Bläddra i källkod

Added public methods on ScriptController for registering and unregistering global script callback functions (i.e. initiailze, finalize, update, render, touchEvent, keyEvent, etc). Multiple registered functions per callback are now supported and scripts can register themselves.
Updated gameplay lua script bindings.

Steve Grenier 12 år sedan
förälder
incheckning
bcf4fd0242

+ 11 - 19
gameplay/src/Game.cpp

@@ -123,30 +123,22 @@ bool Game::startup()
         Properties* scripts = _properties->getNamespace("scripts", true);
         if (scripts)
         {
-            const char* name;
-            while ((name = scripts->getNextProperty()) != NULL)
+            const char* callback;
+            while ((callback = scripts->getNextProperty()) != NULL)
             {
-                ScriptController::ScriptCallback callback = ScriptController::toCallback(name);
-                if (callback != ScriptController::INVALID_CALLBACK)
+                std::string url = scripts->getString();
+                std::string file;
+                std::string id;
+                splitURL(url, &file, &id);
+
+                if (file.size() <= 0 || id.size() <= 0)
                 {
-                    std::string url = scripts->getString();
-                    std::string file;
-                    std::string id;
-                    splitURL(url, &file, &id);
-
-                    if (file.size() <= 0 || id.size() <= 0)
-                    {
-                        GP_ERROR("Invalid %s script callback function '%s'.", name, url.c_str());
-                    }
-                    else
-                    {
-                        _scriptController->loadScript(file.c_str());
-                        _scriptController->registerCallback(callback, id);
-                    }
+                    GP_ERROR("Invalid %s script callback function '%s'.", callback, url.c_str());
                 }
                 else
                 {
-                    // Ignore everything else.
+                    _scriptController->loadScript(file.c_str());
+                    _scriptController->registerCallback(callback, id.c_str());
                 }
             }
         }

+ 56 - 49
gameplay/src/ScriptController.cpp

@@ -641,15 +641,10 @@ void ScriptController::print(const char* str1, const char* str2)
 
 ScriptController::ScriptController() : _lua(NULL)
 {
-    memset(_callbacks, 0, sizeof(std::string*) * CALLBACK_COUNT);
 }
 
 ScriptController::~ScriptController()
 {
-    for (unsigned int i = 0; i < CALLBACK_COUNT; i++)
-    {
-        SAFE_DELETE(_callbacks[i]);
-    }
 }
 
 static const char* lua_print_function = 
@@ -710,10 +705,9 @@ void ScriptController::initialize()
 
 void ScriptController::initializeGame()
 {
-    if (_callbacks[INITIALIZE])
-    {
-        executeFunction<void>(_callbacks[INITIALIZE]->c_str());
-    }
+    std::vector<std::string>& list = _callbacks[INITIALIZE];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str());
 }
 
 void ScriptController::finalize()
@@ -727,21 +721,15 @@ void ScriptController::finalize()
 
 void ScriptController::finalizeGame()
 {
-	std::string finalizeCallback;
-	if (_callbacks[FINALIZE])
-		finalizeCallback = _callbacks[FINALIZE]->c_str();
+    std::vector<std::string> finalizeCallbacks = _callbacks[FINALIZE]; // no & : makes a copy of the vector
 
 	// Remove any registered callbacks so they don't get called after shutdown
 	for (unsigned int i = 0; i < CALLBACK_COUNT; i++)
-    {
-        SAFE_DELETE(_callbacks[i]);
-    }
+        _callbacks[i].clear();
 
-	// Fire script finalize callback
-    if (!finalizeCallback.empty())
-	{
-        executeFunction<void>(finalizeCallback.c_str());
-    }
+	// Fire script finalize callbacks
+    for (size_t i = 0, count = finalizeCallbacks.size(); i < count; ++i)
+        executeFunction<void>(finalizeCallbacks[i].c_str());
 
     // Perform a full garbage collection cycle.
 	// Note that this does NOT free any global variables declared in scripts, since 
@@ -752,59 +740,55 @@ void ScriptController::finalizeGame()
 
 void ScriptController::update(float elapsedTime)
 {
-    if (_callbacks[UPDATE])
-    {
-        executeFunction<void>(_callbacks[UPDATE]->c_str(), "f", elapsedTime);
-    }
+    std::vector<std::string>& list = _callbacks[UPDATE];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str(), "f", elapsedTime);
 }
 
 void ScriptController::render(float elapsedTime)
 {
-    if (_callbacks[RENDER])
-    {
-        executeFunction<void>(_callbacks[RENDER]->c_str(), "f", elapsedTime);
-    }
+    std::vector<std::string>& list = _callbacks[RENDER];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str(), "f", elapsedTime);
 }
 
 void ScriptController::resizeEvent(unsigned int width, unsigned int height)
 {
-    if (_callbacks[RESIZE_EVENT])
-    {
-        executeFunction<void>(_callbacks[RESIZE_EVENT]->c_str(), "uiui", width, height);
-    }
+    std::vector<std::string>& list = _callbacks[RESIZE_EVENT];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str(), "uiui", width, height);
 }
 
 void ScriptController::keyEvent(Keyboard::KeyEvent evt, int key)
 {
-    if (_callbacks[KEY_EVENT])
-    {
-        executeFunction<void>(_callbacks[KEY_EVENT]->c_str(), "[Keyboard::KeyEvent][Keyboard::Key]", evt, key);
-    }
+    std::vector<std::string>& list = _callbacks[KEY_EVENT];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str(), "[Keyboard::KeyEvent][Keyboard::Key]", evt, key);
 }
 
 void ScriptController::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
-    if (_callbacks[TOUCH_EVENT])
-    {
-        executeFunction<void>(_callbacks[TOUCH_EVENT]->c_str(), "[Touch::TouchEvent]iiui", evt, x, y, contactIndex);
-    }
+    std::vector<std::string>& list = _callbacks[TOUCH_EVENT];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str(), "[Touch::TouchEvent]iiui", evt, x, y, contactIndex);
 }
 
 bool ScriptController::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 {
-    if (_callbacks[MOUSE_EVENT])
+    std::vector<std::string>& list = _callbacks[MOUSE_EVENT];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
     {
-        return executeFunction<bool>(_callbacks[MOUSE_EVENT]->c_str(), "[Mouse::MouseEvent]iii", evt, x, y, wheelDelta);
+        if (executeFunction<bool>(list[i].c_str(), "[Mouse::MouseEvent]iii", evt, x, y, wheelDelta))
+            return true;
     }
     return false;
 }
 
 void ScriptController::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
 {
-    if (_callbacks[GAMEPAD_EVENT])
-    {
-        executeFunction<void>(_callbacks[GAMEPAD_EVENT]->c_str(), "[Gamepad::GamepadEvent]<Gamepad>", evt, gamepad);
-    }
+    std::vector<std::string>& list = _callbacks[GAMEPAD_EVENT];
+    for (size_t i = 0, count = list.size(); i < count; ++i)
+        executeFunction<void>(list[i].c_str(), "[Gamepad::GamepadEvent]<Gamepad>", evt, gamepad);
 }
 
 void ScriptController::executeFunctionHelper(int resultCount, const char* func, const char* args, va_list* list)
@@ -935,10 +919,33 @@ void ScriptController::executeFunctionHelper(int resultCount, const char* func,
         GP_WARN("Failed to call function '%s' with error '%s'.", func, lua_tostring(_lua, -1));
 }
 
-void ScriptController::registerCallback(ScriptCallback callback, const std::string& function)
+void ScriptController::registerCallback(const char* callback, const char* function)
 {
-    SAFE_DELETE(_callbacks[callback]);
-    _callbacks[callback] = new std::string(function);
+    ScriptCallback scb = toCallback(callback);
+    if (scb < INVALID_CALLBACK)
+    {
+        _callbacks[scb].push_back(function);
+    }
+    else
+    {
+        GP_WARN("Invalid script callback function specified: %s", callback);
+    }
+}
+
+void ScriptController::unregisterCallback(const char* callback, const char* function)
+{
+    ScriptCallback scb = toCallback(callback);
+    if (scb < INVALID_CALLBACK)
+    {
+        std::vector<std::string>& list = _callbacks[scb];
+        std::vector<std::string>::iterator itr = std::find(list.begin(), list.end(), std::string(function));
+        if (itr != list.end())
+            list.erase(itr);
+    }
+    else
+    {
+        GP_WARN("Invalid script callback function specified: %s", callback);
+    }
 }
 
 ScriptController::ScriptCallback ScriptController::toCallback(const char* name)

+ 27 - 10
gameplay/src/ScriptController.h

@@ -349,6 +349,7 @@ class ScriptController
     friend class Platform;
 
 public:
+
     /**
      * Loads the given script file and executes its global code.
      * 
@@ -366,6 +367,30 @@ public:
      */
     std::string loadUrl(const char* url);
 
+    /**
+     * Registers the given script callback.
+     *
+     * The 'callback' parameter must be one of the supported global callback
+     * event functions. The following strings are accepted: initialize, finalize,
+     * update, render, resizeEvent, keyEvent, touchEvent, mouseEvent, gamepadEvent.
+     * Signatures for the registered script function must match that of the
+     * corresponding signatures of these events on the Game class.
+     *
+     * @param callback The script callback to register for.
+     * @param function The name of the script function to register.
+     */
+    void registerCallback(const char* callback, const char* function);
+
+    /**
+     * Unregisters the given script callback.
+     *
+     * @param callback The script callback to unregister for.
+     * @param function The name of the script function to unregister.
+     *
+     * @see registerCallback(const char*, const char*)
+     */
+    void unregisterCallback(const char* callback, const char* function);
+
     /**
      * Calls the specified no-parameter Lua function.
      * 
@@ -732,7 +757,7 @@ public:
 private:
 
     /**
-     * Represents a Lua callback function binding.
+     * Represents a callback function that can be registered for.
      */
     enum ScriptCallback
     {
@@ -875,14 +900,6 @@ private:
      */
     void executeFunctionHelper(int resultCount, const char* func, const char* args, va_list* list);
 
-    /**
-     * Registers the given script callback.
-     * 
-     * @param callback The script callback to register for.
-     * @param function The name of the function within the Lua script to call.
-     */
-    void registerCallback(ScriptCallback callback, const std::string& function);
-
     /**
      * Converts the given string to a valid script callback enumeration value
      * or to ScriptController::INVALID_CALLBACK if there is no valid conversion.
@@ -945,7 +962,7 @@ private:
     lua_State* _lua;
     unsigned int _returnCount;
     std::map<std::string, std::vector<std::string> > _hierarchy;
-    std::string* _callbacks[CALLBACK_COUNT];
+    std::vector<std::string> _callbacks[CALLBACK_COUNT];
     std::set<std::string> _loadedScripts;
     std::vector<luaStringEnumConversionFunction> _stringFromEnum;
 };

+ 76 - 0
gameplay/src/lua/lua_Camera.cpp

@@ -41,10 +41,12 @@ void luaRegister_Camera()
         {"pickRay", lua_Camera_pickRay},
         {"project", lua_Camera_project},
         {"release", lua_Camera_release},
+        {"resetProjectionMatrix", lua_Camera_resetProjectionMatrix},
         {"setAspectRatio", lua_Camera_setAspectRatio},
         {"setFarPlane", lua_Camera_setFarPlane},
         {"setFieldOfView", lua_Camera_setFieldOfView},
         {"setNearPlane", lua_Camera_setNearPlane},
+        {"setProjectionMatrix", lua_Camera_setProjectionMatrix},
         {"setZoomX", lua_Camera_setZoomX},
         {"setZoomY", lua_Camera_setZoomY},
         {"unproject", lua_Camera_unproject},
@@ -925,6 +927,38 @@ int lua_Camera_release(lua_State* state)
     return 0;
 }
 
+int lua_Camera_resetProjectionMatrix(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                Camera* instance = getInstance(state);
+                instance->resetProjectionMatrix();
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_Camera_resetProjectionMatrix - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Camera_setAspectRatio(lua_State* state)
 {
     // Get the number of parameters.
@@ -1069,6 +1103,48 @@ int lua_Camera_setNearPlane(lua_State* state)
     return 0;
 }
 
+int lua_Camera_setProjectionMatrix(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                bool param1Valid;
+                gameplay::ScriptUtil::LuaArray<Matrix> param1 = gameplay::ScriptUtil::getObjectPointer<Matrix>(2, "Matrix", true, &param1Valid);
+                if (!param1Valid)
+                {
+                    lua_pushstring(state, "Failed to convert parameter 1 to type 'Matrix'.");
+                    lua_error(state);
+                }
+
+                Camera* instance = getInstance(state);
+                instance->setProjectionMatrix(*param1);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_Camera_setProjectionMatrix - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Camera_setZoomX(lua_State* state)
 {
     // Get the number of parameters.

+ 2 - 0
gameplay/src/lua/lua_Camera.h

@@ -25,10 +25,12 @@ int lua_Camera_getZoomY(lua_State* state);
 int lua_Camera_pickRay(lua_State* state);
 int lua_Camera_project(lua_State* state);
 int lua_Camera_release(lua_State* state);
+int lua_Camera_resetProjectionMatrix(lua_State* state);
 int lua_Camera_setAspectRatio(lua_State* state);
 int lua_Camera_setFarPlane(lua_State* state);
 int lua_Camera_setFieldOfView(lua_State* state);
 int lua_Camera_setNearPlane(lua_State* state);
+int lua_Camera_setProjectionMatrix(lua_State* state);
 int lua_Camera_setZoomX(lua_State* state);
 int lua_Camera_setZoomY(lua_State* state);
 int lua_Camera_static_create(lua_State* state);

+ 38 - 0
gameplay/src/lua/lua_FrameBuffer.cpp

@@ -32,6 +32,7 @@ void luaRegister_FrameBuffer()
     {
         {"bindDefault", lua_FrameBuffer_static_bindDefault},
         {"create", lua_FrameBuffer_static_create},
+        {"getCurrent", lua_FrameBuffer_static_getCurrent},
         {"getFrameBuffer", lua_FrameBuffer_static_getFrameBuffer},
         {"getMaxRenderTargets", lua_FrameBuffer_static_getMaxRenderTargets},
         {NULL, NULL}
@@ -759,6 +760,43 @@ int lua_FrameBuffer_static_create(lua_State* state)
     return 0;
 }
 
+int lua_FrameBuffer_static_getCurrent(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 0:
+        {
+            void* returnPtr = (void*)FrameBuffer::getCurrent();
+            if (returnPtr)
+            {
+                gameplay::ScriptUtil::LuaObject* object = (gameplay::ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(gameplay::ScriptUtil::LuaObject));
+                object->instance = returnPtr;
+                object->owns = false;
+                luaL_getmetatable(state, "FrameBuffer");
+                lua_setmetatable(state, -2);
+            }
+            else
+            {
+                lua_pushnil(state);
+            }
+
+            return 1;
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 0).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_FrameBuffer_static_getFrameBuffer(lua_State* state)
 {
     // Get the number of parameters.

+ 1 - 0
gameplay/src/lua/lua_FrameBuffer.h

@@ -21,6 +21,7 @@ int lua_FrameBuffer_setDepthStencilTarget(lua_State* state);
 int lua_FrameBuffer_setRenderTarget(lua_State* state);
 int lua_FrameBuffer_static_bindDefault(lua_State* state);
 int lua_FrameBuffer_static_create(lua_State* state);
+int lua_FrameBuffer_static_getCurrent(lua_State* state);
 int lua_FrameBuffer_static_getFrameBuffer(lua_State* state);
 int lua_FrameBuffer_static_getMaxRenderTargets(lua_State* state);
 

+ 82 - 0
gameplay/src/lua/lua_ScriptController.cpp

@@ -14,6 +14,8 @@ void luaRegister_ScriptController()
     {
         {"loadScript", lua_ScriptController_loadScript},
         {"loadUrl", lua_ScriptController_loadUrl},
+        {"registerCallback", lua_ScriptController_registerCallback},
+        {"unregisterCallback", lua_ScriptController_unregisterCallback},
         {NULL, NULL}
     };
     const luaL_Reg lua_statics[] = 
@@ -130,6 +132,46 @@ int lua_ScriptController_loadUrl(lua_State* state)
     return 0;
 }
 
+int lua_ScriptController_registerCallback(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL) &&
+                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = gameplay::ScriptUtil::getString(2, false);
+
+                // Get parameter 2 off the stack.
+                const char* param2 = gameplay::ScriptUtil::getString(3, false);
+
+                ScriptController* instance = getInstance(state);
+                instance->registerCallback(param1, param2);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_ScriptController_registerCallback - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_ScriptController_static_print(lua_State* state)
 {
     // Get the number of parameters.
@@ -190,4 +232,44 @@ int lua_ScriptController_static_print(lua_State* state)
     return 0;
 }
 
+int lua_ScriptController_unregisterCallback(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL) &&
+                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = gameplay::ScriptUtil::getString(2, false);
+
+                // Get parameter 2 off the stack.
+                const char* param2 = gameplay::ScriptUtil::getString(3, false);
+
+                ScriptController* instance = getInstance(state);
+                instance->unregisterCallback(param1, param2);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_ScriptController_unregisterCallback - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 }

+ 2 - 0
gameplay/src/lua/lua_ScriptController.h

@@ -7,7 +7,9 @@ namespace gameplay
 // Lua bindings for ScriptController.
 int lua_ScriptController_loadScript(lua_State* state);
 int lua_ScriptController_loadUrl(lua_State* state);
+int lua_ScriptController_registerCallback(lua_State* state);
 int lua_ScriptController_static_print(lua_State* state);
+int lua_ScriptController_unregisterCallback(lua_State* state);
 
 void luaRegister_ScriptController();