mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 00:24:40 +00:00
Event manager priority chaining
listeners can register with a priority to get an event into an ordered stream of listeners
This commit is contained in:
parent
562756a306
commit
299d358d0b
2 changed files with 63 additions and 42 deletions
|
|
@ -79,26 +79,30 @@ bool EventManagerListener::onMessageReceived( StringTableEntry queue, const char
|
||||||
if( subscribers == NULL )
|
if( subscribers == NULL )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (U32 i = 0; i < subscribers->size(); i++)
|
for (U32 i = 0; i < subscribers->size();)
|
||||||
{
|
{
|
||||||
Subscriber* itter = &((*subscribers)[i]);
|
Subscriber& itter = (*subscribers)[i];
|
||||||
if (itter->listener == NULL)
|
|
||||||
|
if (itter.listener == NULL)
|
||||||
{
|
{
|
||||||
(*subscribers).erase(i);
|
subscribers->erase(i);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (!itter->removeFlag)
|
|
||||||
|
if (!itter.removeFlag)
|
||||||
{
|
{
|
||||||
itter->callDepth++;
|
itter.callDepth++;
|
||||||
Con::executef(itter->listener, itter->callback, data);
|
Con::executef(itter.listener, itter.callback, data);
|
||||||
itter->callDepth--;
|
itter.callDepth--;
|
||||||
if (itter->removeFlag && itter->callDepth == 0)
|
|
||||||
|
if (itter.removeFlag && itter.callback == 0)
|
||||||
{
|
{
|
||||||
(*subscribers).erase(i);
|
subscribers->erase(i);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subscribers->size() == 0)
|
i++;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -270,7 +274,7 @@ bool EventManager::postEvent( const char* event, const char* data )
|
||||||
|
|
||||||
// CodeReview [tom, 2/20/2007] The "listener" argument was an IMessageListener,
|
// CodeReview [tom, 2/20/2007] The "listener" argument was an IMessageListener,
|
||||||
// but it was actually used as a SimObject and never a listener. Thus, it is now a SimObject.
|
// but it was actually used as a SimObject and never a listener. Thus, it is now a SimObject.
|
||||||
bool EventManager::subscribe(SimObject *callbackObj, const char* event, const char* callback /*= NULL */)
|
bool EventManager::subscribe(SimObject *callbackObj, const char* event, const char* callback /*= NULL */, S32 priority /*=0*/)
|
||||||
{
|
{
|
||||||
// Make sure the event is valid.
|
// Make sure the event is valid.
|
||||||
if( !isRegisteredEvent( event ) )
|
if( !isRegisteredEvent( event ) )
|
||||||
|
|
@ -300,6 +304,7 @@ bool EventManager::subscribe(SimObject *callbackObj, const char* event, const ch
|
||||||
subscriber.listener = callbackObj;
|
subscriber.listener = callbackObj;
|
||||||
subscriber.event = StringTable->insert( event );
|
subscriber.event = StringTable->insert( event );
|
||||||
subscriber.callback = StringTable->insert( cb );
|
subscriber.callback = StringTable->insert( cb );
|
||||||
|
subscriber.priority = priority;
|
||||||
subscriber.callDepth = 0;
|
subscriber.callDepth = 0;
|
||||||
subscriber.removeFlag = false;
|
subscriber.removeFlag = false;
|
||||||
|
|
||||||
|
|
@ -311,8 +316,22 @@ bool EventManager::subscribe(SimObject *callbackObj, const char* event, const ch
|
||||||
// If the event exists, there should always be a valid subscriber list.
|
// If the event exists, there should always be a valid subscriber list.
|
||||||
AssertFatal( subscribers, "Invalid event subscriber list." );
|
AssertFatal( subscribers, "Invalid event subscriber list." );
|
||||||
|
|
||||||
// Add the subscriber.
|
// Add the subscriber at the appropriate index based on priority.
|
||||||
subscribers->push_back( subscriber );
|
S32 insertIndex = subscribers->size();
|
||||||
|
|
||||||
|
for (S32 i = 0; i < subscribers->size(); i++)
|
||||||
|
{
|
||||||
|
EventManagerListener::Subscriber& cur = (*subscribers)[i];
|
||||||
|
|
||||||
|
if (subscriber.priority > cur.priority)
|
||||||
|
{
|
||||||
|
insertIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribers->insert(insertIndex);
|
||||||
|
(*subscribers)[insertIndex] = subscriber;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -342,10 +361,10 @@ void EventManager::remove(SimObject *cbObj, const char* event)
|
||||||
// Erase the event.
|
// Erase the event.
|
||||||
if( iter->listener == cbObj )
|
if( iter->listener == cbObj )
|
||||||
{
|
{
|
||||||
if (iter->callDepth > 0)
|
if (iter->callDepth > 0)
|
||||||
iter->removeFlag = true;
|
iter->removeFlag = true;
|
||||||
else
|
else
|
||||||
subscribers->erase_fast( iter );
|
subscribers->erase_fast( iter );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -356,21 +375,21 @@ void EventManager::removeAll(SimObject *cbObj)
|
||||||
// Iterate over all events.
|
// Iterate over all events.
|
||||||
for( Vector<StringTableEntry>::const_iterator iter1 = mEvents.begin(); iter1 != mEvents.end(); iter1++ )
|
for( Vector<StringTableEntry>::const_iterator iter1 = mEvents.begin(); iter1 != mEvents.end(); iter1++ )
|
||||||
{
|
{
|
||||||
Vector<EventManagerListener::Subscriber>* subscribers = mListener.mSubscribers.retreive( *iter1 );
|
Vector<EventManagerListener::Subscriber>* subscribers = mListener.mSubscribers.retreive( *iter1 );
|
||||||
if( !subscribers )
|
if( !subscribers )
|
||||||
continue;
|
continue;
|
||||||
for( Vector<EventManagerListener::Subscriber>::iterator iter2 = subscribers->begin(); iter2 != subscribers->end(); iter2++ )
|
for( Vector<EventManagerListener::Subscriber>::iterator iter2 = subscribers->begin(); iter2 != subscribers->end(); iter2++ )
|
||||||
{
|
{
|
||||||
// Erase the event.
|
// Erase the event.
|
||||||
if( iter2->listener == cbObj )
|
if( iter2->listener == cbObj )
|
||||||
{
|
{
|
||||||
if (iter2->callDepth > 0)
|
if (iter2->callDepth > 0)
|
||||||
iter2->removeFlag = true;
|
iter2->removeFlag = true;
|
||||||
else
|
else
|
||||||
subscribers->erase_fast( iter2 );
|
subscribers->erase_fast( iter2 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -460,7 +479,7 @@ DefineEngineMethod( EventManager, postEvent, bool, ( const char * evt, const cha
|
||||||
return object->postEvent( evt, data );
|
return object->postEvent( evt, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod( EventManager, subscribe, bool, ( const char * listenerName, const char * evt, const char * callback ), (""), "( SimObject listener, String event, String callback )\n\n"
|
DefineEngineMethod( EventManager, subscribe, bool, ( const char * listenerName, const char * evt, const char * callback, S32 priority ), ("", 0), "( SimObject listener, String event, String callback, int priority = 0 )\n\n"
|
||||||
"Subscribe a listener to an event.\n"
|
"Subscribe a listener to an event.\n"
|
||||||
"@param listener The listener to subscribe.\n"
|
"@param listener The listener to subscribe.\n"
|
||||||
"@param event The event to subscribe to.\n"
|
"@param event The event to subscribe to.\n"
|
||||||
|
|
@ -475,7 +494,7 @@ DefineEngineMethod( EventManager, subscribe, bool, ( const char * listenerName,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return object->subscribe( cbObj, evt, callback );
|
return object->subscribe( cbObj, evt, callback, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineEngineMethod( EventManager, remove, void, ( const char * listenerName, const char * evt), , "( SimObject listener, String event )\n\n"
|
DefineEngineMethod( EventManager, remove, void, ( const char * listenerName, const char * evt), , "( SimObject listener, String event )\n\n"
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,13 @@ class EventManagerListener : public Dispatcher::IMessageListener
|
||||||
/// Stores subscription information for a subscriber.
|
/// Stores subscription information for a subscriber.
|
||||||
struct Subscriber
|
struct Subscriber
|
||||||
{
|
{
|
||||||
SimObjectPtr< SimObject > listener; ///< The listener object.
|
SimObjectPtr< SimObject > listener; ///< The listener object.
|
||||||
StringTableEntry callback; ///< The callback to execute when the event is triggered.
|
StringTableEntry callback; ///< The callback to execute when the event is triggered.
|
||||||
StringTableEntry event; ///< The event being listened for.
|
StringTableEntry event; ///< The event being listened for.
|
||||||
U32 callDepth;
|
|
||||||
bool removeFlag;
|
S32 priority;
|
||||||
|
U32 callDepth;
|
||||||
|
bool removeFlag;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Subscriber table hashed by event name.
|
/// Subscriber table hashed by event name.
|
||||||
|
|
@ -154,7 +156,7 @@ public:
|
||||||
/// Triggers an event.
|
/// Triggers an event.
|
||||||
bool postEvent( const char* eventName, const char* data );
|
bool postEvent( const char* eventName, const char* data );
|
||||||
/// Adds a subscription to an event.
|
/// Adds a subscription to an event.
|
||||||
bool subscribe( SimObject *callbackObj, const char* event, const char* callback = NULL );
|
bool subscribe( SimObject *callbackObj, const char* event, const char* callback = NULL, S32 priority = 0 );
|
||||||
/// Remove a subscriber from an event.
|
/// Remove a subscriber from an event.
|
||||||
void remove( SimObject *cbObj, const char* event );
|
void remove( SimObject *cbObj, const char* event );
|
||||||
void removeAll( SimObject *cbObj );
|
void removeAll( SimObject *cbObj );
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue