00001 /*************************************************************************** 00002 * * 00003 * (c) Art Tevs, MPI Informatik Saarbruecken * 00004 * mailto: <tevs@mpi-sb.mpg.de> * 00005 * * 00006 * This program is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 2 of the License, or * 00009 * (at your option) any later version. * 00010 * * 00011 ***************************************************************************/ 00012 00013 00014 #ifndef _NR_EVENTMANAGER_H_ 00015 #define _NR_EVENTMANAGER_H_ 00016 00017 /*! 00018 * \defgroup event Event-Management 00019 * 00020 * If you want to start to write a game you should be familar with event 00021 * systems and event based programming. Event system are used to pass events 00022 * between system modules without calling certain functions of that modules. 00023 * So using of events could reduce the dependability of the system components. 00024 * 00025 * In our engine we are trying to improve the normal behaviour of the event 00026 * management system. We do not only use simple events, instead of this we 00027 * mix several techniques like signals, triggers and state machines within the concept 00028 * of events to give the develeoper a possibility to increase the dependecy gap 00029 * between application modules. 00030 * 00031 * The engine does also use name driven event system instead of id driven design. 00032 * This is done for the reasons of readability and expandability. So if new 00033 * event should be added to the system, it can be added by using other name rather 00034 * then to recompile the application by adding new ids. Also using of string based 00035 * names for the vents allows better using of scripting. 00036 * 00037 * New type of events could be easely added through plugins, so the engine must not be 00038 * recompiled. For example: the engine could easely be extended to an input system. 00039 * The input system can fully be programmed as a plugin. To allow a communication 00040 * between the components of the engine and application, the new plugin could 00041 * generate a new type of events, namely "input". Each event listener which is 00042 * registered for hearing the communication channel for the input events will be 00043 * informed if there is a new event. 00044 * 00045 * Our events are priority based. This means that each event does get a priority number 00046 * defining how soon this event should be delivered. In each cycle the application 00047 * running all events/messages comming to a channel will be collected in a priority queue. 00048 * When the EventManager gets updated it tells the channels, that they now can deliver the 00049 * messages to all connected actors. So the events with the highest priority will be 00050 * delivered as first and the messages with the lowest priority will be delivered as last. 00051 * If there is two events of the same priority, so it is not defined which one will be 00052 * delivered as first. 00053 * 00054 * There is also special events having the priority number IMMEDIATE which will 00055 * cause the channel to deliver this message immediately without be stored in the queue. 00056 * This actors will be informed about this events as soon as the event is triggered. 00057 * 00058 * C++ does not provide any possibility to write the event management typesafe without 00059 * big circumastances. There are some techniques, but this will end up in a big 00060 * code plus a lot of function calls if to provide you the derived class instance instead 00061 * of the base Event class. However we will try to give you the possibility of using 00062 * your own event types derived from the base class in a controlled typesafe way. 00063 * This means that if you handle correctly, so you will never cast to any wrong 00064 * class by handling events. 00065 * 00066 * <hr> 00067 * Another problem which we have to solve is: How to share event messages between 00068 * plugins and application. Assume you compiled your application with the nrEngine 00069 * library linked in. Then if you start the app you use the same memory mapping like 00070 * the engine does. It means sending now events through the nrEngine's subsystem to 00071 * your application is not a big problem. However if you now use plugins which are 00072 * dynamic libraries, which are linked dynamicaly while your app is running, this 00073 * approach could not work so easy. it means you are still able to send events, but 00074 * you now can not convert an event to a type which is provided by the plugin. 00075 * (i.e. plugin defines new type of events (NewEvent). Plugin create an instance of 00076 * this class and send it to your application, you now not able to cast base class 00077 * Event to this NewEvent class). Problem of sharing type information between modules. 00078 * 00079 * One solution were to forbidd plugins to send any new type of events which was 00080 * not declared in the engine before. This solution might work, but then we loose 00081 * to generality of our engine, because then we have to implement all things which 00082 * are needed for properly use in the engine (graphics, inputs, ...) 00083 * 00084 * The other solution is to provide the engine TODO !!!!!! 00085 **/ 00086 00087 //---------------------------------------------------------------------------------- 00088 // Includes 00089 //---------------------------------------------------------------------------------- 00090 #include "Prerequisities.h" 00091 #include "ITask.h" 00092 00093 namespace nrEngine{ 00094 00095 00096 //! Main class providing the event messaging system 00097 /** 00098 * EventManager is a class managing the whole event communication 00099 * system in our engine. The system can be thought as a message bus 00100 * where all senders and recievers are connected to. They send/recieve 00101 * messages through this bus. In the message bus we define message channels 00102 * which suppose to send/recieve only events/messages of a certain type. 00103 * 00104 * \ingroup event 00105 **/ 00106 class _NRExport EventManager: public ITask { 00107 public: 00108 00109 /** 00110 * Create a new event messaging channel. Any listener 00111 * connected to this channel will recieve only the messages 00112 * coming from senders connected to this channel. Any state change 00113 * of the channel will produce a new notice event to give the 00114 * listeners a possibility to react to the new state. 00115 * 00116 * @param name Unique name for this channel 00117 * @return either OK or an error code 00118 **/ 00119 Result createChannel(const std::string& name); 00120 00121 /** 00122 * Delete a certain communication channel. 00123 * All actors connected to the channel are getting disconnected 00124 * from the channel. 00125 * 00126 * @param name Unique name for the channel to remove 00127 **/ 00128 Result removeChannel(const std::string& name); 00129 00130 /** 00131 * Get a channel by its name 00132 * @return smart pointer to the channel 00133 **/ 00134 SharedPtr<EventChannel> getChannel(const std::string& name); 00135 00136 /** 00137 * Send a new event message to the channel. The priority number 00138 * of the event will be used to check if the message should be 00139 * send immediately or if it should go to the channel queue as first. 00140 * 00141 * @param name Unique channel name, where to emit the event (empty for all channels) 00142 * @param event SMart pointer on event to be emited 00143 **/ 00144 Result emit(const std::string& name, SharedPtr<Event> event); 00145 00146 /** 00147 * Same as emit() but this will emit messages to the system specific 00148 * default channel. This channel is used by the engine to establish 00149 * a communication between system components. 00150 * 00151 * NOTE: In next version this channel will be secured, so user are 00152 * not allowed to send messages here anymore 00153 **/ 00154 Result emitSystem(SharedPtr<Event> event); 00155 00156 /** 00157 * Inherited method from the ITask interface. Our event manager 00158 * is updated in each cycle to allow the channels to provide events 00159 * to all connected parties. 00160 **/ 00161 Result updateTask(); 00162 00163 /** 00164 * Call this function if you prefer to create a new event object 00165 * from all registerd factories. The function will go through all 00166 * registered factories and ask them which does support the given 00167 * event type. If one could be found, so create it. 00168 **/ 00169 SharedPtr<Event> createEvent(const std::string& eventType); 00170 00171 /** 00172 * Register a new event factory. The given event factory will be 00173 * stored in a list. The factory can later be used to create instancies 00174 * of certain event types. 00175 * 00176 * @param name Unique name of a factory 00177 * @param factory Smart pointer containing the factory object 00178 **/ 00179 Result registerFactory(const std::string& name, SharedPtr<EventFactory> factory); 00180 00181 /** 00182 * Delete a registered factory from the list. 00183 **/ 00184 Result removeFactory(const std::string& name); 00185 00186 #if 0 00187 /** 00188 * Create and emit a message through a channel. 00189 * @param channel Channel name where to emit 00190 * @return Result of emit() method 00191 **/ 00192 template<class EventT> 00193 Result createEmit(const std::string& channel, void* param = NULL) 00194 { 00195 SharedPtr<Event> msg(new EventT); 00196 return emit(channel, msg); 00197 } 00198 #endif 00199 00200 private: 00201 00202 //! Only engine is allowed to create the instance 00203 friend class Engine; 00204 00205 /** 00206 * Create default system specific communication channel. 00207 * This channel will be used to allow communication between 00208 * system components. 00209 * 00210 * In the next version of nrEngine we should secure this channel 00211 * by flags, so user applications are not allowed to hear or to emit 00212 * messages in this channel!!! 00213 **/ 00214 EventManager(); 00215 00216 //! Close all event channels and release used memory 00217 ~EventManager(); 00218 00219 //! Database representing the connection channels by their names 00220 typedef std::map<std::string, SharedPtr<EventChannel> > ChannelDatabase; 00221 00222 //! Store the database in this variable 00223 ChannelDatabase mChannelDb; 00224 00225 //! Here we do store event factories able to create new instancies 00226 typedef std::map<std::string, SharedPtr<EventFactory> > FactoryDatabase; 00227 00228 //! Variable to hold the data 00229 FactoryDatabase mFactoryDb; 00230 00231 }; 00232 00233 }; // end namespace 00234 00235 #endif