#include "ScriptController.h" namespace gameplay { // Helper macros. #define SCRIPT_EXECUTE_FUNCTION_PARAM(type, checkfunc) \ va_list list; \ va_start(list, args); \ executeFunctionHelper(1, func, args, list); \ type value = (type)checkfunc(_lua, -1); \ lua_pop(_lua, -1); \ va_end(list); \ return value; template T ScriptController::executeFunction(const char* func, const char* args, ...) { GP_ERROR("Unsupported type!"); } template<> void ScriptController::executeFunction(const char* func, const char* args, ...) { va_list list; va_start(list, args); executeFunctionHelper(0, func, args, list); va_end(list); } template<> bool ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(bool, luaCheckBool); } template<> char ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(char, luaL_checkint); } template<> short ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(short, luaL_checkint); } template<> int ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(int, luaL_checkint); } template<> long ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(long, luaL_checklong); } template<> unsigned char ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned char, luaL_checkunsigned); } template<> unsigned short ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned short, luaL_checkunsigned); } template<> unsigned int ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned int, luaL_checkunsigned); } template<> unsigned long ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned long, luaL_checkunsigned); } template<> float ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(float, luaL_checknumber); } template<> double ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(double, luaL_checknumber); } template<> std::string ScriptController::executeFunction(const char* func, const char* args, ...) { SCRIPT_EXECUTE_FUNCTION_PARAM(std::string, luaL_checkstring); } template T* ScriptController::executeFunction(const Type& type, const char* func, const char* args, ...) { va_list list; va_start(list, args); executeFunctionHelper(1, func, args, list); T* value = (T*)*((T**)luaL_checkudata(_lua, -1, type.type)); lua_pop(_lua, -1); va_end(list); return value; } templateT* ScriptController::getObjectPointer(int index, const char* type, bool nonNull) { if (lua_type(_lua, index) == LUA_TNIL) { if (nonNull) { GP_ERROR("Attempting to pass NULL for required non-NULL parameter at index %d (likely a reference or by-value parameter).", index); } return NULL; } void* p = lua_touserdata(_lua, index); if (p != NULL) { if (lua_getmetatable(_lua, index)) { // Check if it matches the type's metatable. luaL_getmetatable(_lua, type); if (lua_rawequal(_lua, -1, -2)) { lua_pop(_lua, 2); T* ptr = (T*)((ScriptController::LuaObject*)p)->instance; if (ptr == NULL && nonNull) { GP_ERROR("Attempting to pass NULL for required non-NULL parameter at index %d (likely a reference or by-value parameter).", index); } return ptr; } lua_pop(_lua, 1); // Check if it matches any of the derived types' metatables. const std::vector& types = _hierarchy[type]; for (unsigned int i = 0, count = types.size(); i < count; i++) { luaL_getmetatable(_lua, types[i].c_str()); if (lua_rawequal(_lua, -1, -2)) { lua_pop(_lua, 2); T* ptr = (T*)((ScriptController::LuaObject*)p)->instance; if (ptr == NULL && nonNull) { GP_ERROR("Attempting to pass NULL for required non-NULL parameter at index %d (likely a reference or by-value parameter).", index); } return ptr; } lua_pop(_lua, 1); } lua_pop(_lua, 1); } } if (nonNull) { GP_ERROR("Failed to retrieve a valid object pointer of type '%s' for parameter %d.", type, index); } return NULL; } templateT* ScriptController::getObjectPointer(const char* type, const char* name) { lua_getglobal(_lua, name); void* userdata = luaL_checkudata(_lua, -1, type); std::string msg = std::string("'") + std::string(type) + std::string("' expected."); luaL_argcheck(_lua, userdata != NULL, 1, msg.c_str()); return (T*)((ScriptController::LuaObject*)userdata)->instance; } templatevoid ScriptController::setPointer(const char* type, const char* name, T* v) { ScriptController::LuaObject* object = (ScriptController::LuaObject*)lua_newuserdata(state, sizeof(ScriptController::LuaObject)); object->instance = (void*)v; object->owns = false; luaL_getmetatable(state, type); lua_setmetatable(state, -2); lua_setglobal(_lua, name); } }