//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #ifndef _EVENTMANAGER_H_ #define _EVENTMANAGER_H_ #ifndef _CONSOLE_H_ #include "console/console.h" #endif #ifndef _DISPATCHER_H_ #include "util/messaging/dispatcher.h" #endif #ifndef _TSIMPLEHASHTABLE_H #include "core/tSimpleHashTable.h" #endif //----------------------------------------------------------------------------- /// Listener class used by the EventManager to dispatch messages to specific /// callbacks. //----------------------------------------------------------------------------- class EventManagerListener : public Dispatcher::IMessageListener { friend class EventManager; /// Stores subscription information for a subscriber. struct Subscriber { SimObjectPtr< SimObject > listener; ///< The listener object. StringTableEntry callback; ///< The callback to execute when the event is triggered. StringTableEntry event; ///< The event being listened for. U32 callDepth; bool removeFlag; }; /// Subscriber table hashed by event name. SimpleHashTable< Vector > mSubscribers; public: // Ensure that the subscriber map doesn't use case-sensitive string comparisons. EventManagerListener(): mSubscribers(64, false) {} /// Called by the EventManager queue when an event is triggered. Calls all listeners subscribed to the triggered event. virtual bool onMessageReceived( StringTableEntry queue, const char* event, const char* data ); virtual bool onMessageObjectReceived( StringTableEntry queue, Message *msg ) { return true; }; }; /// @addtogroup msgsys Message System // @{ //----------------------------------------------------------------------------- /// The EventManager class is a wrapper for the standard messaging system. It /// provides functionality for management of event queues, events, and /// subscriptions. /// /// Creating an EventManager is as simple as calling new EventManager /// and specifying a queue name. /// /// Example Usage: /// /// @code /// // Create the EventManager. /// $MyEventManager = new EventManager() { queue = "MyEventManager"; }; /// /// // Create an event. /// $MyEventManager.registerEvent( "SomeCoolEvent" ); /// /// // Create a listener and subscribe. /// $MyListener = new ScriptMsgListener() { class = MyListener; }; /// $MyEventManager.subscribe( $MyListener, "SomeCoolEvent" ); /// /// function MyListener::onSomeCoolEvent( %this, %data ) /// { /// echo( "onSomeCoolEvent Triggered" ); /// } /// /// // Trigger the event. /// $MyEventManager.postEvent( "SomeCoolEvent", "Data" ); /// @endcode //----------------------------------------------------------------------------- class EventManager : public SimObject { typedef SimObject Parent; private: /// The name of the message queue. StringTableEntry mQueue; /// Registered events. Vector mEvents; /// The event listener. Listens for all events and dispatches them to the appropriate subscribers. EventManagerListener mListener; /// List of all EventManagers. static Vector smEventManagers; /// Sets the message queue. static bool _setMessageQueue( void *obj, const char *index, const char *data ) { static_cast( obj )->setMessageQueue( data ); return false; }; public: DECLARE_CONOBJECT( EventManager ); EventManager(); virtual ~EventManager(); static void initPersistFields(); /// @name Properties /// @{ StringTableEntry getMessageQueue() const { return mQueue; } void setMessageQueue( const char* queue ); /// @} /// @name Event Management /// @{ /// Checks if an event is registered. bool isRegisteredEvent( const char* eventName ); /// Registers an event. bool registerEvent( const char* eventName ); /// Removes an event. void unregisterEvent( const char* eventName ); /// Removes all events. void unregisterAllEvents(); /// Triggers an event. bool postEvent( const char* eventName, const char* data ); /// Adds a subscription to an event. bool subscribe( SimObject *callbackObj, const char* event, const char* callback = NULL ); /// Remove a subscriber from an event. void remove( SimObject *cbObj, const char* event ); void removeAll( SimObject *cbObj ); /// @} /// @name Debug Output /// @{ /// Prints all registered events to the console. void dumpEvents(); /// Prints all subscribers to the console. void dumpSubscribers(); /// Prints subscribers to a specific event to the console. void dumpSubscribers( const char* event ); /// @} /// @name Event Manager Tracking /// @{ /// Adds an EventManager. static void addEventManager( EventManager* em ) { smEventManagers.push_back( em ); }; /// Removes an EventManager. static void removeEventManager( EventManager* em ) { for( Vector::iterator iter = smEventManagers.begin(); iter != smEventManagers.end(); iter++ ) { if( *iter == em ) { smEventManagers.erase_fast( iter ); break; } } }; /// Retrieves an EventManager. static EventManager* getEventManager( const char* name ) { StringTableEntry queue = StringTable->insert( name ); for( Vector::iterator iter = smEventManagers.begin(); iter != smEventManagers.end(); iter++ ) { if( ( *iter )->mQueue == queue ) return *iter; } return NULL; }; /// Prints all the EventManagers to the console. static void printEventManagers() { for( Vector::iterator iter = smEventManagers.begin(); iter != smEventManagers.end(); iter++ ) ( *iter )->dumpSubscribers(); } /// @} }; // @} #endif // _EVENTMANAGER_H_