Просмотр исходного кода

Add coroutine.start and coroutine.sleep in Lua.

aster2013 11 лет назад
Родитель
Сommit
526e114db6

+ 19 - 1
Source/Engine/LuaScript/LuaScript.cpp

@@ -21,6 +21,7 @@
 //
 
 #include "Precompiled.h"
+#include "CoreEvents.h"
 #include "EngineEvents.h"
 #include "File.h"
 #include "Log.h"
@@ -58,6 +59,7 @@ extern int tolua_PhysicsLuaAPI_open(lua_State*);
 extern int tolua_ResourceLuaAPI_open(lua_State*);
 extern int tolua_SceneLuaAPI_open(lua_State*);
 extern int tolua_UILuaAPI_open(lua_State*);
+extern int tolua_Urho2DLuaAPI_open(lua_State*);
 extern int tolua_LuaScriptLuaAPI_open(lua_State*);
 
 namespace Urho3D
@@ -101,6 +103,11 @@ LuaScript::LuaScript(Context* context) :
     tolua_UILuaAPI_open(luaState_);
     tolua_LuaScriptLuaAPI_open(luaState_);
 
+    coroutineUpdate_ = GetFunction("coroutine.update");
+
+    // Subscribe to post update
+    SubscribeToEvent(E_POSTUPDATE, HANDLER(LuaScript, HandlePostUpdate));
+
     // Subscribe to console commands
     SubscribeToEvent(E_CONSOLECOMMAND, HANDLER(LuaScript, HandleConsoleCommand));
 }
@@ -214,7 +221,7 @@ void LuaScript::ScriptUnsubscribeFromEvent(void* sender, const String& eventName
     if (i != objectToEventTypeToFunctionMap_[object].End())
     {
         UnsubscribeFromEvent(object, eventType);
-        
+
         objectToEventTypeToFunctionMap_[object].Erase(i);
     }
 }
@@ -366,6 +373,17 @@ void LuaScript::HandleObjectEvent(StringHash eventType, VariantMap& eventData)
     }
 }
 
+void LuaScript::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
+{
+    if (coroutineUpdate_ && coroutineUpdate_->BeginCall())
+    {
+        using namespace PostUpdate;
+        float timeStep = eventData[P_TIMESTEP].GetFloat();
+        coroutineUpdate_->PushFloat(timeStep);
+        coroutineUpdate_->EndCall();
+    }
+}
+
 void LuaScript::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
 {
     using namespace ConsoleCommand;

+ 6 - 2
Source/Engine/LuaScript/LuaScript.h

@@ -66,7 +66,7 @@ public:
     void ScriptUnsubscribeFromEvent(void* sender, const String& eventName);
     /// Script unsubscribe from a specific sender's all events.
     void ScriptUnsubscribeFromEvents(void* sender);
-    
+
     /// Return Lua state.
     lua_State* GetState() const { return luaState_; }
     /// Return Lua function.
@@ -81,11 +81,13 @@ private:
     void HandleEvent(StringHash eventType, VariantMap& eventData);
     /// Handle object event.
     void HandleObjectEvent(StringHash eventType, VariantMap& eventData);
+    /// Handle post update.
+    void HandlePostUpdate(StringHash eventType, VariantMap& eventData);
     /// Handle a console command event.
     void HandleConsoleCommand(StringHash eventType, VariantMap& eventData);
     /// Push script function.
     bool PushScriptFunction(const String& functionName, bool silentIfNotfound = false);
-    
+
     /// At panic.
     static int AtPanic(lua_State* L);
     /// Loader.
@@ -95,6 +97,8 @@ private:
 
     /// Lua state.
     lua_State* luaState_;
+    /// Coroutine update function.
+    WeakPtr<LuaFunction> coroutineUpdate_;
     /// Function name to function map.
     HashMap<String, SharedPtr<LuaFunction> > functionNameToFunctionMap_;
     /// Event type to function map.

+ 1 - 1
Source/Engine/LuaScript/ToluaUtils.cpp

@@ -51,7 +51,7 @@ Context* GetContext(lua_State* L)
 {
     HashMap<void*, Context*>::ConstIterator i = contextMapping.Find(L);
     if (i == contextMapping.End())
-        return 0;
+        return GetContext(lua_getmainthread(L));
 
     return i->second_;
 }

+ 55 - 0
Source/Engine/LuaScript/pkgs/LuaScript/Coroutine.pkg

@@ -0,0 +1,55 @@
+$[
+
+-- Total time
+coroutine.totaltime = 0
+
+-- Suspended coroutines
+coroutine.suspendedcoroutines = {}
+
+-- Start a coroutine
+function coroutine.start(func)
+    if func == nil then
+        return nil
+    end
+
+    local co = coroutine.create(func)
+    return coroutine.resume(co)
+end
+
+-- Sleep a coroutine
+function coroutine.sleep(time)
+    -- Return running coroutine
+    local co = coroutine.running()
+    if co == nil then
+        return
+    end
+
+    -- Calculate wake up time
+    local wakeuptime = coroutine.totaltime + time
+    coroutine.suspendedcoroutines[co] = wakeuptime
+
+    -- Suspend running coroutine
+    return coroutine.yield(co)
+end
+
+-- Update suspended coroutines
+function coroutine.update(steptime)
+    -- Update total time
+    coroutine.totaltime = coroutine.totaltime + steptime
+
+    -- Find all coroutines
+    local coroutines = {}
+    for co, wakeuptime in pairs(coroutine.suspendedcoroutines) do
+        if wakeuptime < coroutine.totaltime then
+            table.insert(coroutines, co)
+        end
+    end
+
+    -- Resume all coroutines
+    for _, co in ipairs(coroutines) do
+        coroutine.suspendedcoroutines[co] = nil
+        coroutine.resume(co)
+    end
+end
+
+$]

+ 1 - 0
Source/Engine/LuaScript/pkgs/LuaScriptLuaAPI.pkg

@@ -1,3 +1,4 @@
+$pfile "LuaScript/Coroutine.pkg"
 $pfile "LuaScript/LuaScript.pkg"
 $pfile "LuaScript/LuaScriptInstance.pkg"