2
0
Эх сурвалжийг харах

Merge branch 'next' of https://github.com/blackberry/GamePlay into next

Conflicts:
	gameplay/src/Control.cpp
Adam Blake 12 жил өмнө
parent
commit
ebb0e32c15

+ 2 - 0
gameplay/android/jni/Android.mk

@@ -180,6 +180,7 @@ LOCAL_SRC_FILES := \
     lua/lua_Global.cpp \
     lua/lua_HeightField.cpp \
     lua/lua_Image.cpp \
+    lua/lua_ImageControl.cpp \
     lua/lua_ImageFormat.cpp \
     lua/lua_Joint.cpp \
     lua/lua_Joystick.cpp \
@@ -262,6 +263,7 @@ LOCAL_SRC_FILES := \
     lua/lua_Technique.cpp \
     lua/lua_Terrain.cpp \
     lua/lua_TerrainFlags.cpp \
+    lua/lua_TerrainListener.cpp \
     lua/lua_TextBox.cpp \
     lua/lua_Texture.cpp \
     lua/lua_TextureFilter.cpp \

+ 70 - 26
gameplay/src/FileSystem.cpp

@@ -86,6 +86,27 @@ static bool androidFileExists(const char* filePath)
 static std::string __resourcePath("./");
 static std::map<std::string, std::string> __aliases;
 
+/**
+ * Gets the fully resolved path.
+ * If the path is relative then it will be prefixed with the resource path.
+ * Aliases will be converted to a relative path.
+ * 
+ * @param path The path to resolve.
+ * @param fullPath The full resolved path. (out param)
+ */
+static void getFullPath(const char* path, std::string& fullPath)
+{
+    if (FileSystem::isAbsolutePath(path))
+    {
+        fullPath.assign(path);
+    }
+    else
+    {
+        fullPath.assign(__resourcePath);
+        fullPath += FileSystem::resolvePath(path);
+    }
+}
+
 /**
  * 
  * @script{ignore}
@@ -259,30 +280,54 @@ bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
         path.append(dirPath);
     }
     path.append("/.");
+    bool result = false;
+
     struct dirent* dp;
     DIR* dir = opendir(path.c_str());
-    if (!dir)
+    if (dir != NULL)
     {
-        return false;
+        while ((dp = readdir(dir)) != NULL)
+        {
+            std::string filepath(path);
+            filepath.append("/");
+            filepath.append(dp->d_name);
+
+            struct stat buf;
+            if (!stat(filepath.c_str(), &buf))
+            {
+                // Add to the list if this is not a directory
+                if (!S_ISDIR(buf.st_mode))
+                {
+                    files.push_back(dp->d_name);
+                }
+            }
+        }
+        closedir(dir);
+        result = true;
     }
-    while ((dp = readdir(dir)) != NULL)
-    {
-        std::string filepath(path);
-        filepath.append("/");
-        filepath.append(dp->d_name);
 
-        struct stat buf;
-        if (!stat(filepath.c_str(), &buf))
+#ifdef __ANDROID__
+    // List the files that are in the android APK at this path
+    AAssetDir* assetDir = AAssetManager_openDir(__assetManager, dirPath);
+    if (assetDir != NULL)
+    {
+        AAssetDir_rewind(assetDir);
+        const char* file = NULL;
+        while ((file = AAssetDir_getNextFileName(assetDir)) != NULL)
         {
-            // Add to the list if this is not a directory
-            if (!S_ISDIR(buf.st_mode))
+            std::string filename(file);
+            // Check if this file was already added to the list because it was copied to the SD card.
+            if (find(files.begin(), files.end(), filename) == files.end())
             {
-                files.push_back(dp->d_name);
+                files.push_back(filename);
             }
         }
+        AAssetDir_close(assetDir);
+        result = true;
     }
-    closedir(dir);
-    return true;
+#endif
+
+    return result;
 #endif
 }
 
@@ -297,13 +342,13 @@ bool FileSystem::fileExists(const char* filePath)
     }
 #endif
 
-    std::string fullPath(__resourcePath);
-    fullPath += resolvePath(filePath);
+    std::string fullPath;
+    getFullPath(filePath, fullPath);
 
     gp_stat_struct s;
 
 #ifdef WIN32
-    if (stat(fullPath.c_str(), &s) != 0)
+    if (!isAbsolutePath(filePath) && stat(fullPath.c_str(), &s) != 0)
     {
         fullPath = __resourcePath;
         fullPath += "../../gameplay/";
@@ -352,12 +397,12 @@ Stream* FileSystem::open(const char* path, size_t mode)
         return FileStreamAndroid::create(resolvePath(path), modeStr);
     }
 #else
-    std::string fullPath(__resourcePath);
-    fullPath += resolvePath(path);
+    std::string fullPath;
+    getFullPath(path, fullPath);
     
 #ifdef WIN32
     gp_stat_struct s;
-    if (stat(fullPath.c_str(), &s) != 0 && (mode & WRITE) == 0)
+    if (!isAbsolutePath(path) && stat(fullPath.c_str(), &s) != 0 && (mode & WRITE) == 0)
     {
         fullPath = __resourcePath;
         fullPath += "../../gameplay/";
@@ -386,15 +431,15 @@ FILE* FileSystem::openFile(const char* filePath, const char* mode)
     GP_ASSERT(filePath);
     GP_ASSERT(mode);
 
-    std::string fullPath(__resourcePath);
-    fullPath += resolvePath(filePath);
+    std::string fullPath;
+    getFullPath(filePath, fullPath);
 
     createFileFromAsset(filePath);
     
     FILE* fp = fopen(fullPath.c_str(), mode);
     
 #ifdef WIN32
-    if (fp == NULL)
+    if (fp == NULL && !isAbsolutePath(filePath))
     {
         fullPath = __resourcePath;
         fullPath += "../../gameplay/";
@@ -452,11 +497,10 @@ bool FileSystem::isAbsolutePath(const char* filePath)
     if (filePath == 0 || filePath[0] == '\0')
         return false;
 #ifdef WIN32
-    if (strlen(filePath) >= 2)
+    if (filePath[1] != '\0')
     {
         char first = filePath[0];
-        if (filePath[1] == ':' && ((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')))
-            return true;
+        return (filePath[1] == ':' && ((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')));
     }
     return false;
 #else

+ 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());
                 }
             }
         }

+ 6 - 3
gameplay/src/ImageControl.cpp

@@ -85,7 +85,7 @@ void ImageControl::setRegionSrc(float x, float y, float width, float height)
     _uvs.u1 = x * _tw;
     _uvs.u2 = (x + width) * _tw;
     _uvs.v1 = 1.0f - (y * _th);
-    _uvs.v2 = 1.0f - ((y + height) * _tw);
+    _uvs.v2 = 1.0f - ((y + height) * _th);
 }
 
 void ImageControl::setRegionSrc(const Rectangle& region)
@@ -120,17 +120,20 @@ void ImageControl::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
     // An ImageControl is not part of the texture atlas but should use the same projection matrix.
     _batch->setProjectionMatrix(spriteBatch->getProjectionMatrix());
 
+    Vector4 color = Vector4::one();
+    color.w *= _opacity;
+
     _batch->start();
     if (_dstRegion.isEmpty())
     {
         _batch->draw(_viewportBounds.x, _viewportBounds.y, _viewportBounds.width, _viewportBounds.height,
-            _uvs.u1, _uvs.v1, _uvs.u2, _uvs.v2, Vector4::one(), _viewportClipBounds);
+            _uvs.u1, _uvs.v1, _uvs.u2, _uvs.v2, color, _viewportClipBounds);
     }
     else
     {
         _batch->draw(_viewportBounds.x + _dstRegion.x, _viewportBounds.y + _dstRegion.y,
             _dstRegion.width, _dstRegion.height,
-            _uvs.u1, _uvs.v1, _uvs.u2, _uvs.v2, Vector4::one(), _viewportClipBounds);
+            _uvs.u1, _uvs.v1, _uvs.u2, _uvs.v2, color, _viewportClipBounds);
     }
     _batch->finish();
 

+ 56 - 53
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 = 
@@ -657,7 +652,6 @@ static const char* lua_print_function =
     "    ScriptController.print(table.concat({...},\"\\t\"), \"\\n\")\n"
     "end\n";
 
-#ifndef WIN32 
 static const char* lua_loadfile_function = 
     "do\n"
     "    local oldLoadfile = loadfile\n"
@@ -681,7 +675,6 @@ static const char* lua_dofile_function =
     "        return oldDofile(filename)\n"
     "    end\n"
     "end\n";
-#endif
 
 void ScriptController::initialize()
 {
@@ -699,21 +692,18 @@ void ScriptController::initialize()
     if (luaL_dostring(_lua, lua_print_function))
         GP_ERROR("Failed to load custom print() function with error: '%s'.", lua_tostring(_lua, -1));
 
-#ifndef WIN32
     // Change the functions that read a file to use FileSystem.getResourcePath as their base path.
     if (luaL_dostring(_lua, lua_loadfile_function))
         GP_ERROR("Failed to load custom loadfile() function with error: '%s'.", lua_tostring(_lua, -1));
     if (luaL_dostring(_lua, lua_dofile_function))
         GP_ERROR("Failed to load custom dofile() function with error: '%s'.", lua_tostring(_lua, -1));
-#endif
 }
 
 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 +717,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 +736,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, unsigned int analogIndex)
 {
-    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 +915,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)
+{
+    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)
 {
-    SAFE_DELETE(_callbacks[callback]);
-    _callbacks[callback] = new std::string(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

@@ -350,6 +350,7 @@ class ScriptController
     friend class Platform;
 
 public:
+
     /**
      * Loads the given script file and executes its global code.
      * 
@@ -367,6 +368,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.
      * 
@@ -733,7 +758,7 @@ public:
 private:
 
     /**
-     * Represents a Lua callback function binding.
+     * Represents a callback function that can be registered for.
      */
     enum ScriptCallback
     {
@@ -876,14 +901,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.
@@ -946,7 +963,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;
 };

+ 1 - 1
gameplay/src/Theme.cpp

@@ -509,7 +509,7 @@ const Theme::UVs& Theme::UVs::empty()
 
 const Theme::UVs& Theme::UVs::full()
 {
-    static UVs full(0, 0, 1, 1);
+    static UVs full(0, 1, 1, 0);
     return full;
 }
 

+ 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();