浏览代码

Add LuaFunction class, Add more Lua API in Sound, fixed typo.

Aster Jian 12 年之前
父节点
当前提交
4b9f241065

+ 2 - 2
Source/Extras/LuaScript/LuaFile.h

@@ -48,9 +48,9 @@ public:
     /// Save resource. Return true if successful.
     virtual bool Save(Serializer& dest) const;
 
-    /// Load buffer as Lua chunk.
+    /// Load buffer as chunk.
     bool LoadChunk(lua_State* luaState);
-    /// Load buffer as lua chunk and execute.
+    /// Load buffer as chunk and execute.
     bool LoadAndExecute(lua_State* luaState);
 
 private:

+ 209 - 0
Source/Extras/LuaScript/LuaFunction.cpp

@@ -0,0 +1,209 @@
+//
+// Copyright (c) 2008-2013 the Urho3D project.
+//
+// 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.
+//
+
+#include "Precompiled.h"
+#include "Log.h"
+#include "LuaFunction.h"
+#include "LuaScript.h"
+#include "LuaScriptInstance.h"
+#include "VectorBuffer.h"
+#include "ToluaUrho3DEx.h"
+
+extern "C"
+{
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+}
+#include "tolua++.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+LuaFunction::LuaFunction(lua_State* luaState, int functionRef) : 
+    luaState_(luaState),
+    functionRef_(functionRef)
+{
+}
+
+LuaFunction::~LuaFunction()
+{
+    if (functionRef_ != LUA_REFNIL)
+        luaL_unref(luaState_, LUA_REGISTRYINDEX, functionRef_);
+}
+
+
+bool LuaFunction::IsValid() const
+{
+    return functionRef_ != LUA_REFNIL;
+}
+
+bool LuaFunction::BeginCall()
+{
+    if (!IsValid())
+        return false;
+
+    stackTop_ = lua_gettop(luaState_);
+    numArguments_ = 0;
+    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef_);
+
+    return true;
+}
+
+bool LuaFunction::BeginCall(const LuaScriptInstance* instance)
+{
+    if (!IsValid())
+        return false;
+
+    stackTop_ = lua_gettop(luaState_);
+    numArguments_ = 1;
+    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef_);
+    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, instance->GetScriptObjectRef());
+
+    return true;
+}
+
+bool LuaFunction::EndCall(int numReturns)
+{
+    if (lua_pcall(luaState_, numArguments_, numReturns, 0) != 0)
+    {
+        const char* message = lua_tostring(luaState_, -1);
+        LOGERROR("Execute Lua function failed: " + String(message));
+        lua_settop(luaState_, stackTop_);
+        return false;
+    }
+
+    return true;
+}
+
+void LuaFunction::PushInt(int value)
+{
+    ++numArguments_;
+
+    lua_pushinteger(luaState_, value);
+}
+
+void LuaFunction::PushBool(bool value)
+{
+    ++numArguments_;
+
+    lua_pushboolean(luaState_, value);
+}
+
+void LuaFunction::PushFloat(float value)
+{
+    ++numArguments_;
+
+    lua_pushnumber(luaState_, value);
+}
+
+void LuaFunction::PushString(const String& string)
+{
+    tolua_pushurho3dstring(luaState_, string);
+}
+
+void LuaFunction::PushUserType(void* userType, const char* typeName)
+{
+    ++numArguments_;
+
+    tolua_pushusertype(luaState_, userType, typeName);
+}
+
+bool LuaFunction::PushVariant(const Variant& variant)
+{
+    switch (variant.GetType())
+    {
+    case VAR_INT:
+        PushInt(variant.GetInt());
+        return true;
+
+    case VAR_BOOL:
+        PushBool(variant.GetBool());
+        return true;
+
+    case VAR_FLOAT:
+        PushFloat(variant.GetFloat()); 
+        return true;
+
+    case VAR_VECTOR2:
+        PushUserType(variant.GetVector2(), "Vector2"); 
+        return true;
+
+    case VAR_VECTOR3:
+        PushUserType(variant.GetVector3(), "Vector3");
+        return true;
+
+    case VAR_VECTOR4:
+        PushUserType(variant.GetVector4(), "Vector4");
+        return true;
+
+    case VAR_QUATERNION:
+        PushUserType(variant.GetQuaternion(), "Quaternion"); 
+        return true;
+
+    case VAR_COLOR:
+        PushUserType(variant.GetQuaternion(), "Color");
+        return true;
+
+    case VAR_STRING:
+        PushString(variant.GetString());
+        return true;
+
+    case VAR_BUFFER:
+        {
+            VectorBuffer buffer(variant.GetBuffer());
+            PushUserType(buffer, "VectorBuffer");
+        }
+        return true;
+
+    case VAR_RESOURCEREF:
+        PushUserType(variant.GetResourceRef(), "ResourceRef");
+        return true;
+
+    case VAR_INTRECT:
+        PushUserType(variant.GetIntRect(), "IntRect");
+        return true;
+
+    case VAR_INTVECTOR2:
+        PushUserType(variant.GetIntVector2(), "IntVector2"); 
+        return true;
+    }
+
+    return false;
+}
+
+bool LuaFunction::PushLuaTable(const String& tableName)
+{
+    ++numArguments_;
+
+    lua_getglobal(luaState_, tableName.CString());
+    if (!lua_istable(luaState_, -1))
+    {
+        LOGERROR("Could not find lua table " + tableName);
+        return false;
+    }
+    return true;
+}
+
+}

+ 99 - 0
Source/Extras/LuaScript/LuaFunction.h

@@ -0,0 +1,99 @@
+//
+// Copyright (c) 2008-2013 the Urho3D project.
+//
+// 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.
+//
+
+#pragma once
+
+struct lua_State;
+
+namespace Urho3D
+{
+
+class LuaScript;
+class LuaScriptInstance;
+
+/// Lua function.
+class URHO3D_API LuaFunction
+{
+public:
+    /// Construct.
+    LuaFunction(lua_State* lusState, int functionRef);
+    /// Destruct.
+    ~LuaFunction();
+
+    /// Check function is valid.
+    bool IsValid() const;
+    /// Begin call function.
+    bool BeginCall();
+    /// Begin call script object's function.
+    bool BeginCall(const LuaScriptInstance* instance);
+    /// End call function.
+    bool EndCall(int numReturns = 0);
+    /// Push int to stack.
+    void PushInt(int value);
+    /// Push bool to stack.
+    void PushBool(bool value);
+    /// Push float to stack.
+    void PushFloat(float value);
+    /// Push string to stack.
+    void PushString(const String& string);
+    /// Push user type to stack.
+    void PushUserType(void* userType, const char* typeName);
+    /// Push user type to stack.
+    template <typename T> void PushUserType(const T* userType)
+    {
+        PushUserType((void*)userType, T::GetTypeName().CString());
+    }
+    /// Push user type to stack.
+    template <typename T> void PushUserType(const T& userType)
+    {
+        PushUserType((void*)&userType, T::GetTypeName().CString());
+    }
+    /// Push user type to stack.
+    template <typename T> void PushUserType(const T* userType, const char* typeName)
+    {
+        PushUserType((void*)userType, typeName);
+    }
+    /// Push user type to stack.
+    template <typename T> void PushUserType(const T& userType, const char* typeName)
+    {
+        PushUserType((void*)&userType, typeName);
+    }
+    /// Push variant to stack.
+    bool PushVariant(const Variant& variant);
+    /// Push Lua table to stack.
+    bool PushLuaTable(const String& tableName);
+
+    /// Return function ref.
+    int GetFunctionRef() const { return functionRef_; }
+
+private:
+    /// Lua state.
+    lua_State* luaState_;
+    /// Function ref.
+    int functionRef_;
+    /// Lua stack top.
+    int stackTop_;
+    /// Number of arguments.
+    int numArguments_;
+};
+
+}

+ 65 - 85
Source/Extras/LuaScript/LuaScript.cpp

@@ -25,6 +25,7 @@
 #include "File.h"
 #include "Log.h"
 #include "LuaFile.h"
+#include "LuaFunction.h"
 #include "LuaScript.h"
 #include "LuaScriptInstance.h"
 #include "ProcessUtils.h"
@@ -105,14 +106,14 @@ LuaScript::LuaScript(Context* context) :
 
 LuaScript::~LuaScript()
 {
-    for (HashMap<String, int>::Iterator i = functionNameToFunctionRefMap_.Begin(); i != functionNameToFunctionRefMap_.End(); ++i)
-    {
-        if (i->second_ != LUA_REFNIL)
-            luaL_unref(luaState_, LUA_REGISTRYINDEX, i->second_);
-    }
+    for (HashMap<String, LuaFunction*>::Iterator i = functionNameToFunctionMap_.Begin(); i != functionNameToFunctionMap_.End(); ++i)
+        delete i->second_;
 
-    if (luaState_)
-        lua_close(luaState_);
+    lua_State* luaState = luaState_;
+    luaState_ = 0;
+
+    if (luaState)
+        lua_close(luaState);
 }
 
 bool LuaScript::ExecuteFile(const String& fileName)
@@ -147,34 +148,18 @@ bool LuaScript::ExecuteString(const String& string)
     return true;
 }
 
-bool LuaScript::ExecuteFunction(const String& functionName, const VariantVector& parameters)
+bool LuaScript::ExecuteFunction(const String& functionName)
 {
-    PROFILE(ExecuteFunction);
-
-    int top = lua_gettop(luaState_);
-
-    if (!PushScriptFunction(functionName))
-    {
-        lua_settop(luaState_, top);
+    LuaFunction* function = GetFunction(functionName);
+    if (!function)
         return false;
-    }
 
-    // Push parameters.
-    if (!tolua_pushurho3dvariantvector(luaState_, parameters))
+    if (function->BeginCall())
     {
-        lua_settop(luaState_, top);
-        return false;
+        return function->EndCall();
     }
 
-    if (lua_pcall(luaState_, parameters.Size(), 0, 0))
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-        return false;
-    }
-
-    return true;
+    return false;
 }
 
 void LuaScript::ScriptSendEvent(const String& eventName, VariantMap& eventData)
@@ -186,34 +171,36 @@ void LuaScript::ScriptSubscribeToEvent(const String& eventName, const String& fu
 {
     StringHash eventType(eventName);
 
-    int functionRef = GetScriptFunctionRef(functionName);
-    if (functionRef != LUA_REFNIL)
+    LuaFunction* luaFunciton = GetFunction(functionName);
+    if (luaFunciton)
     {
         SubscribeToEvent(eventType, HANDLER(LuaScript, HandleEvent));
-        eventTypeToFunctionRefMap_[eventType] = functionRef;
+
+        eventTypeToFunctionMap_[eventType] = luaFunciton;
     }
 }
 
-
 void LuaScript::ScriptUnsubscribeFromEvent(const String& eventName)
 {
     StringHash eventType(eventName);
 
-    HashMap<StringHash, int>::Iterator i = eventTypeToFunctionRefMap_.Find(eventType);
-    if (i != eventTypeToFunctionRefMap_.End())
+    HashMap<StringHash, LuaFunction*>::Iterator i = eventTypeToFunctionMap_.Find(eventType);
+    if (i != eventTypeToFunctionMap_.End())
     {
         UnsubscribeFromEvent(eventType);
-        eventTypeToFunctionRefMap_.Erase(i);
+
+        eventTypeToFunctionMap_.Erase(i);
     }
 }
 
 void LuaScript::ScriptUnsubscribeFromAllEvents()
 {
-    if (eventTypeToFunctionRefMap_.Empty())
+    if (eventTypeToFunctionMap_.Empty())
         return;
 
     UnsubscribeFromAllEvents();
-    eventTypeToFunctionRefMap_.Clear();
+
+    eventTypeToFunctionMap_.Clear();
 }
 
 void LuaScript::ScriptSubscribeToEvent(void* sender, const String& eventName, const String& functionName)
@@ -221,11 +208,12 @@ void LuaScript::ScriptSubscribeToEvent(void* sender, const String& eventName, co
     StringHash eventType(eventName);
     Object* object = (Object*)sender;
 
-    int functionRef = GetScriptFunctionRef(functionName);
-    if (functionRef != LUA_REFNIL)
+    LuaFunction* function = GetFunction(functionName);
+    if (function)
     {
         SubscribeToEvent(object, eventType, HANDLER(LuaScript, HandleObjectEvent));
-        objectToEventTypeToFunctionRefMap_[object][eventType] = functionRef;
+
+        objectToEventTypeToFunctionMap_[object][eventType] = function;
     }
 }
 
@@ -234,12 +222,12 @@ void LuaScript::ScriptUnsubscribeFromEvent(void* sender, const String& eventName
     StringHash eventType(eventName);
     Object* object = (Object*)sender;
 
-    HashMap<StringHash, int>::Iterator i = objectToEventTypeToFunctionRefMap_[object].Find(eventType);
-    if (i != objectToEventTypeToFunctionRefMap_[object].End())
+    HashMap<StringHash, LuaFunction*>::Iterator i = objectToEventTypeToFunctionMap_[object].Find(eventType);
+    if (i != objectToEventTypeToFunctionMap_[object].End())
     {
         UnsubscribeFromEvent(object, eventType);
-
-        objectToEventTypeToFunctionRefMap_[object].Erase(i);
+		
+        objectToEventTypeToFunctionMap_[object].Erase(i);
     }
 }
 
@@ -247,13 +235,12 @@ void LuaScript::ScriptUnsubscribeFromEvents(void* sender)
 {
     Object* object = (Object*)sender;
 
-    HashMap<Object*, HashMap<StringHash, int> >::Iterator it = objectToEventTypeToFunctionRefMap_.Find(object);
-    if (it == objectToEventTypeToFunctionRefMap_.End())
+    HashMap<Object*, HashMap<StringHash, LuaFunction*> >::Iterator it = objectToEventTypeToFunctionMap_.Find(object);
+    if (it == objectToEventTypeToFunctionMap_.End())
         return;
 
     UnsubscribeFromEvents(object);
-
-    objectToEventTypeToFunctionRefMap_.Erase(it);
+    objectToEventTypeToFunctionMap_.Erase(it);
 }
 
 void LuaScript::RegisterLoader()
@@ -327,42 +314,58 @@ int LuaScript::Print(lua_State *L)
     return 0;
 }
 
-int LuaScript::GetScriptFunctionRef(const String& functionName, bool silentIfNotFound)
+LuaFunction* LuaScript::GetFunction(const String& functionName, bool silentIfNotFound)
 {
-    HashMap<String, int>::Iterator i = functionNameToFunctionRefMap_.Find(functionName);
-    if (i != functionNameToFunctionRefMap_.End())
+    if (!luaState_)
+        return 0;
+
+    HashMap<String, LuaFunction*>::Iterator i = functionNameToFunctionMap_.Find(functionName);
+    if (i != functionNameToFunctionMap_.End())
         return i->second_;
 
     int top = lua_gettop(luaState_);
 
-    int functionRef = LUA_REFNIL;
+    LuaFunction* function = 0;
     if (PushScriptFunction(functionName, silentIfNotFound))
-        functionRef = luaL_ref(luaState_, LUA_REGISTRYINDEX);
+    {
+        int ref = luaL_ref(luaState_, LUA_REGISTRYINDEX);
+        function = new LuaFunction(luaState_, ref);
+    }
 
     lua_settop(luaState_, top);
 
-    functionNameToFunctionRefMap_[functionName] = functionRef;
+    functionNameToFunctionMap_[functionName] = function;
 
-    return functionRef;
+    return function;
 }
 
 void LuaScript::HandleEvent(StringHash eventType, VariantMap& eventData)
 {
-    int functionRef = eventTypeToFunctionRefMap_[eventType];
-    if (functionRef == LUA_REFNIL)
+    LuaFunction* function = eventTypeToFunctionMap_[eventType];
+    if (!function)
         return;
 
-    CallScriptFunction(functionRef, eventType, eventData);
+    if (function->BeginCall())
+    {
+        function->PushUserType(eventType, "StringHash");
+        function->PushUserType(eventData, "VariantMap");
+        function->EndCall();
+    }
 }
 
 void LuaScript::HandleObjectEvent(StringHash eventType, VariantMap& eventData)
 {
     Object* object = GetEventSender();
-    int functionRef = objectToEventTypeToFunctionRefMap_[object][eventType];
-    if (functionRef == LUA_REFNIL)
+    LuaFunction* function = objectToEventTypeToFunctionMap_[object][eventType];
+    if (!function)
         return;
 
-    CallScriptFunction(functionRef, eventType, eventData);
+    if (function->BeginCall())
+    {
+        function->PushUserType(eventType, "StringHash");
+        function->PushUserType(eventData, "VariantMap");
+        function->EndCall();
+    }
 }
 
 void LuaScript::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
@@ -411,29 +414,6 @@ bool LuaScript::PushScriptFunction(const String& functionName, bool silentIfNotF
     return true;
 }
 
-void LuaScript::CallScriptFunction(int functionRef, StringHash eventType, VariantMap& eventData )
-{
-    int top = lua_gettop(luaState_);
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-    if (!lua_isfunction(luaState_, -1))
-    {
-        LOGERROR("Could not find function");
-        lua_settop(luaState_, top);
-        return;
-    }
-
-    tolua_pushusertype(luaState_, (void*)&eventType, "StringHash");
-    tolua_pushusertype(luaState_, (void*)&eventData, "VariantMap");
-
-    if (lua_pcall(luaState_, 2, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-        return;
-    }
-}
-
 void RegisterLuaScriptLibrary(Context* context)
 {
     LuaFile::RegisterObject(context);

+ 14 - 15
Source/Extras/LuaScript/LuaScript.h

@@ -32,6 +32,7 @@ namespace Urho3D
 
 extern const char* LOGIC_CATEGORY;
 
+class LuaFunction;
 class Scene;
 
 /// Lua script subsystem.
@@ -49,8 +50,8 @@ public:
     bool ExecuteFile(const String& fileName);
     /// Execute script string. Return true if successful.
     bool ExecuteString(const String& string);
-    /// Execute script function. Parameters can be supplied in a VariantVector. Return true if successful.
-    bool ExecuteFunction(const String& functionName, const VariantVector& parameters = Variant::emptyVariantVector);
+    /// Execute script function.
+    bool ExecuteFunction(const String& functionName);
     /// Script send event.
     void ScriptSendEvent(const String& eventName, VariantMap& eventData);
     /// Script subscribe to an event that can by send by any sender.
@@ -67,10 +68,10 @@ public:
     void ScriptUnsubscribeFromEvents(void* sender);
     
     /// Return Lua state.
-    lua_State* GetLuaState() const { return luaState_; }
-    /// Return script function ref.
-    int GetScriptFunctionRef(const String& functionName, bool silentIfNotfound = false);
-    
+    lua_State* GetState() const { return luaState_; }
+    /// Return Lua function.
+    LuaFunction* GetFunction(const String& funcitonName, bool silentIfNotfound = false);
+
 private:
     /// Register loader.
     void RegisterLoader();
@@ -84,9 +85,7 @@ private:
     void HandleConsoleCommand(StringHash eventType, VariantMap& eventData);
     /// Push script function.
     bool PushScriptFunction(const String& functionName, bool silentIfNotfound = false);
-    /// Call script function.
-    void CallScriptFunction(int functionRef, StringHash eventType, VariantMap& eventData);
-
+    
     /// Loader.
     static int Loader(lua_State* L);
     /// Print function.
@@ -94,12 +93,12 @@ private:
 
     /// Lua state.
     lua_State* luaState_;
-    /// Function name to function ref map.
-    HashMap<String, int> functionNameToFunctionRefMap_;
-    /// Event type to function ref map.
-    HashMap<StringHash, int> eventTypeToFunctionRefMap_;
-    /// Object to event type to function ref map.
-    HashMap<Object*, HashMap<StringHash, int> > objectToEventTypeToFunctionRefMap_;
+    /// Function name to function map.
+    HashMap<String, LuaFunction*> functionNameToFunctionMap_;
+    /// Event type to function map.
+    HashMap<StringHash, LuaFunction*> eventTypeToFunctionMap_;
+    /// Object to event type to function map.
+    HashMap<Object*, HashMap<StringHash, LuaFunction*> > objectToEventTypeToFunctionMap_;
 };
 
 /// Register Lua script library objects.

+ 142 - 285
Source/Extras/LuaScript/LuaScriptInstance.cpp

@@ -25,6 +25,7 @@
 #include "Context.h"
 #include "Log.h"
 #include "LuaFile.h"
+#include "LuaFunction.h"
 #include "LuaScript.h"
 #include "LuaScriptInstance.h"
 #include "MemoryBuffer.h"
@@ -42,33 +43,34 @@ extern "C"
 }
 #include "tolua++.h"
 
+#include "DebugNew.h"
+
 namespace Urho3D
 {
 
 static const char* scriptObjectMethodNames[] = {
-    ".Start",
-    ".Stop",
-    // ".DelayedStart",
-    ".Update",
-    ".PostUpdate",
-    ".FixedUpdate",
-    ".FixedPostUpdate",
-    ".Load",
-    ".Save",
-    ".ReadNetworkUpdate",
-    ".WriteNetworkUpdate",
-    ".ApplyAttributes"
+    "Start",
+    "Stop",
+    "Update",
+    "PostUpdate",
+    "FixedUpdate",
+    "FixedPostUpdate",
+    "Load",
+    "Save",
+    "ReadNetworkUpdate",
+    "WriteNetworkUpdate",
+    "ApplyAttributes"
 };
 
-LuaScriptInstance::LuaScriptInstance(Context* context) : 
+LuaScriptInstance::LuaScriptInstance(Context* context) :
     Component(context),
     scriptObjectRef_(LUA_REFNIL)
 {
     luaScript_ = GetSubsystem<LuaScript>();
-    luaState_ = luaScript_->GetLuaState();
+    luaState_ = luaScript_->GetState();
 
     for (unsigned i = 0; i < MAX_LUA_SCRIPT_OBJECT_METHODS; ++i)
-        scriptObjectMethodRefs_[i] = LUA_REFNIL;
+        scriptObjectMethods_[i] = 0;
 }
 
 LuaScriptInstance::~LuaScriptInstance()
@@ -89,13 +91,17 @@ void LuaScriptInstance::RegisterObject(Context* context)
 
 void LuaScriptInstance::ApplyAttributes()
 {
-    CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_APPLYATTRIBUTES]);
+    LuaFunction* function = scriptObjectMethods_[LSOM_APPLYATTRIBUTES];
+    if (function && function->BeginCall(this))
+    {
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::OnSetEnabled()
 {
     if (enabled_)
-        SubscribeToScriptMethodEvents();    
+        SubscribeToScriptMethodEvents();
     else
         UnsubscribeFromScriptMethodEvents();
 }
@@ -140,36 +146,15 @@ void LuaScriptInstance::SetScriptObjectType(const String& scriptObjectType)
 
     ReleaseObject();
 
-    int top = lua_gettop(luaState_);
-
-    lua_getglobal(luaState_, "CreateScriptObjectInstance");
-    if (!lua_isfunction(luaState_, -1))
-    {
-        LOGERROR("Could not find lua function CreateScriptObjectInstance");
-        lua_settop(luaState_, top);
-        return;
-    }
-
-    // Get table as first paramter.
-    lua_getglobal(luaState_, scriptObjectType.CString());
-    if (!lua_istable(luaState_, -1))
-    {
-        LOGERROR("Could not find lua table " + scriptObjectType);
-        lua_settop(luaState_, top);
+    LuaFunction* function = luaScript_->GetFunction("CreateScriptObjectInstance");
+    if (!function || !function->BeginCall())
         return;
-    }
-
-    // Push this as second parameter.
-    tolua_pushusertype(luaState_, (void*)this, "LuaScriptInstance");
 
-    // Call ObjectType:new function.
-    if (lua_pcall(luaState_, 2, 1, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
+    function->PushLuaTable(scriptObjectType);
+    function->PushUserType((void*)this, "LuaScriptInstance");
+    
+    if (!function->EndCall(1))
         return;
-    }
 
     scriptObjectType_ = scriptObjectType;
     scriptObjectRef_ = luaL_ref(luaState_, LUA_REGISTRYINDEX);
@@ -180,34 +165,48 @@ void LuaScriptInstance::SetScriptObjectType(const String& scriptObjectType)
 
 void LuaScriptInstance::SetScriptDataAttr(PODVector<unsigned char> data)
 {
-    int functionRef = scriptObjectMethodRefs_[LSOM_LOAD];
-    if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
+    if (scriptObjectRef_ == LUA_REFNIL)
+        return;
+
+    LuaFunction* function = scriptObjectMethods_[LSOM_LOAD];
+    if (!function)
         return;
 
     MemoryBuffer buf(data);
-    CallScriptObjectFunction(functionRef, (Deserializer&)buf);
+    if (function->BeginCall(this))
+    {
+        function->PushUserType((Deserializer&)buf, "Deserializer");
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::SetScriptNetworkDataAttr(PODVector<unsigned char> data)
 {
-    int functionRef = scriptObjectMethodRefs_[LSOM_READNETWORKUPDATE];
-    if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
+    if (scriptObjectRef_ == LUA_REFNIL)
         return;
 
+    LuaFunction* function = scriptObjectMethods_[LSOM_READNETWORKUPDATE];
+    if (!function)
+        return;
+    
     MemoryBuffer buf(data);
-    CallScriptObjectFunction(functionRef, (Deserializer&)buf);
+    if (function->BeginCall(this))
+    {
+        function->PushUserType((Deserializer&)buf, "Deserializer");
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::ScriptSubscribeToEvent(const String& eventName, const String& functionName)
 {
     String realFunctionName = functionName.Replaced(":", ".");
 
-    int functionRef = luaScript_->GetScriptFunctionRef(realFunctionName);
-    if (functionRef != LUA_REFNIL)
+    LuaFunction* function = luaScript_->GetFunction(realFunctionName);
+    if (function)
     {
         StringHash eventType(eventName);
         SubscribeToEvent(eventType, HANDLER(LuaScriptInstance, HandleEvent));
-        eventTypeToFunctionRefMap_[eventType] = functionRef;
+        eventTypeToFunctionMap_[eventType] = function;
     }
 }
 
@@ -215,34 +214,34 @@ void LuaScriptInstance::ScriptUnsubscribeFromEvent(const String& eventName)
 {
     StringHash eventType(eventName);
 
-    HashMap<StringHash, int>::Iterator i = eventTypeToFunctionRefMap_.Find(eventType);
-    if (i != eventTypeToFunctionRefMap_.End())
+    HashMap<StringHash, LuaFunction*>::Iterator i = eventTypeToFunctionMap_.Find(eventType);
+    if (i != eventTypeToFunctionMap_.End())
     {
         UnsubscribeFromEvent(eventType);
-        eventTypeToFunctionRefMap_.Erase(i);
+        eventTypeToFunctionMap_.Erase(i);
     }
 }
 
 void LuaScriptInstance::ScriptUnsubscribeFromAllEvents()
 {
-    if (eventTypeToFunctionRefMap_.Empty())
+    if (eventTypeToFunctionMap_.Empty())
         return;
 
     UnsubscribeFromAllEvents();
-    eventTypeToFunctionRefMap_.Clear();
+    eventTypeToFunctionMap_.Clear();
 }
 
 void LuaScriptInstance::ScriptSubscribeToEvent(void* sender, const String& eventName, const String& functionName)
 {
     String realFunctionName = functionName.Replaced(":", ".");
 
-    int functionRef = luaScript_->GetScriptFunctionRef(realFunctionName);
-    if (functionRef != LUA_REFNIL)
+    LuaFunction* function = luaScript_->GetFunction(realFunctionName);
+    if (function)
     {
         Object* object = (Object*)sender;
         StringHash eventType(eventName);
         SubscribeToEvent(object, eventType, HANDLER(LuaScriptInstance, HandleObjectEvent));
-        objectToEventTypeToFunctionRefMap_[object][eventType] = functionRef;
+        objectToEventTypeToFunctionMap_[object][eventType] = function;
     }
 }
 
@@ -251,11 +250,11 @@ void LuaScriptInstance::ScriptUnsubscribeFromEvent(void* sender, const String& e
     StringHash eventType(eventName);
     Object* object = (Object*)sender ;
 
-    HashMap<StringHash, int>::Iterator i = objectToEventTypeToFunctionRefMap_[object].Find(eventType);
-    if (i != objectToEventTypeToFunctionRefMap_[object].End())
+    HashMap<StringHash, LuaFunction*>::Iterator i = objectToEventTypeToFunctionMap_[object].Find(eventType);
+    if (i != objectToEventTypeToFunctionMap_[object].End())
     {
         UnsubscribeFromEvent(object, eventType);
-        objectToEventTypeToFunctionRefMap_[object].Erase(i);
+        objectToEventTypeToFunctionMap_[object].Erase(i);
     }
 }
 
@@ -263,55 +262,56 @@ void LuaScriptInstance::ScriptUnsubscribeFromEvents(void* sender)
 {
     Object* object = (Object*)sender;
 
-    HashMap<Object*, HashMap<StringHash, int> >::Iterator it = objectToEventTypeToFunctionRefMap_.Find(object);
-    if (it == objectToEventTypeToFunctionRefMap_.End())
+    HashMap<Object*, HashMap<StringHash, LuaFunction*> >::Iterator it = objectToEventTypeToFunctionMap_.Find(object);
+    if (it == objectToEventTypeToFunctionMap_.End())
         return;
 
     UnsubscribeFromEvents(object);
-    objectToEventTypeToFunctionRefMap_.Erase(it);
+    objectToEventTypeToFunctionMap_.Erase(it);
 }
 
-bool LuaScriptInstance::ExecuteFunction(const String& functionName, const VariantVector& parameters)
+PODVector<unsigned char> LuaScriptInstance::GetScriptDataAttr() const
 {
     if (scriptObjectRef_ == LUA_REFNIL)
-        return false;
-
-    int functionRef = luaScript_->GetScriptFunctionRef(scriptObjectType_ + "." + functionName);
-    if (functionRef == LUA_REFNIL)
-        return false;
-    
-    return CallScriptObjectFunction(functionRef, parameters);
-}
+        return PODVector<unsigned char>();
 
-PODVector<unsigned char> LuaScriptInstance::GetScriptDataAttr() const
-{
-    int functionRef = scriptObjectMethodRefs_[LSOM_SAVE];
-    if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
+    LuaFunction* function = scriptObjectMethods_[LSOM_SAVE];
+    if (!function)
         return PODVector<unsigned char>();
 
     VectorBuffer buf;
-    CallScriptObjectFunction(functionRef, (Serializer&)buf);
+    if (function->BeginCall(this))
+    {
+        function->PushUserType((Serializer&)buf, "Serializer");
+        function->EndCall();
+    }
 
     return buf.GetBuffer();
 }
 
 PODVector<unsigned char> LuaScriptInstance::GetScriptNetworkDataAttr() const
 {
-    int functionRef = scriptObjectMethodRefs_[LSOM_WRITENETWORKUPDATE];
-    if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
+    if (scriptObjectRef_ == LUA_REFNIL)
+        return PODVector<unsigned char>();
+
+    LuaFunction* function = scriptObjectMethods_[LSOM_WRITENETWORKUPDATE];
+    if (!function)
         return PODVector<unsigned char>();
 
     VectorBuffer buf;
-    CallScriptObjectFunction(functionRef, (Serializer&)buf);
+    if (function->BeginCall(this))
+    {
+        function->PushUserType((Serializer&)buf, "Serializer");
+        function->EndCall();
+    }
 
     return buf.GetBuffer();
 }
 
-
 void LuaScriptInstance::FindScriptObjectMethodRefs()
 {
     for (unsigned i = 0; i < MAX_LUA_SCRIPT_OBJECT_METHODS; ++i)
-        scriptObjectMethodRefs_[i] = luaScript_->GetScriptFunctionRef(scriptObjectType_ + scriptObjectMethodNames[i], true);
+        scriptObjectMethods_[i] = GetScriptObjectFunction(scriptObjectMethodNames[i]);
 
     if (enabled_)
         SubscribeToScriptMethodEvents();
@@ -319,31 +319,31 @@ void LuaScriptInstance::FindScriptObjectMethodRefs()
 
 void LuaScriptInstance::SubscribeToScriptMethodEvents()
 {
-    if (scriptObjectMethodRefs_[LSOM_UPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_UPDATE])
         SubscribeToEvent(E_UPDATE, HANDLER(LuaScriptInstance, HandleUpdate));
 
-    if (scriptObjectMethodRefs_[LSOM_POSTUPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_POSTUPDATE])
         SubscribeToEvent(E_POSTUPDATE, HANDLER(LuaScriptInstance, HandlePostUpdate));
 
-    if (scriptObjectMethodRefs_[LSOM_FIXEDUPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_FIXEDUPDATE])
         SubscribeToEvent(E_PHYSICSPRESTEP, HANDLER(LuaScriptInstance, HandleFixedUpdate));
 
-    if (scriptObjectMethodRefs_[LSOM_FIXEDPOSTUPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_FIXEDPOSTUPDATE])
         SubscribeToEvent(E_PHYSICSPOSTSTEP, HANDLER(LuaScriptInstance, HandlePostFixedUpdate));
 }
 
 void LuaScriptInstance::UnsubscribeFromScriptMethodEvents()
 {
-    if (scriptObjectMethodRefs_[LSOM_UPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_UPDATE])
         UnsubscribeFromEvent(E_UPDATE);
 
-    if (scriptObjectMethodRefs_[LSOM_POSTUPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_POSTUPDATE])
         UnsubscribeFromEvent(E_POSTUPDATE);
 
-    if (scriptObjectMethodRefs_[LSOM_FIXEDUPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_FIXEDUPDATE])
         UnsubscribeFromEvent(E_PHYSICSPRESTEP);
 
-    if (scriptObjectMethodRefs_[LSOM_FIXEDPOSTUPDATE] != LUA_REFNIL)
+    if (scriptObjectMethods_[LSOM_FIXEDPOSTUPDATE])
         UnsubscribeFromEvent(E_PHYSICSPOSTSTEP);
 }
 
@@ -351,53 +351,75 @@ void LuaScriptInstance::HandleUpdate(StringHash eventType, VariantMap& eventData
 {
     using namespace Update;
     float timeStep = eventData[P_TIMESTEP].GetFloat();
-    CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_UPDATE], timeStep);
+
+    LuaFunction* function = scriptObjectMethods_[LSOM_UPDATE];
+    if (function && function->BeginCall(this))
+    {
+        function->PushFloat(timeStep);
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
 {
     using namespace PostUpdate;
     float timeStep = eventData[P_TIMESTEP].GetFloat();
-    CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_POSTUPDATE], timeStep);
+
+    LuaFunction* function = scriptObjectMethods_[LSOM_POSTUPDATE];
+    if (function && function->BeginCall(this))
+    {
+        function->PushFloat(timeStep);
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::HandleFixedUpdate(StringHash eventType, VariantMap& eventData)
 {
     using namespace PhysicsPreStep;
     float timeStep = eventData[P_TIMESTEP].GetFloat();
-    CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_FIXEDUPDATE], timeStep);
+
+    LuaFunction* function = scriptObjectMethods_[LSOM_FIXEDUPDATE];
+    if (function && function->BeginCall(this))
+    {
+        function->PushFloat(timeStep);
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::HandlePostFixedUpdate(StringHash eventType, VariantMap& eventData)
 {
     using namespace PhysicsPostStep;
     float timeStep = eventData[P_TIMESTEP].GetFloat();
-    CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_FIXEDPOSTUPDATE], timeStep);
+
+    LuaFunction* function = scriptObjectMethods_[LSOM_FIXEDPOSTUPDATE];
+    if (function && function->BeginCall(this))
+    {
+        function->PushFloat(timeStep);
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::HandleEvent(StringHash eventType, VariantMap& eventData)
 {
-    if (scriptObjectRef_ == LUA_REFNIL)
-        return;
-
-    int functionRef = eventTypeToFunctionRefMap_[eventType];
-    if (functionRef == LUA_REFNIL)
-        return;
-
-    CallScriptObjectFunction(functionRef, eventType, eventData);
+    LuaFunction* function = eventTypeToFunctionMap_[eventType];
+    if (function && function->BeginCall(this))
+    {
+        function->PushUserType(eventType, "StringHash");
+        function->PushUserType(eventData, "VariantMap");
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::HandleObjectEvent(StringHash eventType, VariantMap& eventData)
 {
-    if (scriptObjectRef_ == LUA_REFNIL)
-        return;
-
     Object* object = GetEventSender();
-    int functionRef = objectToEventTypeToFunctionRefMap_[object][eventType];
-    if (functionRef == LUA_REFNIL)
-        return;
-
-    CallScriptObjectFunction(functionRef, eventType, eventData);
+    LuaFunction* function = objectToEventTypeToFunctionMap_[object][eventType];
+    if (function && function->BeginCall(this))
+    {
+        function->PushUserType(eventType, "StringHash");
+        function->PushUserType(eventData, "VariantMap");
+        function->EndCall();
+    }
 }
 
 void LuaScriptInstance::ReleaseObject()
@@ -412,182 +434,17 @@ void LuaScriptInstance::ReleaseObject()
     luaL_unref(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
     scriptObjectRef_ = LUA_REFNIL;
 
-    int top = lua_gettop(luaState_);
-    lua_getglobal(luaState_, "DestroyScriptObjectInstance");
-    if (!lua_isfunction(luaState_, -1))
+    LuaFunction* function = luaScript_->GetFunction("DestroyScriptObjectInstance");
+    if (function && function->BeginCall())
     {
-        LOGERROR("Could not find lua function DestroyScriptObjectInstance");
-        lua_settop(luaState_, top);
-        return;
-    }
-
-    // Push this as second parameter.
-    tolua_pushusertype(luaState_, (void*)this, "LuaScriptInstance");
-    if (lua_pcall(luaState_, 1, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-    }
-}
-
-void LuaScriptInstance::CallScriptObjectFunction(int functionRef)
-{
-    if (functionRef == LUA_REFNIL)
-        return;
-
-    int top = lua_gettop(luaState_);
-
-    // Push function.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-
-    // Push script object.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
-
-    // Call script object function.
-    if (lua_pcall(luaState_, 1, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-        return;
-    }
-}
-
-void LuaScriptInstance::CallScriptObjectFunction(int functionRef, float timeStep)
-{
-    if (functionRef == LUA_REFNIL)
-        return;
-
-    int top = lua_gettop(luaState_);
-
-    // Push function.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-
-    // Push script object.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
-
-    // Push time step.
-    tolua_pushnumber(luaState_, timeStep);
-
-    // Call script object function.
-    if (lua_pcall(luaState_, 2, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-        return;
-    }
-}
-
-void LuaScriptInstance::CallScriptObjectFunction(int functionRef, Deserializer& deserializer)
-{
-    if (functionRef == LUA_REFNIL)
-        return;
-
-    int top = lua_gettop(luaState_);
-
-    // Push function.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-
-    // Push script object.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
-
-    // Push Deserializer.
-    tolua_pushusertype(luaState_, (void*)&deserializer, "Deserializer");
-
-    // Call script object function.
-    if (lua_pcall(luaState_, 2, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-    }
-}
-
-void LuaScriptInstance::CallScriptObjectFunction(int functionRef, Serializer& serializer) const
-{
-    if (functionRef == LUA_REFNIL)
-        return;
-
-    int top = lua_gettop(luaState_);
-
-    // Push function.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-
-    // Push script object.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
-
-    // Push Deserializer.
-    tolua_pushusertype(luaState_, (void*)&serializer, "Serializer");
-
-    // Call script object function.
-    if (lua_pcall(luaState_, 2, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-    }
-}
-
-void LuaScriptInstance::CallScriptObjectFunction(int functionRef, StringHash eventType, VariantMap& eventData)
-{
-    if (functionRef == LUA_REFNIL)
-        return;
-    
-    int top = lua_gettop(luaState_);
-
-    // Push function.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-
-    // Push script object.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
-
-    // Push event type.
-    tolua_pushusertype(luaState_, (void*)&eventType, "StringHash");
-
-    // Push event data.
-    tolua_pushusertype(luaState_, (void*)&eventData, "VariantMap");
-
-    // Call script object function.
-    if (lua_pcall(luaState_, 3, 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
+        function->PushUserType((void*)this, "LuaScriptInstance");
+        function->EndCall();
     }
 }
 
-bool LuaScriptInstance::CallScriptObjectFunction(int functionRef, const VariantVector& parameters)
+LuaFunction* LuaScriptInstance::GetScriptObjectFunction(const String& functionName)
 {
-    if (functionRef == LUA_REFNIL)
-        return false;
-
-    int top = lua_gettop(luaState_);
-
-    // Push function.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
-
-    // Push script object.
-    lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
-
-    // Push parameters.
-    if (!tolua_pushurho3dvariantvector(luaState_, parameters))
-    {
-        lua_settop(luaState_, top);
-        return false;
-    }
-    
-    // Call script object function.
-    if (lua_pcall(luaState_, 1 + parameters.Size(), 0, 0) != 0)
-    {
-        const char* message = lua_tostring(luaState_, -1);
-        LOGERROR("Execute Lua function failed: " + String(message));
-        lua_settop(luaState_, top);
-        return false;
-    }
-    
-    return true;
+    return luaScript_->GetFunction(scriptObjectType_ + "." + functionName, true);
 }
 
 }

+ 11 - 23
Source/Extras/LuaScript/LuaScriptInstance.h

@@ -30,13 +30,13 @@ namespace Urho3D
 {
 
 class LuaScript;
+class LuaFunction;
 
 /// Lua Script object methods.
 enum LuaScriptObjectMethod
 {
     LSOM_START = 0,
     LSOM_STOP,
-    // LSOM_DELAYEDSTART,
     LSOM_UPDATE,
     LSOM_POSTUPDATE,
     LSOM_FIXEDUPDATE,
@@ -91,9 +91,7 @@ public:
     void ScriptUnsubscribeFromEvent(void* sender, const String& eventName);
     /// Script unsubscribe from a specific sender's all events.
     void ScriptUnsubscribeFromEvents(void* sender);
-    /// Execute a script object function. Parameters can be supplied in a VariantVector. Return true if successful.
-    bool ExecuteFunction(const String& functionName, const VariantVector& parameters = Variant::emptyVariantVector);
-    
+
     /// Return script file name.
     const String& GetScriptFileName() const { return scriptFileName_; }
     /// Return script object type.
@@ -104,6 +102,8 @@ public:
     PODVector<unsigned char> GetScriptDataAttr() const;
     /// Get script network serialization attribute by calling a script function.
     PODVector<unsigned char> GetScriptNetworkDataAttr() const;
+    /// Return script object's funcition.
+    LuaFunction* GetScriptObjectFunction(const String& functionName);
 
 private:
     /// Find script object method refs.
@@ -126,19 +126,7 @@ private:
     void HandleObjectEvent(StringHash eventType, VariantMap& eventData);
     /// Release the script object.
     void ReleaseObject();
-    /// Call script object function.
-    void CallScriptObjectFunction(int functionRef);
-    /// Call script object function.
-    void CallScriptObjectFunction(int functionRef, float timeStep);
-    /// Call script object function.
-    void CallScriptObjectFunction(int functionRef, Deserializer& deserializer);
-    /// Call script object function.
-    void CallScriptObjectFunction(int functionRef, Serializer& serializer) const;
-    /// Call script object function.
-    void CallScriptObjectFunction(int functionRef, StringHash eventType, VariantMap& eventData);
-    /// Call script object function with arbitrary parameters.
-    bool CallScriptObjectFunction(int functionRef, const VariantVector& parameters);
-    
+
     // Lua Script subsystem.
     LuaScript* luaScript_;
     /// Lua state.
@@ -149,12 +137,12 @@ private:
     String scriptObjectType_;
     /// Script object ref.
     int scriptObjectRef_;
-    /// Script object method refs.
-    int scriptObjectMethodRefs_[MAX_LUA_SCRIPT_OBJECT_METHODS];
-    /// Event type to function ref map.
-    HashMap<StringHash, int> eventTypeToFunctionRefMap_;
-    /// Object to event type to function ref map.
-    HashMap<Object*, HashMap<StringHash, int> > objectToEventTypeToFunctionRefMap_;
+    /// Script object method.
+    LuaFunction* scriptObjectMethods_[MAX_LUA_SCRIPT_OBJECT_METHODS];
+    /// Event type to function map.
+    HashMap<StringHash, LuaFunction*> eventTypeToFunctionMap_;
+    /// Object to event type to function map.
+    HashMap<Object*, HashMap<StringHash, LuaFunction*> > objectToEventTypeToFunctionMap_;
 };
 
 }

+ 0 - 60
Source/Extras/LuaScript/ToluaUrho3DEx.cpp

@@ -45,63 +45,3 @@ int tolua_pushurho3dstringvector(lua_State* L, const Urho3D::Vector<Urho3D::Stri
     }
     return 1;
 }
-
-bool tolua_pushurho3dvariantvector(lua_State* L, const Urho3D::VariantVector& variants)
-{
-    using namespace Urho3D;
-    for (unsigned i = 0; i < variants.Size(); ++i)
-    {
-        switch (variants[i].GetType())
-        {
-        case VAR_INT:
-            tolua_pushnumber(L, (double)variants[i].GetInt());
-            break;
-
-        case VAR_BOOL:
-            tolua_pushboolean(L, variants[i].GetBool() ? 1 : 0);
-            break;
-
-        case VAR_FLOAT:
-            tolua_pushnumber(L, variants[i].GetFloat());
-            break;
-
-        case VAR_VECTOR2:
-            tolua_pushusertype(L, &const_cast<Vector2&>(variants[i].GetVector2()), variants[i].GetTypeName().CString());
-            break;
-
-        case VAR_VECTOR3:
-            tolua_pushusertype(L, &const_cast<Vector3&>(variants[i].GetVector3()), variants[i].GetTypeName().CString());
-            break;
-
-        case VAR_VECTOR4:
-            tolua_pushusertype(L, &const_cast<Vector4&>(variants[i].GetVector4()), variants[i].GetTypeName().CString());
-            break;
-
-        case VAR_QUATERNION:
-            tolua_pushusertype(L, &const_cast<Quaternion&>(variants[i].GetQuaternion()), variants[i].GetTypeName().CString());
-            break;
-
-        case VAR_COLOR:
-            tolua_pushusertype(L, &const_cast<Color&>(variants[i].GetColor()), variants[i].GetTypeName().CString());
-            break;
-        
-        case VAR_STRING:
-            tolua_pushurho3dstring(L, variants[i].GetString());
-            break;
-
-        case VAR_INTRECT:
-            tolua_pushusertype(L, &const_cast<IntRect&>(variants[i].GetIntRect()), variants[i].GetTypeName().CString());
-            break;
-
-        case VAR_INTVECTOR2:
-            tolua_pushusertype(L, &const_cast<IntVector2&>(variants[i].GetIntVector2()), variants[i].GetTypeName().CString());
-            break;
-
-        default:
-            LOGERROR("Unsupported data type");
-            return false;
-        }
-    }
-
-    return true;
-}

+ 0 - 2
Source/Extras/LuaScript/ToluaUrho3DEx.h

@@ -39,5 +39,3 @@ const char* tolua_tofieldurho3dstring(lua_State* L, int lo, int index, const Urh
 
 /// Push Urho3D string vector to Lua.
 int tolua_pushurho3dstringvector(lua_State* L, const Urho3D::Vector<Urho3D::String>& strings);
-/// Push Urho3D variant vector to Lua, if meet unsupported data type return false.
-bool tolua_pushurho3dvariantvector(lua_State* L, const Urho3D::VariantVector& variants);

+ 11 - 0
Source/Extras/LuaScript/pkgs/Audio/Sound.pkg

@@ -2,6 +2,17 @@ $#include "Sound.h"
 
 class Sound : public Resource
 {
+    Sound(Context* context);
+    ~Sound();
+    bool LoadRaw(Deserializer& source);
+    bool LoadWav(Deserializer& source);
+    bool LoadOggVorbis(Deserializer& source);
+    void SetSize(unsigned dataSize);
+    void SetData(const void* data, unsigned dataSize);
+    void SetFormat(unsigned frequency, bool sixteenBit, bool stereo);
+    void SetLooped(bool enable);
+    void SetLoop(unsigned repeatOffset, unsigned endOffset);
+    void FixInterpolation();
     float GetLength() const;
     unsigned GetDataSize() const;
     unsigned GetSampleSize() const;

+ 1 - 0
Source/Extras/LuaScript/pkgs/Audio/SoundListener.pkg

@@ -2,4 +2,5 @@ $#include "SoundListener.h"
 
 class SoundListener : public Component
 {
+
 };

+ 3 - 3
Source/Extras/LuaScript/pkgs/Audio/SoundSource.pkg

@@ -4,6 +4,7 @@ enum SoundType{};
 
 class SoundSource : public Component
 {
+
     void Play(Sound* sound);
     void Play(Sound* sound, float frequency);
     void Play(Sound* sound, float frequency, float gain);
@@ -15,10 +16,9 @@ class SoundSource : public Component
     void SetAttenuation(float attenuation);
     void SetPanning(float panning);
     void SetAutoRemove(bool enable);
-    // void SetPlayPosition(signed char* pos);
+
     
     Sound* GetSound() const;
-    // volatile signed char* GetPlayPosition() const;
     SoundType GetSoundType() const;
     float GetTimePosition() const;
     float GetFrequency() const;
@@ -31,7 +31,7 @@ class SoundSource : public Component
     void PlayLockless(Sound* sound);
     void StopLockless();
     void SetPlayPositionLockless(signed char* position);
-    void Mix(int* dest, unsigned samples, int mixRate, bool stereo, bool interpolation);
+
     
     tolua_readonly tolua_property__get_set Sound* sound;
     tolua_property__get_set SoundType soundType;

+ 12 - 0
Source/Extras/LuaScript/pkgs/Core/Context.pkg

@@ -24,6 +24,8 @@ class Context
 };
 
 Context* GetContext();
+Object* GetEventSender();
+EventHandler* GetEventHandler() const;
 
 Audio* GetAudio();
 Console* GetConsole();
@@ -42,6 +44,16 @@ Time* GetTime();
 UI* GetUI();
 
 ${
+static Object* GetEventSender()
+{
+    return GetContext()->GetEventSender();
+}
+
+static EventHandler* GetEventHandler()
+{
+    return GetContext()->GetEventHandler();
+}
+
 static Audio* GetAudio()
 {
     return GetContext()->GetSubsystem<Audio>();

+ 1 - 1
Source/Extras/LuaScript/pkgs/Core/ProcessUtils.pkg

@@ -5,7 +5,7 @@ void ErrorExit(const String message = String::EMPTY, int exitCode = EXIT_FAILURE
 void OpenConsoleWindow();
 void PrintLine(const String str, bool error = false);
 
-const Vector<String>& GetArguments();
+string* GetArguments();
 
 String GetConsoleInput();
 String GetPlatform();

+ 0 - 7
Source/Extras/LuaScript/pkgs/LuaScript/LuaScript.pkg

@@ -1,7 +1,5 @@
 $#include "LuaScript.h"
 
-Object* GetEventSender();
-
 void SendEvent(const String eventName, VariantMap& eventData);
 void SubscribeToEvent(const String eventName, const String functionName);
 void UnsubscribeFromEvent(const String eventName);
@@ -16,11 +14,6 @@ static LuaScript* GetLuaScript()
     return GetContext()->GetSubsystem<LuaScript>();
 }
 
-static Object* GetEventSender()
-{
-    return GetContext()->GetEventSender();
-}
-
 static void SendEvent(const String& eventName, VariantMap& eventData)
 {
     GetLuaScript()->ScriptSendEvent(eventName, eventData);

+ 1 - 1
Source/Extras/LuaScript/pkgs/Resource/ResourceCache.pkg

@@ -27,7 +27,7 @@ class ResourceCache
 };
 
 ${
-// Disable generated GetResource funciton.
+// Disable generated GetResource function.
 #define TOLUA_DISABLE_tolua_ResourceLuaAPI_ResourceCache_GetResource00
 
 static int tolua_ResourceLuaAPI_ResourceCache_GetResource00(lua_State* tolua_S)

+ 2 - 2
Source/Extras/LuaScript/pkgs/Scene/Node.pkg

@@ -350,7 +350,7 @@ static void NodeGetWorldScaleXYZ(const Node* node, float* x, float* y, float* z)
     *z =  worldScale.z_;
 }
 
-// Disable generated CreateComponent funciton.
+// Disable generated CreateComponent function.
 #define TOLUA_DISABLE_tolua_SceneLuaAPI_Node_CreateComponent00
 
 static int tolua_SceneLuaAPI_Node_CreateComponent00(lua_State* tolua_S)
@@ -388,7 +388,7 @@ static int tolua_SceneLuaAPI_Node_CreateComponent00(lua_State* tolua_S)
 #endif
 }
 
-// Disable generated GetComponent funciton.
+// Disable generated GetComponent function.
 #define TOLUA_DISABLE_tolua_SceneLuaAPI_Node_GetComponent00
 static int tolua_SceneLuaAPI_Node_GetComponent00(lua_State* tolua_S)
 {

+ 9 - 4
Source/Samples/22_LuaIntegration/LuaIntegration.cpp

@@ -26,6 +26,7 @@
 #include "Font.h"
 #include "Graphics.h"
 #include "Input.h"
+#include "LuaFunction.h"
 #include "LuaScript.h"
 #include "LuaScriptInstance.h"
 #include "Material.h"
@@ -110,10 +111,14 @@ void LuaIntegration::CreateScene()
         // rotate the scene node each frame, when the scene sends its update event
         LuaScriptInstance* instance = boxNode->CreateComponent<LuaScriptInstance>();
         instance->CreateObject("LuaScripts/Rotator.lua", "Rotator");
-        // Call the script object's "SetRotationSpeed" function. Function arguments need to be passed in a VariantVector
-        VariantVector parameters;
-        parameters.Push(Vector3(10.0f, 20.0f, 30.0f));
-        instance->ExecuteFunction("SetRotationSpeed", parameters);
+        
+        // Call the script object's "SetRotationSpeed" function.
+        LuaFunction* function = instance->GetScriptObjectFunction("SetRotationSpeed");
+        if (function && function->BeginCall(instance))
+        {
+            function->PushUserType(Vector3(10.0f, 20.0f, 30.0f), "Vector3");
+            function->EndCall();
+        }
     }
     
     // Create the camera. Let the starting position be at the world origin. As the fog limits maximum visible distance, we can

+ 1 - 1
Source/Tools/Urho3D/Urho3D.cpp

@@ -189,7 +189,7 @@ void Urho::Stop()
     else
     {
         LuaScript* luaScript = GetSubsystem<LuaScript>();
-        if (luaScript && luaScript->GetScriptFunctionRef("Stop", true) != -1) // -1 equals NIL reference
+        if (luaScript && luaScript->GetFunction("Stop", true))
             luaScript->ExecuteFunction("Stop");
     }
 #endif