Browse Source

EventListener refactoring for safety.
ScriptEventListener simplification.

Lasse Öörni 15 years ago
parent
commit
fa7cf0041f

+ 136 - 55
Engine/Common/EventListener.cpp

@@ -33,10 +33,13 @@
 
 
 static VariantMap noEventData;
 static VariantMap noEventData;
 
 
-std::map<StringHash, std::list<EventListener*> > EventListener::sEventListeners;
-std::map<std::pair<EventListener*, StringHash>, std::list<EventListener*> > EventListener::sSpecificEventListeners;
+std::map<StringHash, std::vector<EventListener*> > EventListener::sEventListeners;
+std::map<std::pair<EventListener*, StringHash>, std::vector<EventListener*> > EventListener::sSpecificEventListeners;
 
 
-std::vector<EventListener*> eventSender;
+std::vector<EventListener*> eventSenders;
+std::set<StringHash> dirtyEventListeners;
+std::set<std::pair<EventListener*, StringHash> > dirtySpecificEventListeners;
+EventHandlerInvoker* invoker = 0;
 
 
 EventListener::EventListener()
 EventListener::EventListener()
 {
 {
@@ -45,24 +48,27 @@ EventListener::EventListener()
 EventListener::~EventListener()
 EventListener::~EventListener()
 {
 {
     // Check if event sender is destroyed during event handling
     // Check if event sender is destroyed during event handling
-    for (unsigned i = 0; i < eventSender.size(); ++i)
+    for (unsigned i = 0; i < eventSenders.size(); ++i)
     {
     {
-        if (eventSender[i] == this)
-            eventSender[i] = 0;
+        if (eventSenders[i] == this)
+            eventSenders[i] = 0;
     }
     }
     
     
     unsubscribeFromAllEvents();
     unsubscribeFromAllEvents();
     
     
     // Remove from all specific event listeners
     // Remove from all specific event listeners
-    for (std::map<std::pair<EventListener*, StringHash>, std::list<EventListener*> >::iterator i = sSpecificEventListeners.begin();
+    for (std::map<std::pair<EventListener*, StringHash>, std::vector<EventListener*> >::iterator i = sSpecificEventListeners.begin();
         i != sSpecificEventListeners.end();)
         i != sSpecificEventListeners.end();)
     {
     {
-        std::map<std::pair<EventListener*, StringHash>, std::list<EventListener*> >::iterator current = i++;
+        std::map<std::pair<EventListener*, StringHash>, std::vector<EventListener*> >::iterator current = i++;
         if (current->first.first == this)
         if (current->first.first == this)
         {
         {
-            std::list<EventListener*>& listeners = current->second;
-            for (std::list<EventListener*>::iterator j = listeners.begin(); j != listeners.end(); ++j)
-                (*j)->removeSpecificEventHandlers(this);
+            std::vector<EventListener*>& listeners = current->second;
+            for (std::vector<EventListener*>::iterator j = listeners.begin(); j != listeners.end(); ++j)
+            {
+                if (*j)
+                    (*j)->removeSpecificEventHandlers(this);
+            }
             sSpecificEventListeners.erase(current);
             sSpecificEventListeners.erase(current);
         }
         }
     }
     }
@@ -75,13 +81,17 @@ void EventListener::onEvent(EventListener* sender, StringHash eventType, Variant
         std::make_pair(sender, eventType));
         std::make_pair(sender, eventType));
     if (i != mSpecificEventHandlers.end())
     if (i != mSpecificEventHandlers.end())
     {
     {
+        invoker = i->second;
         i->second->invoke(eventType, eventData);
         i->second->invoke(eventType, eventData);
         return;
         return;
     }
     }
     
     
     std::map<StringHash, EventHandlerInvoker*>::const_iterator j = mEventHandlers.find(eventType);
     std::map<StringHash, EventHandlerInvoker*>::const_iterator j = mEventHandlers.find(eventType);
     if (j != mEventHandlers.end())
     if (j != mEventHandlers.end())
+    {
+        invoker = j->second;
         j->second->invoke(eventType, eventData);
         j->second->invoke(eventType, eventData);
+    }
 }
 }
 
 
 void EventListener::subscribeToEvent(StringHash eventType, EventHandlerInvoker* handler)
 void EventListener::subscribeToEvent(StringHash eventType, EventHandlerInvoker* handler)
@@ -99,8 +109,8 @@ void EventListener::subscribeToEvent(StringHash eventType, EventHandlerInvoker*
     
     
     mEventHandlers[eventType] = handler;
     mEventHandlers[eventType] = handler;
     
     
-    std::list<EventListener*>& listeners = sEventListeners[eventType];
-    for (std::list<EventListener*>::const_iterator j = listeners.begin(); j != listeners.end(); ++j)
+    std::vector<EventListener*>& listeners = sEventListeners[eventType];
+    for (std::vector<EventListener*>::const_iterator j = listeners.begin(); j != listeners.end(); ++j)
     {
     {
         // Check if already registered
         // Check if already registered
         if (*j == this)
         if (*j == this)
@@ -133,8 +143,8 @@ void EventListener::subscribeToEvent(EventListener* sender, StringHash eventType
     
     
     mSpecificEventHandlers[combination] = handler;
     mSpecificEventHandlers[combination] = handler;
     
     
-    std::list<EventListener*>& listeners = sSpecificEventListeners[combination];
-    for (std::list<EventListener*>::const_iterator j = listeners.begin(); j != listeners.end(); ++j)
+    std::vector<EventListener*>& listeners = sSpecificEventListeners[combination];
+    for (std::vector<EventListener*>::const_iterator j = listeners.begin(); j != listeners.end(); ++j)
     {
     {
         // Check if already registered
         // Check if already registered
         if (*j == this)
         if (*j == this)
@@ -226,78 +236,81 @@ void EventListener::sendEvent(StringHash eventType, VariantMap& eventData)
 {
 {
     std::set<EventListener*> processed;
     std::set<EventListener*> processed;
     
     
-    eventSender.push_back(this);
+    beginSendEvent();
     
     
     // Check first the specific event listeners
     // Check first the specific event listeners
-    std::map<std::pair<EventListener*, StringHash>, std::list<EventListener*> >::const_iterator i = sSpecificEventListeners.find(
+    std::map<std::pair<EventListener*, StringHash>, std::vector<EventListener*> >::const_iterator i = sSpecificEventListeners.find(
         std::make_pair(this, eventType));
         std::make_pair(this, eventType));
     if (i != sSpecificEventListeners.end())
     if (i != sSpecificEventListeners.end())
     {
     {
-        const std::list<EventListener*>& listeners = i->second;
-        for (std::list<EventListener*>::const_iterator j = listeners.begin(); j != listeners.end();)
+        const std::vector<EventListener*>& listeners = i->second;
+        for (unsigned j = 0; j < listeners.size(); ++j)
         {
         {
-            // Make a copy of the iterator, because the listener might remove itself as a response
-            std::list<EventListener*>::const_iterator current = j++;
-            processed.insert(*current);
-            (*current)->onEvent(this, eventType, eventData);
-            // If sending the event caused self to be destroyed, exit immediately!
-            if (getEventSender() != this)
+            EventListener* listener = listeners[j];
+            if (listener)
             {
             {
-                eventSender.pop_back();
-                return;
+                processed.insert(listener);
+                listener->onEvent(this, eventType, eventData);
+                // If handling the event caused self to be destroyed, exit immediately!
+                if (getEventSender() != this)
+                {
+                    endSendEvent();
+                    return;
+                }
             }
             }
         }
         }
     }
     }
     
     
     // Then the non-specific listeners
     // Then the non-specific listeners
-    std::map<StringHash, std::list<EventListener*> >::const_iterator j = sEventListeners.find(eventType);
+    std::map<StringHash, std::vector<EventListener*> >::const_iterator j = sEventListeners.find(eventType);
     if (j != sEventListeners.end())
     if (j != sEventListeners.end())
     {
     {
-        const std::list<EventListener*>& listeners = j->second;
+        const std::vector<EventListener*>& listeners = j->second;
         if (processed.empty())
         if (processed.empty())
         {
         {
-            for (std::list<EventListener*>::const_iterator k = listeners.begin(); k != listeners.end();)
+            for (unsigned k = 0; k < listeners.size(); ++k)
             {
             {
-                std::list<EventListener*>::const_iterator current = k++;
-                (*current)->onEvent(this, eventType, eventData);
-                if (getEventSender() != this)
+                EventListener* listener = listeners[k];
+                if (listener)
                 {
                 {
-                    eventSender.pop_back();
-                    return;
+                    listener->onEvent(this, eventType, eventData);
+                    if (getEventSender() != this)
+                    {
+                        endSendEvent();
+                        return;
+                    }
                 }
                 }
             }
             }
         }
         }
         else
         else
         {
         {
             // If there were specific listeners, check that the event is not sent doubly to them
             // If there were specific listeners, check that the event is not sent doubly to them
-            for (std::list<EventListener*>::const_iterator k = listeners.begin(); k != listeners.end();)
+            for (unsigned k = 0; k < listeners.size(); ++k)
             {
             {
-                if (processed.find(*k) == processed.end())
+                EventListener* listener = listeners[k];
+                if ((listener) && (processed.find(listener) == processed.end()))
                 {
                 {
-                    std::list<EventListener*>::const_iterator current = k++;
-                    (*current)->onEvent(this, eventType, eventData);
+                    listener->onEvent(this, eventType, eventData);
                     if (getEventSender() != this)
                     if (getEventSender() != this)
                     {
                     {
-                        eventSender.pop_back();
+                        endSendEvent();
                         return;
                         return;
                     }
                     }
                 }
                 }
-                else
-                    ++k;
             }
             }
         }
         }
     }
     }
     
     
-    eventSender.pop_back();
+    endSendEvent();
 }
 }
 
 
 void EventListener::sendEvent(EventListener* receiver, StringHash eventType)
 void EventListener::sendEvent(EventListener* receiver, StringHash eventType)
 {
 {
     if (receiver)
     if (receiver)
     {
     {
-        eventSender.push_back(this);
+        beginSendEvent();
         receiver->onEvent(this, eventType, noEventData);
         receiver->onEvent(this, eventType, noEventData);
-        eventSender.pop_back();
+        endSendEvent();
     }
     }
 }
 }
 
 
@@ -305,9 +318,9 @@ void EventListener::sendEvent(EventListener* receiver, StringHash eventType, Var
 {
 {
     if (receiver)
     if (receiver)
     {
     {
-        eventSender.push_back(this);
+        beginSendEvent();
         receiver->onEvent(this, eventType, eventData);
         receiver->onEvent(this, eventType, eventData);
-        eventSender.pop_back();
+        endSendEvent();
     }
     }
 }
 }
 
 
@@ -337,12 +350,19 @@ void EventListener::removeSpecificEventHandlers(EventListener* sender)
 
 
 void EventListener::removeEventListener(StringHash eventType)
 void EventListener::removeEventListener(StringHash eventType)
 {
 {
-    std::list<EventListener*>& listeners = sEventListeners[eventType];
-    for (std::list<EventListener*>::iterator i = listeners.begin(); i != listeners.end(); ++i)
+    std::vector<EventListener*>& listeners = sEventListeners[eventType];
+    for (std::vector<EventListener*>::iterator i = listeners.begin(); i != listeners.end(); ++i)
     {
     {
         if (*i == this)
         if (*i == this)
         {
         {
-            listeners.erase(i);
+            // If no event handling going on, can erase the listener. Otherwise reset the pointer and clean up later
+            if (eventSenders.empty())
+                listeners.erase(i);
+            else
+            {
+                *i = 0;
+                dirtyEventListeners.insert(eventType);
+            }
             return;
             return;
         }
         }
     }
     }
@@ -350,21 +370,82 @@ void EventListener::removeEventListener(StringHash eventType)
 
 
 void EventListener::removeEventListener(EventListener* sender, StringHash eventType)
 void EventListener::removeEventListener(EventListener* sender, StringHash eventType)
 {
 {
-    std::list<EventListener*>& listeners = sSpecificEventListeners[std::make_pair(sender, eventType)];
-    for (std::list<EventListener*>::iterator i = listeners.begin(); i != listeners.end(); ++i)
+    std::pair<EventListener*, StringHash> combination(sender, eventType);
+    std::vector<EventListener*>& listeners = sSpecificEventListeners[combination];
+    for (std::vector<EventListener*>::iterator i = listeners.begin(); i != listeners.end(); ++i)
     {
     {
         if (*i == this)
         if (*i == this)
         {
         {
-            listeners.erase(i);
+            if (eventSenders.empty())
+                listeners.erase(i);
+            else
+            {
+                *i = 0;
+                dirtySpecificEventListeners.insert(combination);
+            }
             return;
             return;
         }
         }
     }
     }
 }
 }
 
 
+EventHandlerInvoker* EventListener::getInvoker()
+{
+    return invoker;
+}
+
+void EventListener::beginSendEvent()
+{
+    eventSenders.push_back(this);
+}
+
+void EventListener::endSendEvent()
+{
+    eventSenders.pop_back();
+    
+    // If event handling has ended, clean up listeners that were removed during event handling
+    if (eventSenders.empty())
+        cleanupEventListeners();
+}
+
+void EventListener::cleanupEventListeners()
+{
+    if (!dirtySpecificEventListeners.empty())
+    {
+        for (std::set<std::pair<EventListener*, StringHash> >::iterator i = dirtySpecificEventListeners.begin(); i != dirtySpecificEventListeners.end(); ++i)
+        {
+            std::vector<EventListener*>& listeners = sSpecificEventListeners[*i];
+            for (std::vector<EventListener*>::iterator j = listeners.begin(); j != listeners.end();)
+            {
+                if (*j == 0)
+                    j = listeners.erase(j);
+                else
+                    ++j;
+            }
+        }
+        dirtySpecificEventListeners.clear();
+    }
+    
+    if (!dirtyEventListeners.empty())
+    {
+        for (std::set<StringHash>::iterator i = dirtyEventListeners.begin(); i != dirtyEventListeners.end(); ++i)
+        {
+            std::vector<EventListener*>& listeners = sEventListeners[*i];
+            for (std::vector<EventListener*>::iterator j = listeners.begin(); j != listeners.end();)
+            {
+                if (*j == 0)
+                    j = listeners.erase(j);
+                else
+                    ++j;
+            }
+        }
+        dirtyEventListeners.clear();
+    }
+}
+
 EventListener* getEventSender()
 EventListener* getEventSender()
 {
 {
-    if (eventSender.size())
-        return eventSender.back();
+    if (eventSenders.size())
+        return eventSenders.back();
     else
     else
         return 0;
         return 0;
 }
 }

+ 34 - 4
Engine/Common/EventListener.h

@@ -36,7 +36,15 @@ class EventHandlerInvoker
 public:
 public:
     //! Construct with specified listener
     //! Construct with specified listener
     EventHandlerInvoker(EventListener* listener) :
     EventHandlerInvoker(EventListener* listener) :
-        mListener(listener)
+        mListener(listener),
+        mUserData(0)
+    {
+    }
+    
+    //! Construct with specified listener and userdata
+    EventHandlerInvoker(EventListener* listener, void* userData) :
+        mListener(listener),
+        mUserData(userData)
     {
     {
     }
     }
     
     
@@ -48,10 +56,14 @@ public:
     
     
     //! Return event listener
     //! Return event listener
     EventListener* getListener() const { return mListener; }
     EventListener* getListener() const { return mListener; }
+    //! Return userdata
+    void* getUserData() const { return mUserData; }
     
     
 protected:
 protected:
     //! Event listener
     //! Event listener
     EventListener* mListener;
     EventListener* mListener;
+    //! Userdata
+    void* mUserData;
     
     
 private:
 private:
     //! Prevent copy construction
     //! Prevent copy construction
@@ -73,6 +85,13 @@ public:
     {
     {
     }
     }
     
     
+    //! Construct with listener and function pointers and userdata
+    EventHandlerInvokerImpl(T* listener, HandlerFunctionPtr handler, void* userData) :
+        EventHandlerInvoker(listener, userData),
+        mHandler(handler)
+    {
+    }
+    
     //! Invoke event handler
     //! Invoke event handler
     virtual void invoke(StringHash eventType, VariantMap& eventData)
     virtual void invoke(StringHash eventType, VariantMap& eventData)
     {
     {
@@ -91,6 +110,7 @@ private:
 };
 };
 
 
 #define EVENT_HANDLER(classname, function) (new EventHandlerInvokerImpl<classname>(this, &classname::function))
 #define EVENT_HANDLER(classname, function) (new EventHandlerInvokerImpl<classname>(this, &classname::function))
+#define EVENT_HANDLER_USERDATA(classname, function, userdata) (new EventHandlerInvokerImpl<classname>(this, &classname::function, userdata))
 
 
 //! Event listener
 //! Event listener
 class EventListener
 class EventListener
@@ -143,16 +163,26 @@ protected:
     //! Event handlers for specific senders' events
     //! Event handlers for specific senders' events
     std::map<std::pair<EventListener*, StringHash>, EventHandlerInvoker*> mSpecificEventHandlers;
     std::map<std::pair<EventListener*, StringHash>, EventHandlerInvoker*> mSpecificEventHandlers;
     
     
+    //! Return last event handler invoker. Only valid during onEvent()
+    static EventHandlerInvoker* getInvoker();
+    
 private:
 private:
+    //! Begin event handling. Save self as sender
+    void beginSendEvent();
+    //! End event handling. Remove self and clean up event listeners if possible and necessary
+    void endSendEvent();
+    //! Cleanup event listeners removed while handling an event
+    void cleanupEventListeners();
+    
     //! Prevent copy construction
     //! Prevent copy construction
     EventListener(const EventListener& rhs);
     EventListener(const EventListener& rhs);
     //! Prevent assignment
     //! Prevent assignment
     EventListener& operator = (const EventListener& rhs);
     EventListener& operator = (const EventListener& rhs);
-    
+
     //! Event listeners for non-specific events
     //! Event listeners for non-specific events
-    static std::map<StringHash, std::list<EventListener*> > sEventListeners;
+    static std::map<StringHash, std::vector<EventListener*> > sEventListeners;
     //! Event listeners for specific senders' events
     //! Event listeners for specific senders' events
-    static std::map<std::pair<EventListener*, StringHash>, std::list<EventListener*> > sSpecificEventListeners;
+    static std::map<std::pair<EventListener*, StringHash>, std::vector<EventListener*> > sSpecificEventListeners;
 };
 };
 
 
 //! Return event sender. Only non-null during the event handling
 //! Return event sender. Only non-null during the event handling

+ 3 - 3
Engine/Engine/RegisterCommon.cpp

@@ -670,21 +670,21 @@ static void UnsubscribeFromEvent(const std::string& eventType)
 {
 {
     ScriptEventListener* listener = getScriptContextEventListener();
     ScriptEventListener* listener = getScriptContextEventListener();
     if (listener)
     if (listener)
-        listener->removeEventHandler(StringHash(eventType));
+        listener->unsubscribeFromEvent(StringHash(eventType));
 }
 }
 
 
 static void UnsubscribeFromSenderEvent(EventListener* sender, const std::string& eventType)
 static void UnsubscribeFromSenderEvent(EventListener* sender, const std::string& eventType)
 {
 {
     ScriptEventListener* listener = getScriptContextEventListener();
     ScriptEventListener* listener = getScriptContextEventListener();
     if (listener)
     if (listener)
-        listener->removeEventHandler(sender, StringHash(eventType));
+        listener->unsubscribeFromEvent(sender, StringHash(eventType));
 }
 }
 
 
 static void UnsubscribeFromSenderEvents(EventListener* sender)
 static void UnsubscribeFromSenderEvents(EventListener* sender)
 {
 {
     ScriptEventListener* listener = getScriptContextEventListener();
     ScriptEventListener* listener = getScriptContextEventListener();
     if (listener)
     if (listener)
-        listener->removeEventHandlers(sender);
+        listener->unsubscribeFromEvents(sender);
 }
 }
 
 
 static void UnsubscribeFromAllEvents()
 static void UnsubscribeFromAllEvents()

+ 11 - 50
Engine/Script/ScriptEventListener.cpp

@@ -24,60 +24,21 @@
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "ScriptEventListener.h"
 #include "ScriptEventListener.h"
 
 
-void ScriptEventListener::removeEventHandler(StringHash eventType)
+void ScriptEventListener::removeAllEventHandlers()
 {
 {
-    for (std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator i = mSpecificEventHandlers.begin(); i !=
-        mSpecificEventHandlers.end();)
+    // If event handlers have userdata defined, they should be scripted and thus can be removed
+    // Do not remove internal event handlers, such as ScriptInstance's update handlers
+    for (std::map<std::pair<EventListener*, StringHash>, EventHandlerInvoker*>::iterator i = mSpecificEventHandlers.begin(); i != mSpecificEventHandlers.end();)
     {
     {
-        std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator current = i++;
-        if (current->first.second == eventType)
-            mSpecificEventHandlers.erase(current);
+        std::map<std::pair<EventListener*, StringHash>, EventHandlerInvoker*>::iterator current = i++;
+        if (current->second->getUserData())
+            unsubscribeFromEvent(current->first.first, current->first.second);
     }
     }
     
     
-    std::map<StringHash, asIScriptFunction*>::iterator i = mEventHandlers.find(eventType);
-    if (i != mEventHandlers.end())
-        mEventHandlers.erase(i);
-    
-    unsubscribeFromEvent(eventType);
-}
-
-void ScriptEventListener::removeEventHandler(EventListener* sender, StringHash eventType)
-{
-    std::pair<EventListener*, StringHash> combination = std::make_pair(sender, eventType);
-    
-    std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator i = mSpecificEventHandlers.find(combination);
-    if (i != mSpecificEventHandlers.end())
+    for (std::map<StringHash, EventHandlerInvoker*>::iterator i = mEventHandlers.begin(); i != mEventHandlers.end();)
     {
     {
-        mSpecificEventHandlers.erase(i);
-        unsubscribeFromEvent(sender, eventType);
+        std::map<StringHash, EventHandlerInvoker*>::iterator current = i++;
+        if (current->second->getUserData())
+            unsubscribeFromEvent(current->first);
     }
     }
 }
 }
-
-void ScriptEventListener::removeEventHandlers(EventListener* sender)
-{
-    for (std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator i = mSpecificEventHandlers.begin(); i !=
-        mSpecificEventHandlers.end();)
-    {
-        std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator current = i++;
-        if (current->first.first == sender)
-            mSpecificEventHandlers.erase(current);
-    }
-    
-    unsubscribeFromEvents(sender);
-}
-
-void ScriptEventListener::removeAllEventHandlers()
-{
-    // Note: we can not simply call unsubscribeFromAllEvents(), as for example ScriptInstance has its own internal
-    // scene update event handlers, which must not be unsubscribed
-    for (std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator i = mSpecificEventHandlers.begin(); i !=
-        mSpecificEventHandlers.end(); ++i)
-        unsubscribeFromEvent(i->first.first, i->first.second);
-    
-    mSpecificEventHandlers.clear();
-    
-    for (std::map<StringHash, asIScriptFunction*>::iterator i = mEventHandlers.begin(); i != mEventHandlers.end(); ++i)
-        unsubscribeFromEvent(i->first);
-    
-    mEventHandlers.clear();
-}

+ 3 - 15
Engine/Script/ScriptEventListener.h

@@ -31,24 +31,12 @@ class asIScriptFunction;
 class ScriptEventListener : public EventListener
 class ScriptEventListener : public EventListener
 {
 {
 public:
 public:
-    //! Add an event handler. Called by script exposed version of subscribeToEvent()
+    //! Add a scripted event handler. Called by script exposed version of subscribeToEvent()
     virtual void addEventHandler(StringHash eventType, const std::string& handlerName) = 0;
     virtual void addEventHandler(StringHash eventType, const std::string& handlerName) = 0;
-    //! Add an event handler for a specific sender. Called by script exposed version of subscribeToEvent()
+    //! Add a scripted event handler for a specific sender. Called by script exposed version of subscribeToEvent()
     virtual void addEventHandler(EventListener* sender, StringHash eventType, const std::string& handlerName) = 0;
     virtual void addEventHandler(EventListener* sender, StringHash eventType, const std::string& handlerName) = 0;
-    //! Remove an event handler. Called by script exposed version of unsubcribeFromEvent()
-    void removeEventHandler(StringHash eventType);
-    //! Remove an event handler for a specific sender. Called by script exposed version of unsubscribeFromEvent();
-    void removeEventHandler(EventListener* sender, StringHash eventType);
-    //! Remove all event handlers for a specific sender. Called by script exposed version of unsubscribeFromEvents();
-    void removeEventHandlers(EventListener* sender);
-    //! Remove all event handlers. Called by script exposed version of unsubscribeFromAllEvents()
+    //! Remove all scripted event handlers. Called by script exposed version of unsubscribeFromAllEvents()
     void removeAllEventHandlers();
     void removeAllEventHandlers();
-    
-protected:
-    //! Pointers to event handler functions
-    std::map<StringHash, asIScriptFunction*> mEventHandlers;
-    //! Pointers to event handler functions for specific event senders
-    std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*> mSpecificEventHandlers;
 };
 };
 
 
 #endif // SCRIPT_SCRIPTEVENTLISTENER_H
 #endif // SCRIPT_SCRIPTEVENTLISTENER_H

+ 4 - 15
Engine/Script/ScriptFile.cpp

@@ -110,8 +110,7 @@ void ScriptFile::addEventHandler(StringHash eventType, const std::string& handle
         return;
         return;
     }
     }
     
     
-    subscribeToEvent(eventType, EVENT_HANDLER(ScriptFile, handleScriptEvent));
-    mEventHandlers[eventType] = function;
+    subscribeToEvent(eventType, EVENT_HANDLER_USERDATA(ScriptFile, handleScriptEvent, (void*)function));
 }
 }
 
 
 void ScriptFile::addEventHandler(EventListener* sender, StringHash eventType, const std::string& handlerName)
 void ScriptFile::addEventHandler(EventListener* sender, StringHash eventType, const std::string& handlerName)
@@ -133,8 +132,7 @@ void ScriptFile::addEventHandler(EventListener* sender, StringHash eventType, co
         return;
         return;
     }
     }
     
     
-    subscribeToEvent(sender, eventType, EVENT_HANDLER(ScriptFile, handleSpecificScriptEvent));
-    mSpecificEventHandlers[std::make_pair(sender, eventType)] = function;
+    subscribeToEvent(sender, eventType, EVENT_HANDLER_USERDATA(ScriptFile, handleSpecificScriptEvent, (void*)function));
 }
 }
 
 
 bool ScriptFile::execute(const std::string& declaration, const std::vector<Variant>& parameters, bool unprepare)
 bool ScriptFile::execute(const std::string& declaration, const std::vector<Variant>& parameters, bool unprepare)
@@ -545,14 +543,10 @@ void ScriptFile::handleScriptEvent(StringHash eventType, VariantMap& eventData)
     if (!mCompiled)
     if (!mCompiled)
         return;
         return;
     
     
-    std::map<StringHash, asIScriptFunction*>::iterator i = mEventHandlers.find(eventType);
-    if (i == mEventHandlers.end())
-        return;
-    
     std::vector<Variant> parameters;
     std::vector<Variant> parameters;
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventData));
     parameters.push_back(Variant((void*)&eventData));
-    execute(i->second, parameters);
+    execute(static_cast<asIScriptFunction*>(getInvoker()->getUserData()), parameters);
 }
 }
 
 
 void ScriptFile::handleSpecificScriptEvent(StringHash eventType, VariantMap& eventData)
 void ScriptFile::handleSpecificScriptEvent(StringHash eventType, VariantMap& eventData)
@@ -560,15 +554,10 @@ void ScriptFile::handleSpecificScriptEvent(StringHash eventType, VariantMap& eve
     if (!mCompiled)
     if (!mCompiled)
         return;
         return;
     
     
-    std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator i = mSpecificEventHandlers.find(std::make_pair(
-        getEventSender(), eventType));
-    if (i == mSpecificEventHandlers.end())
-        return;
-    
     std::vector<Variant> parameters;
     std::vector<Variant> parameters;
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventData));
     parameters.push_back(Variant((void*)&eventData));
-    execute(i->second, parameters);
+    execute(static_cast<asIScriptFunction*>(getInvoker()->getUserData()), parameters);
 }
 }
 
 
 ScriptFile* getScriptContextFile()
 ScriptFile* getScriptContextFile()

+ 4 - 15
Engine/Script/ScriptInstance.cpp

@@ -433,8 +433,7 @@ void ScriptInstance::addEventHandler(StringHash eventType, const std::string& ha
         return;
         return;
     }
     }
     
     
-    subscribeToEvent(eventType, EVENT_HANDLER(ScriptInstance, handleScriptEvent));
-    mEventHandlers[eventType] = method;
+    subscribeToEvent(eventType, EVENT_HANDLER_USERDATA(ScriptInstance, handleScriptEvent, (void*)method));
 }
 }
 
 
 void ScriptInstance::addEventHandler(EventListener* sender, StringHash eventType, const std::string& handlerName)
 void ScriptInstance::addEventHandler(EventListener* sender, StringHash eventType, const std::string& handlerName)
@@ -456,8 +455,7 @@ void ScriptInstance::addEventHandler(EventListener* sender, StringHash eventType
         return;
         return;
     }
     }
     
     
-    subscribeToEvent(sender, eventType, EVENT_HANDLER(ScriptInstance, handleSpecificScriptEvent));
-    mSpecificEventHandlers[std::make_pair(sender, eventType)] = method;
+    subscribeToEvent(sender, eventType, EVENT_HANDLER_USERDATA(ScriptInstance, handleSpecificScriptEvent, (void*)method));
 }
 }
 
 
 bool ScriptInstance::createObject()
 bool ScriptInstance::createObject()
@@ -656,14 +654,10 @@ void ScriptInstance::handleScriptEvent(StringHash eventType, VariantMap& eventDa
     if ((!mEnabled) || (!mScriptFile) || (!mScriptObject))
     if ((!mEnabled) || (!mScriptFile) || (!mScriptObject))
         return;
         return;
     
     
-    std::map<StringHash, asIScriptFunction*>::iterator i = mEventHandlers.find(eventType);
-    if (i == mEventHandlers.end())
-        return;
-    
     std::vector<Variant> parameters;
     std::vector<Variant> parameters;
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventData));
     parameters.push_back(Variant((void*)&eventData));
-    mScriptFile->execute(mScriptObject, i->second, parameters);
+    mScriptFile->execute(mScriptObject, static_cast<asIScriptFunction*>(getInvoker()->getUserData()), parameters);
 }
 }
 
 
 void ScriptInstance::handleSpecificScriptEvent(StringHash eventType, VariantMap& eventData)
 void ScriptInstance::handleSpecificScriptEvent(StringHash eventType, VariantMap& eventData)
@@ -671,15 +665,10 @@ void ScriptInstance::handleSpecificScriptEvent(StringHash eventType, VariantMap&
     if ((!mEnabled) || (!mScriptFile) || (!mScriptObject))
     if ((!mEnabled) || (!mScriptFile) || (!mScriptObject))
         return;
         return;
     
     
-    std::map<std::pair<EventListener*, StringHash>, asIScriptFunction*>::iterator i = mSpecificEventHandlers.find(std::make_pair(
-        getEventSender(), eventType));
-    if (i == mSpecificEventHandlers.end())
-        return;
-    
     std::vector<Variant> parameters;
     std::vector<Variant> parameters;
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventType));
     parameters.push_back(Variant((void*)&eventData));
     parameters.push_back(Variant((void*)&eventData));
-    mScriptFile->execute(mScriptObject, i->second, parameters);
+    mScriptFile->execute(mScriptObject, static_cast<asIScriptFunction*>(getInvoker()->getUserData()), parameters);
 }
 }
 
 
 ScriptInstance* getScriptContextInstance()
 ScriptInstance* getScriptContextInstance()