diff --git a/lua/cocos2dx_support/CCLuaEngine.cpp b/lua/cocos2dx_support/CCLuaEngine.cpp new file mode 100644 index 0000000000..d807f5252c --- /dev/null +++ b/lua/cocos2dx_support/CCLuaEngine.cpp @@ -0,0 +1,306 @@ +/**************************************************************************** + Copyright (c) 2011 cocos2d-x.org + + http://www.cocos2d-x.org + + 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 "CCLuaEngine.h" +#include "tolua++.h" +#include "tolua_fix.h" + +extern "C" { +#include "lualib.h" +#include "lauxlib.h" +#include "lualoadexts.h" +} + +#include "LuaCocos2d.h" +#include "LuaGameInterfaces.h" +#include "CCArray.h" +#include "CCTimer.h" + +namespace cocos2d +{ + +CCSchedulerFuncEntry* CCSchedulerFuncEntry::entryWithFunctionRefID(int functionRefID, ccTime fInterval, bool bPaused) +{ + CCSchedulerFuncEntry* entry = new CCSchedulerFuncEntry(); + entry->initWithFunctionRefID(functionRefID, fInterval, bPaused); + entry->autorelease(); + return entry; +} + +bool CCSchedulerFuncEntry::initWithFunctionRefID(int functionRefID, ccTime fInterval, bool bPaused) +{ + m_timer = new CCTimer(); + m_timer->initWithScriptFunc(functionRefID, fInterval); + m_timer->autorelease(); + m_timer->retain(); + m_functionRefID = functionRefID; + m_paused = bPaused; + LUALOG("[LUA] ADD function refID: %04d, add schedule entryID: %d", m_functionRefID, m_entryID); + return true; +} + +CCSchedulerFuncEntry::CCSchedulerFuncEntry(void) +: m_timer(NULL) +, m_functionRefID(0) +, m_paused(true) +, m_isMarkDeleted(false) +{ + static int entryIDCount = 0; + ++entryIDCount; + m_entryID = entryIDCount; +} + +CCSchedulerFuncEntry::~CCSchedulerFuncEntry(void) +{ + m_timer->release(); + CCLuaEngine::sharedEngine()->removeLuaFunctionRef(m_functionRefID); + LUALOG("[LUA] DEL function refID: %04d, remove schedule entryID: %d", m_functionRefID, m_entryID); +} + +// ---------------------------- + + +CCLuaEngine* CCLuaEngine::s_engine = NULL; + +CCLuaEngine::CCLuaEngine() +{ + m_state = lua_open(); + luaL_openlibs(m_state); + tolua_Cocos2d_open(m_state); + tolua_prepare_ccobject_table(m_state); + tolua_LuaGameInterfaces_open(m_state); + luax_loadexts(m_state); +} + +CCLuaEngine::~CCLuaEngine() +{ + lua_close(m_state); + s_engine = NULL; +} + +CCLuaEngine* CCLuaEngine::sharedEngine() +{ + if (!s_engine) + { + s_engine = new CCLuaEngine(); + } + return s_engine; +} + +void CCLuaEngine::purgeSharedEngine() +{ + if (s_engine) delete s_engine; +} + +// ------------------------------------------- + +void CCLuaEngine::removeCCObject(CCObject *object) +{ + tolua_remove_ccobject_by_refid(m_state, object->m_refID); +} + +void CCLuaEngine::removeLuaFunctionRef(int functionRefID) +{ + tolua_remove_function_by_refid(m_state, functionRefID); +} + +void CCLuaEngine::addSearchPath(const char* path) +{ + lua_getglobal(m_state, "package"); /* stack: package */ + lua_getfield(m_state, -1, "path"); /* get package.path, stack: package path */ + const char* cur_path = lua_tostring(m_state, -1); + lua_pop(m_state, 1); /* stack: package */ + lua_pushfstring(m_state, "%s;%s/?.lua", cur_path, path); /* stack: package newpath */ + lua_setfield(m_state, -2, "path"); /* package.path = newpath, stack: package */ + lua_pop(m_state, 1); /* stack: - */ +} + +int CCLuaEngine::executeScriptFile(const char* filename) +{ + int nRet = luaL_dofile(m_state, filename); +// lua_gc(m_state, LUA_GCCOLLECT, 0); + + if (nRet != 0) + { + CCLOG("[LUA ERROR] %s", lua_tostring(m_state, -1)); + lua_pop(m_state, 1); + return nRet; + } + return 0; +} + +int CCLuaEngine::executeGlobalFunction(const char* function_name) +{ + lua_getglobal(m_state, function_name); /* query function by name, stack: function */ + if (!lua_isfunction(m_state, -1)) + { + CCLOG("[LUA ERROR] name '%s' does not represent a Lua function", function_name); + lua_pop(m_state, 1); + return 0; + } + + int error = lua_pcall(m_state, 0, 1, 0); /* call function, stack: ret */ +// lua_gc(m_state, LUA_GCCOLLECT, 0); + + if (error) + { + CCLOG("[LUA ERROR] %s", lua_tostring(m_state, - 1)); + lua_pop(m_state, 1); // clean error message + return 0; + } + + // get return value + if (!lua_isnumber(m_state, -1)) + { + lua_pop(m_state, 1); + return 0; + } + + int ret = lua_tointeger(m_state, -1); + lua_pop(m_state, 1); /* stack: - */ + return ret; +} + +int CCLuaEngine::executeFunctionByRefID(int functionRefId, int numArgs) +{ + lua_pushstring(m_state, TOLUA_REFID_FUNC_MAPPING); + lua_rawget(m_state, LUA_REGISTRYINDEX); /* stack: ... refid_func */ + lua_pushinteger(m_state, functionRefId); /* stack: ... refid_func refid */ + lua_rawget(m_state, -2); /* stack: ... refid_func func */ + + if (!lua_isfunction(m_state, -1)) + { + CCLOG("[LUA ERROR] function refid '%d' does not reference a Lua function", functionRefId); + lua_pop(m_state, 2 + numArgs); + return 0; + } + + if (numArgs > 0) + { + // [a1] [a2] refid_func func + // -4 -3 -2 -1 + // [a1] [a2] refid_func func [a1] + // -5 -4 -3 -2 -1 + int lo = -2 - numArgs; + for (int i = 0; i < numArgs; i++) + { + tolua_pushvalue(m_state, lo); /* stack: ... refid_func func (...) */ + } + } + + int error = 0; + try + { + error = lua_pcall(m_state, numArgs, 1, 0); /* stack: ... refid_func ret */ + } + catch (exception& e) + { + CCLOG("[LUA ERROR] lua_pcall(%d) catch C++ exception: %s", functionRefId, e.what()); + lua_settop(m_state, 0); + return 0; + } + catch (...) + { + CCLOG("[LUA ERROR] lua_pcall(%d) catch C++ unknown exception.", functionRefId); + lua_settop(m_state, 0); + return 0; + } + if (error) + { + CCLOG("[LUA ERROR] %s", lua_tostring(m_state, - 1)); + lua_pop(m_state, 2 + numArgs); // clean error message + return 0; + } + + // get return value + int ret = 0; + if (lua_isnumber(m_state, -1)) + { + ret = lua_tointeger(m_state, -1); + } + else if (lua_isboolean(m_state, -1)) + { + ret = lua_toboolean(m_state, -1); + } + + lua_pop(m_state, 2 + numArgs); + return ret; +} + +int CCLuaEngine::executeFunctionWithIntegerData(int functionRefId, int data) +{ + lua_pushinteger(m_state, data); + return executeFunctionByRefID(functionRefId, 1); +} + +int CCLuaEngine::executeFunctionWithFloatData(int functionRefId, float data) +{ + lua_pushnumber(m_state, data); + return executeFunctionByRefID(functionRefId, 1); +} + +int CCLuaEngine::executeFunctionWithBooleanData(int functionRefId, bool data) +{ + lua_pushboolean(m_state, data); + return executeFunctionByRefID(functionRefId, 1); +} + +// functions for excute touch event +int CCLuaEngine::executeTouchEvent(int functionRefId, int eventType, CCTouch *pTouch) +{ + CCPoint pt = CCDirector::sharedDirector()->convertToGL(pTouch->locationInView(pTouch->view())); + lua_pushinteger(m_state, eventType); + lua_pushnumber(m_state, pt.x); + lua_pushnumber(m_state, pt.y); + return executeFunctionByRefID(functionRefId, 3); +} + +int CCLuaEngine::executeTouchesEvent(int functionRefId, int eventType, CCSet *pTouches) +{ + lua_pushinteger(m_state, eventType); + lua_newtable(m_state); + + CCSetIterator it = pTouches->begin(); + CCTouch* touch; + int n = 1; + while (it != pTouches->end()) + { + touch = (CCTouch*)*it; + const CCPoint& pos = touch->locationInView(0); + lua_pushnumber(m_state, pos.x); + lua_rawseti(m_state, -2, n++); + lua_pushnumber(m_state, pos.y); + lua_rawseti(m_state, -2, n++); + ++it; + } + + return executeFunctionByRefID(functionRefId, 2); +} + +int CCLuaEngine::executeSchedule(int functionRefID, ccTime dt) +{ + return executeFunctionWithFloatData(functionRefID, dt); +} + +} // namespace cocos2d diff --git a/lua/cocos2dx_support/CCLuaEngine.h b/lua/cocos2dx_support/CCLuaEngine.h new file mode 100644 index 0000000000..35c4be7d02 --- /dev/null +++ b/lua/cocos2dx_support/CCLuaEngine.h @@ -0,0 +1,165 @@ +/**************************************************************************** + Copyright (c) 2011 cocos2d-x.org + + http://www.cocos2d-x.org + + 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. + ****************************************************************************/ +#ifndef __LUA_ENGINE_H__ +#define __LUA_ENGINE_H__ + +extern "C" { +#include "lua.h" +} + +#include "ccTypes.h" +#include "CCObject.h" +#include "CCTouch.h" +#include "CCSet.h" +#include "CCNode.h" + +namespace cocos2d +{ + +class CCTimer; + +// Lua support for CCSchedule +class CCSchedulerFuncEntry : public CCObject +{ +public: + // functionRefID return by tolua_ref_function(), called from LuaCocos2d.cpp + static CCSchedulerFuncEntry* entryWithFunctionRefID(int functionRefID, ccTime fInterval, bool bPaused); + ~CCSchedulerFuncEntry(void); + + inline cocos2d::CCTimer* getTimer(void) { + return m_timer; + } + + inline bool isPaused(void) { + return m_paused; + } + + inline int getEntryID(void) { + return m_entryID; + } + + void markDeleted(void) { + m_isMarkDeleted = true; + } + + bool isMarkDeleted(void) { + return m_isMarkDeleted; + } + +private: + CCSchedulerFuncEntry(void); + bool initWithFunctionRefID(int refID, ccTime fInterval, bool bPaused); + + cocos2d::CCTimer* m_timer; + bool m_paused; + int m_functionRefID; // Lua function reference + int m_entryID; + bool m_isMarkDeleted; +}; + + +// Lua support for touch events +class CCTouchEventEntry : public CCObject +{ +public: + static CCTouchEventEntry* entryWithFunctionRefID(int functionRefID); +}; + + +// Lua support for cocos2d-x +class CCLuaEngine +{ +public: + ~CCLuaEngine(); + + /** + @brief Method used to get a pointer to the lua_State that the script module is attached to. + @return A pointer to the lua_State that the script module is attached to. + */ + lua_State* getLuaState(void) { + return m_state; + } + + /** + @brief Remove CCObject from lua state + @param object to remove + */ + void removeCCObject(cocos2d::CCObject *object); + + /** + @brief Remove Lua function reference + */ + void removeLuaFunctionRef(int functionRefID); + + /** + @brief Add a path to find lua files in + @param path to be added to the Lua path + */ + void addSearchPath(const char* path); + + /** + @brief Execute a script file. + @param filename String object holding the filename of the script file that is to be executed + */ + int executeScriptFile(const char* filename); + + /** + @brief Execute a scripted global function. + @brief The function should not take any parameters and should return an integer. + @param function_name String object holding the name of the function, in the global script environment, that is to be executed. + @return The integer value returned from the script function. + */ + int executeGlobalFunction(const char* function_name); + + /** + @brief Execute a function by ref id + @param The function ref id + @param Number of parameters + @return The integer value returned from the script function. + */ + int executeFunctionByRefID(int functionRefId, int numArgs = 0); + int executeFunctionWithIntegerData(int functionRefId, int data); + int executeFunctionWithFloatData(int functionRefId, float data); + int executeFunctionWithBooleanData(int functionRefId, bool data); + + // functions for excute touch event + int executeTouchEvent(int functionRefId, int eventType, cocos2d::CCTouch *pTouch); + int executeTouchesEvent(int functionRefId, int eventType, cocos2d::CCSet *pTouches); + + // execute a schedule function + int executeSchedule(int functionRefID, cocos2d::ccTime dt); + + static CCLuaEngine* sharedEngine(); + static void purgeSharedEngine(); + +private: + CCLuaEngine(); + + static CCLuaEngine* s_engine; + lua_State* m_state; +}; + +} // namespace cocos2d + +#endif // __LUA_ENGINE_H__ diff --git a/lua/cocos2dx_support/LuaCocos2d.cpp.REMOVED.git-id b/lua/cocos2dx_support/LuaCocos2d.cpp.REMOVED.git-id new file mode 100644 index 0000000000..ba3e65d659 --- /dev/null +++ b/lua/cocos2dx_support/LuaCocos2d.cpp.REMOVED.git-id @@ -0,0 +1 @@ +e26f1325639653fb88b0b14aabc3de5e497e75bd \ No newline at end of file diff --git a/lua/cocos2dx_support/LuaCocos2d.h b/lua/cocos2dx_support/LuaCocos2d.h index 08341dc9ac..0bde2f654e 100644 --- a/lua/cocos2dx_support/LuaCocos2d.h +++ b/lua/cocos2dx_support/LuaCocos2d.h @@ -1,46 +1,42 @@ -/**************************************************************************** - Copyright (c) 2011 cocos2d-x.org - Copyright (c) 2011 NetDragon.com - - http://www.cocos2d-x.org - - 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. - ****************************************************************************/ - -#ifndef LUACOCOS2D_H -#define LUACOCOS2D_H -#include "cocos2d.h" -#include "tolua++.h" - -#include -#include "CCKeypadDispatcher.h" -#include "CCRibbon.h" -#include "CCParallaxNode.h" -#include "CCAutoreleasePool.h" -#include "CCIMEDispatcher.h" -#include "CCMutableArray.h" -//#define TOLUA_RELEASE -#if defined(_WIN32) && defined(_DEBUG) -#pragma warning (disable:4800) -#endif -int tolua_Cocos2d_open(lua_State* tolua_S); - -#define TOLUA_RELEASE - -#endif//LUACOCOS2D_H \ No newline at end of file +/**************************************************************************** + Copyright (c) 2011 cocos2d-x.org + Copyright (c) 2011 NetDragon.com + + http://www.cocos2d-x.org + + 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. + ****************************************************************************/ + +#ifndef __LUACOCOS2D_H +#define __LUACOCOS2D_H + +#if defined(_WIN32) && defined(_DEBUG) +#pragma warning (disable:4800) +#endif + +#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0 +#define TOLUA_RELEASE +#endif + +#include "tolua++.h" + +int tolua_Cocos2d_open(lua_State* tolua_S); + + +#endif // __LUACOCOS2D_H diff --git a/lua/cocos2dx_support/tolua_fix.c b/lua/cocos2dx_support/tolua_fix.c new file mode 100644 index 0000000000..08516d9156 --- /dev/null +++ b/lua/cocos2dx_support/tolua_fix.c @@ -0,0 +1,208 @@ + +#include "tolua_fix.h" +#include + +TOLUA_API void tolua_prepare_ccobject_table(lua_State* L) +{ + lua_pushstring(L, TOLUA_REFID_PTR_MAPPING); + lua_newtable(L); + lua_rawset(L, LUA_REGISTRYINDEX); + + lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING); + lua_newtable(L); + lua_rawset(L, LUA_REGISTRYINDEX); + + lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING); + lua_newtable(L); + lua_rawset(L, LUA_REGISTRYINDEX); +} + +TOLUA_API int tolua_pushusertype_ccobject(lua_State* L, int refid, int* p_refid, void* ptr, const char* type) +{ + if (ptr == NULL || p_refid == NULL) + { + lua_pushnil(L); + return -1; + } + + if (*p_refid == 0) + { + *p_refid = refid; + + lua_pushstring(L, TOLUA_REFID_PTR_MAPPING); + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_ptr */ + lua_pushinteger(L, refid); /* stack: refid_ptr refid */ + lua_pushlightuserdata(L, ptr); /* stack: refid_ptr refid ptr */ + + lua_rawset(L, -3); /* refid_ptr[refid] = ptr, stack: refid_ptr */ + lua_pop(L, 1); /* stack: - */ + + lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING); + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_type */ + lua_pushinteger(L, refid); /* stack: refid_type refid */ + lua_pushstring(L, type); /* stack: refid_type refid type */ + lua_rawset(L, -3); /* refid_type[refid] = type, stack: refid_type */ + lua_pop(L, 1); /* stack: - */ + + //printf("[LUA] push CCObject OK - refid: %d, ptr: %x, type: %s\n", *p_refid, (int)ptr, type); + } + + tolua_pushusertype(L, ptr, type); + return 0; +} + +TOLUA_API int tolua_remove_ccobject_by_refid(lua_State* L, int refid) +{ + if (refid == 0) return -1; + + // get ptr from tolua_refid_ptr_mapping + lua_pushstring(L, TOLUA_REFID_PTR_MAPPING); + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_ptr */ + lua_pushinteger(L, refid); /* stack: refid_ptr refid */ + lua_rawget(L, -2); /* stack: refid_ptr ptr */ + void* ptr = lua_touserdata(L, -1); + lua_pop(L, 1); /* stack: refid_ptr */ + if (ptr == NULL) + { + lua_pop(L, 1); + // Lua stack has closed, C++ object not in Lua. + printf("[LUA ERROR] remove CCObject with NULL ptr, refid: %d\n", refid); + return -2; + } + + // remove ptr from tolua_refid_ptr_mapping + lua_pushinteger(L, refid); /* stack: refid_ptr refid */ + lua_pushnil(L); /* stack: refid_ptr refid nil */ + lua_rawset(L, -3); /* delete refid_ptr[refid], stack: refid_ptr */ + lua_pop(L, 1); /* stack: - */ + + + // get type from tolua_refid_type_mapping + lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING); + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_type */ + lua_pushinteger(L, refid); /* stack: refid_type refid */ + lua_rawget(L, -2); /* stack: refid_type type */ + if (lua_isnil(L, -1)) + { + lua_pop(L, 2); + printf("[LUA ERROR] remove CCObject with NULL type, refid: %d, ptr: %x\n", refid, (int)ptr); + return -1; + } + + const char* type = lua_tostring(L, -1); + lua_pop(L, 1); /* stack: refid_type */ + + // remove type from tolua_refid_type_mapping + lua_pushinteger(L, refid); /* stack: refid_type refid */ + lua_pushnil(L); /* stack: refid_type refid nil */ + lua_rawset(L, -3); /* delete refid_type[refid], stack: refid_type */ + lua_pop(L, 1); /* stack: - */ + + // get ubox + luaL_getmetatable(L, type); /* stack: mt */ + lua_pushstring(L, "tolua_ubox"); /* stack: mt key */ + lua_rawget(L, -2); /* stack: mt ubox */ + if (lua_isnil(L, -1)) + { + // use global ubox + lua_pop(L, 1); /* stack: mt */ + lua_pushstring(L, "tolua_ubox"); /* stack: mt key */ + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: mt ubox */ + }; + + lua_pushlightuserdata(L, ptr); /* stack: mt ubox ptr */ + lua_rawget(L,-2); /* stack: mt ubox ud */ + if (lua_isnil(L, -1)) + { + // Lua object has released (GC), C++ object not in ubox. + printf("[LUA ERROR] remove CCObject with NULL ubox, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type); + lua_pop(L, 3); + return -3; + } + + void** ud = (void**)lua_touserdata(L, -1); + lua_pop(L, 1); /* stack: mt ubox */ + if (ud == NULL) + { + printf("[LUA ERROR] remove CCObject with NULL userdata, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type); + lua_pop(L, 2); + return -1; + } + + // clean userdata + *ud = NULL; + + lua_pushlightuserdata(L, ptr); /* stack: mt ubox ptr */ + lua_pushnil(L); /* stack: mt ubox ptr nil */ + lua_rawset(L, -3); /* ubox[ptr] = nil, stack: mt ubox */ + + lua_pop(L, 2); + //printf("[LUA] remove CCObject, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type); + return 0; +} + +TOLUA_API int tolua_ref_function(lua_State* L, int lo, int def) +{ + static int functionRefIDCount = 0; + if (lua_gettop(L) < abs(lo) || !lua_isfunction(L, lo)) return 0; + + ++functionRefIDCount; + /* stack: ... func ... */ + lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING); + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: ... func ... refid_func */ + lua_pushinteger(L, functionRefIDCount); /* stack: ... func ... refid_func refid */ + lua_pushvalue(L, lo); /* stack: ... func ... refid_func refid func */ + lua_rawset(L, -3); /* refid_func[refid] = func, stack: ... func ... refid_func */ + lua_pop(L, 1); /* stack: ... func ... */ + + return functionRefIDCount; +} + +TOLUA_API void tolua_remove_function_by_refid(lua_State* L, int refid) +{ + lua_pushstring(L, TOLUA_REFID_FUNC_MAPPING); + lua_rawget(L, LUA_REGISTRYINDEX); /* stack: refid_func */ + lua_pushinteger(L, refid); /* stack: refid_func refid */ + lua_pushnil(L); /* stack: refid_func refid nil */ + lua_rawget(L, -2); /* delete refid_func[refid], stack: refid_func */ + lua_pop(L, 1); /* stack: - */ +} + +// check lua value is funciton +TOLUA_API int tolua_isfunction(lua_State* L, int lo, tolua_Error* err) +{ + if (lua_gettop(L) >= abs(lo) && lua_isfunction(L, lo)) + { + return 1; + } + err->index = lo; + err->array = 0; + err->type = "[not function]"; + return 0; +} + +TOLUA_API void tolua_stack_dump(lua_State* L, const char* label) +{ + int i; + int top = lua_gettop(L); + printf("Total [%d] in lua stack: %s\n", top, label != 0 ? label : ""); + for (i = -1; i >= -top; i--) + { + int t = lua_type(L, i); + switch (t) + { + case LUA_TSTRING: + printf(" [%02d] string %s\n", i, lua_tostring(L, i)); + break; + case LUA_TBOOLEAN: + printf(" [%02d] boolean %s\n", i, lua_toboolean(L, i) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf(" [%02d] number %g\n", i, lua_tonumber(L, i)); + break; + default: + printf(" [%02d] %s\n", i, lua_typename(L, t)); + } + } + printf("\n"); +} diff --git a/lua/cocos2dx_support/tolua_fix.h b/lua/cocos2dx_support/tolua_fix.h new file mode 100644 index 0000000000..1784a056db --- /dev/null +++ b/lua/cocos2dx_support/tolua_fix.h @@ -0,0 +1,31 @@ + +#ifndef __TOLUA_FIX_H_ +#define __TOLUA_FIX_H_ + +#include "tolua++.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define TOLUA_REFID_PTR_MAPPING "tolua_refid_ptr_mapping" +#define TOLUA_REFID_TYPE_MAPPING "tolua_refid_type_mapping" +#define TOLUA_REFID_FUNC_MAPPING "tolua_refid_func_mapping" + +TOLUA_API void tolua_prepare_ccobject_table(lua_State* L); +TOLUA_API int tolua_pushusertype_ccobject(lua_State* L, int uid, int* p_refid, void* ptr, const char* type); +TOLUA_API int tolua_remove_ccobject_by_refid(lua_State* L, int refid); + +TOLUA_API int tolua_ref_function(lua_State* L, int lo, int def); +TOLUA_API void tolua_remove_function_by_refid(lua_State* L, int refid); + +TOLUA_API int tolua_isfunction(lua_State* L, int lo, tolua_Error* err); + +TOLUA_API void tolua_stack_dump(lua_State* L, const char* label); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __TOLUA_FIX_H_