Bläddra i källkod

Use command to record add or remove event handler when invoking.
Convert tab to spaces.

aster2013 11 år sedan
förälder
incheckning
a8104ef27c

+ 117 - 4
Source/Urho3D/LuaScript/LuaScriptEventInvoker.cpp

@@ -29,15 +29,59 @@
 namespace Urho3D
 {
 
+class EventHandlerCommand
+{
+public:
+    EventHandlerCommand(int type) : type_(type) { }
+    virtual ~EventHandlerCommand() { }
+    int type_;
+};
+
+struct AddOrRemoveEventHandlerCommand : public EventHandlerCommand
+{
+    enum { Type = 1 };
+    AddOrRemoveEventHandlerCommand(bool add, Object* sender, const StringHash& eventType, WeakPtr<LuaFunction> function) : 
+        EventHandlerCommand(Type), add_(add), sender_(sender), eventType_(eventType), function_(function)
+    {
+    }
+
+    bool add_;
+    Object* sender_;
+    StringHash eventType_;
+    WeakPtr<LuaFunction> function_;
+};
+
+struct RemoveAllEventHandlersCommand : public EventHandlerCommand
+{    
+    enum { Type = 2 };
+    RemoveAllEventHandlersCommand(Object* sender) : EventHandlerCommand(Type), sender_(sender)
+    {
+    }
+
+    Object* sender_;
+};
+
+struct RemoveEventHandlersExceptCommand : public EventHandlerCommand
+{
+
+    enum { Type = 3 };
+    RemoveEventHandlersExceptCommand(const PODVector<StringHash>& exceptionTypes) : EventHandlerCommand(Type), exceptionTypes_(exceptionTypes)
+    {
+    }
+    PODVector<StringHash> exceptionTypes_;
+};
+
 LuaScriptEventInvoker::LuaScriptEventInvoker(Context* context) : 
     Object(context), 
-    instance_(0)
+    instance_(0),
+    invoking_(false)
 {
 }
 
 LuaScriptEventInvoker::LuaScriptEventInvoker(LuaScriptInstance* instance) : 
     Object(instance->GetContext()), 
-    instance_(instance)
+    instance_(instance),
+    invoking_(false)
 {
 }
 
@@ -47,6 +91,12 @@ LuaScriptEventInvoker::~LuaScriptEventInvoker()
 
 void LuaScriptEventInvoker::AddEventHandler(Object* sender, const StringHash& eventType, WeakPtr<LuaFunction> function)
 {
+    if (invoking_)
+    {
+        eventHandlerCommands_.Push(new AddOrRemoveEventHandlerCommand(true, sender, eventType, function));
+        return;
+    }
+
     EventTypeToLuaFunctionVectorMap& eventTypeToFunctionVectorMap = GetEventTypeToLuaFunctionVectorMap(sender);
     EventTypeToLuaFunctionVectorMap::Iterator i = eventTypeToFunctionVectorMap.Find(eventType);
 
@@ -68,6 +118,12 @@ void LuaScriptEventInvoker::AddEventHandler(Object* sender, const StringHash& ev
 
 void LuaScriptEventInvoker::RemoveEventHandler(Object* sender, const StringHash& eventType, WeakPtr<LuaFunction> function)
 {
+    if (invoking_)
+    {
+        eventHandlerCommands_.Push(new AddOrRemoveEventHandlerCommand(false, sender, eventType, function));
+        return;
+    }
+
     EventTypeToLuaFunctionVectorMap& eventTypeToLuaFunctionVectorMap = GetEventTypeToLuaFunctionVectorMap(sender);
     EventTypeToLuaFunctionVectorMap::Iterator i = eventTypeToLuaFunctionVectorMap.Find(eventType);
     if (i == eventTypeToLuaFunctionVectorMap.End())
@@ -91,6 +147,12 @@ void LuaScriptEventInvoker::RemoveEventHandler(Object* sender, const StringHash&
 
 void LuaScriptEventInvoker::RemoveAllEventHandlers(Object* sender)
 {
+    if (invoking_)
+    {
+        eventHandlerCommands_.Push(new RemoveAllEventHandlersCommand(sender));
+        return;
+    }
+
     if (!sender)
     {
         UnsubscribeFromAllEvents();
@@ -106,6 +168,12 @@ void LuaScriptEventInvoker::RemoveAllEventHandlers(Object* sender)
 
 void LuaScriptEventInvoker::RemoveEventHandlersExcept(const PODVector<StringHash>& exceptionTypes)
 {
+    if (invoking_)
+    {
+        eventHandlerCommands_.Push(new RemoveEventHandlersExceptCommand(exceptionTypes));
+        return;
+    }
+
     for (unsigned i = 0; i < exceptionTypes.Size(); ++i)
         eventTypeToLuaFunctionVectorMap.Erase(exceptionTypes[i]);
 
@@ -120,9 +188,9 @@ void LuaScriptEventInvoker::HandleLuaScriptEvent(StringHash eventType, VariantMa
     if (i == eventTypeToLuaFunctionVectorMap.End())
         return;
 
-    // Create a copy
-    LuaFunctionVector luaFunctionVector = i->second_;
+    invoking_ = true;
 
+    LuaFunctionVector& luaFunctionVector = i->second_;
     if (instance_)
     {
         instance_->AddRef();
@@ -153,6 +221,51 @@ void LuaScriptEventInvoker::HandleLuaScriptEvent(StringHash eventType, VariantMa
             }
         }
     }
+
+    invoking_ = false;
+
+    if (!eventHandlerCommands_.Empty())
+    {
+        for (unsigned i = 0; i < eventHandlerCommands_.Size(); ++i)
+            ExecuteThenDestroyCommand(eventHandlerCommands_[i]);
+
+        eventHandlerCommands_.Clear();
+    }
+}
+
+void LuaScriptEventInvoker::ExecuteThenDestroyCommand(EventHandlerCommand* command)
+{
+    if (!command)
+        return;
+
+    switch (command->type_)
+    {
+    case AddOrRemoveEventHandlerCommand::Type:
+        {
+            AddOrRemoveEventHandlerCommand* theCommand = (AddOrRemoveEventHandlerCommand*)command;
+            if (theCommand->add_)
+                AddEventHandler(theCommand->sender_, theCommand->eventType_, theCommand->function_);
+            else
+                RemoveEventHandler(theCommand->sender_, theCommand->eventType_, theCommand->function_);
+        }
+        break;
+
+    case RemoveAllEventHandlersCommand::Type:
+        {
+            RemoveAllEventHandlersCommand* theCommand = (RemoveAllEventHandlersCommand*)command;
+            RemoveAllEventHandlers(theCommand->sender_);
+        }
+        break;
+
+    case RemoveEventHandlersExceptCommand::Type:
+        {
+            RemoveEventHandlersExceptCommand* theCommand = (RemoveEventHandlersExceptCommand*)command;
+            RemoveEventHandlersExcept(theCommand->exceptionTypes_);
+        }
+        break;
+    }
+
+    delete command;
 }
 
 }

+ 7 - 2
Source/Urho3D/LuaScript/LuaScriptEventInvoker.h

@@ -27,6 +27,7 @@
 namespace Urho3D
 {
 
+class EventHandlerCommand;
 class LuaFunction;
 class LuaScriptInstance;
 
@@ -54,10 +55,8 @@ public:
 private:
     /// Handle script event in Lua script.
     void HandleLuaScriptEvent(StringHash eventType, VariantMap& eventData);
-
     typedef Vector<WeakPtr<LuaFunction> > LuaFunctionVector;
     typedef HashMap<StringHash, LuaFunctionVector> EventTypeToLuaFunctionVectorMap;
-    
     /// Return event type to Lua function vector map.
     EventTypeToLuaFunctionVectorMap& GetEventTypeToLuaFunctionVectorMap(Object* sender)
     {
@@ -66,9 +65,15 @@ private:
 
         return senderEventTypeToLuaFunctionVectorMap[sender];
     }
+    /// Execute then destory command.
+    void ExecuteThenDestroyCommand(EventHandlerCommand* command);
 
     /// Lua script instance.
     LuaScriptInstance* instance_;
+    /// Invoking.
+    bool invoking_;
+    /// Event handler commands.
+    PODVector<EventHandlerCommand*> eventHandlerCommands_;
     /// Event type to Lua function vector map.
     EventTypeToLuaFunctionVectorMap eventTypeToLuaFunctionVectorMap;
     /// Event type to Lua function vector map for specific sender.

+ 7 - 7
Source/Urho3D/LuaScript/LuaScriptInstance.cpp

@@ -396,7 +396,7 @@ void LuaScriptInstance::RemoveEventHandlersExcept(const Vector<String>& exceptio
 
 bool LuaScriptInstance::CreateObject(const String& scriptObjectType)
 {
-	SetScriptFile(0);
+    SetScriptFile(0);
     SetScriptObjectType(scriptObjectType);
     return scriptObjectRef_ != LUA_REFNIL;
 }
@@ -410,13 +410,13 @@ bool LuaScriptInstance::CreateObject(LuaFile* scriptFile, const String& scriptOb
 
 void LuaScriptInstance::SetScriptFile(LuaFile* scriptFile)
 {
-	if (scriptFile == scriptFile_)
-		return;
+    if (scriptFile == scriptFile_)
+        return;
 
-	scriptFile_ = scriptFile;
+    scriptFile_ = scriptFile;
 
-	if (!scriptFile_)
-		return;
+    if (!scriptFile_)
+        return;
 
     if (!scriptFile_->LoadAndExecute(luaState_))
         LOGERROR("Execute Lua file failed: " + scriptFile_->GetName());
@@ -478,7 +478,7 @@ void LuaScriptInstance::SetScriptNetworkDataAttr(const PODVector<unsigned char>&
 
 LuaFile* LuaScriptInstance::GetScriptFile() const
 {
-	return scriptFile_;
+    return scriptFile_;
 }
 
 PODVector<unsigned char> LuaScriptInstance::GetScriptDataAttr() const

+ 10 - 10
Source/Urho3D/LuaScript/LuaScriptInstance.h

@@ -117,8 +117,8 @@ public:
     /// Set script network serialization attribute by calling a script function.
     void SetScriptNetworkDataAttr(const PODVector<unsigned char>& data);
 
-	/// Return script file.
-	LuaFile* GetScriptFile() const;
+    /// Return script file.
+    LuaFile* GetScriptFile() const;
     /// Return script object type.
     const String& GetScriptObjectType() const { return scriptObjectType_; }
     /// Return script object ref.
@@ -130,10 +130,10 @@ public:
     /// Return script object's funcition.
     WeakPtr<LuaFunction> GetScriptObjectFunction(const String& functionName) const;
 
-	/// Set script file attribute.
-	void SetScriptFileAttr(const ResourceRef& value);
-	/// Return script file attribute.
-	ResourceRef GetScriptFileAttr() const;
+    /// Set script file attribute.
+    void SetScriptFileAttr(const ResourceRef& value);
+    /// Return script file attribute.
+    ResourceRef GetScriptFileAttr() const;
 
 protected:
     /// Handle node transform being dirtied.
@@ -168,10 +168,10 @@ private:
     /// Event invoker.
     SharedPtr<LuaScriptEventInvoker> eventInvoker_;
     /// Script file.
-	SharedPtr<LuaFile> scriptFile_;
-	/// Script object type.
-	String scriptObjectType_;
-	/// Attributes, including script object variables.
+    SharedPtr<LuaFile> scriptFile_;
+    /// Script object type.
+    String scriptObjectType_;
+    /// Attributes, including script object variables.
     Vector<AttributeInfo> attributeInfos_;
     /// Script object ref.
     int scriptObjectRef_;