ScriptController.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. #include "Base.h"
  2. #include "FileSystem.h"
  3. #include "ScriptController.h"
  4. #include "lua/lua_all_bindings.h"
  5. #define GENERATE_LUA_GET_POINTER(type, checkFunc) \
  6. ScriptController* sc = Game::getInstance()->getScriptController(); \
  7. /* Check that the parameter is the correct type. */ \
  8. if (!lua_istable(sc->_lua, index)) \
  9. { \
  10. if (lua_islightuserdata(sc->_lua, index)) \
  11. return LuaArray<type>((type*)lua_touserdata(sc->_lua, index)); \
  12. lua_pushfstring(sc->_lua, "Expected a " #type " pointer (an array represented as a Lua table), got '%s' instead.", \
  13. luaL_typename(sc->_lua, index)); \
  14. lua_error(sc->_lua); \
  15. return LuaArray<type>((type*)NULL); \
  16. } \
  17. \
  18. /* Get the size of the array. */ \
  19. lua_len(sc->_lua, index); \
  20. int size = luaL_checkint(sc->_lua, -1); \
  21. if (size <= 0) \
  22. return LuaArray<type>((type*)NULL); \
  23. \
  24. /* Declare a LuaArray to store the values. */ \
  25. LuaArray<type> arr(size); \
  26. \
  27. /* Push the first key. */ \
  28. lua_pushnil(sc->_lua); \
  29. int i = 0; \
  30. for (; lua_next(sc->_lua, index) != 0 && i < size; i++) \
  31. { \
  32. arr[i] = (checkFunc(sc->_lua, -1)); \
  33. \
  34. /* Remove the value we just retrieved, but leave the key for the next iteration. */ \
  35. lua_pop(sc->_lua, 1); \
  36. } \
  37. \
  38. return arr
  39. namespace gameplay
  40. {
  41. extern void splitURL(const std::string& url, std::string* file, std::string* id);
  42. void ScriptUtil::registerLibrary(const char* name, const luaL_Reg* functions)
  43. {
  44. ScriptController* sc = Game::getInstance()->getScriptController();
  45. lua_newtable(sc->_lua);
  46. // Go through the list of functions and add them to the table.
  47. const luaL_Reg* iter = functions;
  48. for (; iter && iter->name; iter++)
  49. {
  50. lua_pushcfunction(sc->_lua, iter->func);
  51. lua_setfield(sc->_lua, -2, iter->name);
  52. }
  53. lua_setglobal(sc->_lua, name);
  54. }
  55. void ScriptUtil::registerConstantBool(const std::string& name, bool value, const std::vector<std::string>& scopePath)
  56. {
  57. ScriptController* sc = Game::getInstance()->getScriptController();
  58. // If the constant is within a scope, get the correct parent
  59. // table on the stack before setting its value.
  60. if (!scopePath.empty())
  61. {
  62. lua_getglobal(sc->_lua, scopePath[0].c_str());
  63. for (unsigned int i = 1; i < scopePath.size(); i++)
  64. {
  65. lua_pushstring(sc->_lua, scopePath[i].c_str());
  66. lua_gettable(sc->_lua, -2);
  67. }
  68. // Add the constant to the parent table.
  69. lua_pushboolean(sc->_lua, value);
  70. lua_setfield(sc->_lua, -2, name.c_str());
  71. // Pop all the parent tables off the stack.
  72. int size = scopePath.size();
  73. lua_pop(sc->_lua, size);
  74. }
  75. else
  76. {
  77. // TODO: Currently unsupported (we don't parse for this yet).
  78. // If the constant is global, add it to the global table.
  79. lua_pushboolean(sc->_lua, value);
  80. lua_pushvalue(sc->_lua, -1);
  81. lua_setglobal(sc->_lua, name.c_str());
  82. }
  83. }
  84. void ScriptUtil::registerConstantNumber(const std::string& name, double value, const std::vector<std::string>& scopePath)
  85. {
  86. ScriptController* sc = Game::getInstance()->getScriptController();
  87. // If the constant is within a scope, get the correct parent
  88. // table on the stack before setting its value.
  89. if (!scopePath.empty())
  90. {
  91. lua_getglobal(sc->_lua, scopePath[0].c_str());
  92. for (unsigned int i = 1; i < scopePath.size(); i++)
  93. {
  94. lua_pushstring(sc->_lua, scopePath[i].c_str());
  95. lua_gettable(sc->_lua, -2);
  96. }
  97. // Add the constant to the parent table.
  98. lua_pushnumber(sc->_lua, value);
  99. lua_setfield(sc->_lua, -2, name.c_str());
  100. // Pop all the parent tables off the stack.
  101. int size = scopePath.size();
  102. lua_pop(sc->_lua, size);
  103. }
  104. else
  105. {
  106. // TODO: Currently unsupported (we don't parse for this yet).
  107. // If the constant is global, add it to the global table.
  108. lua_pushnumber(sc->_lua, value);
  109. lua_pushvalue(sc->_lua, -1);
  110. lua_setglobal(sc->_lua, name.c_str());
  111. }
  112. }
  113. void ScriptUtil::registerConstantString(const std::string& name, const std::string& value, const std::vector<std::string>& scopePath)
  114. {
  115. ScriptController* sc = Game::getInstance()->getScriptController();
  116. // If the constant is within a scope, get the correct parent
  117. // table on the stack before setting its value.
  118. if (!scopePath.empty())
  119. {
  120. lua_getglobal(sc->_lua, scopePath[0].c_str());
  121. for (unsigned int i = 1; i < scopePath.size(); i++)
  122. {
  123. lua_pushstring(sc->_lua, scopePath[i].c_str());
  124. lua_gettable(sc->_lua, -2);
  125. }
  126. // Add the constant to the parent table.
  127. lua_pushstring(sc->_lua, value.c_str());
  128. lua_setfield(sc->_lua, -2, name.c_str());
  129. // Pop all the parent tables off the stack.
  130. int size = scopePath.size();
  131. lua_pop(sc->_lua, size);
  132. }
  133. else
  134. {
  135. // TODO: Currently unsupported (we don't parse for this yet).
  136. // If the constant is global, add it to the global table.
  137. lua_pushstring(sc->_lua, value.c_str());
  138. lua_pushvalue(sc->_lua, -1);
  139. lua_setglobal(sc->_lua, name.c_str());
  140. }
  141. }
  142. void ScriptUtil::registerClass(const char* name, const luaL_Reg* members, lua_CFunction newFunction,
  143. lua_CFunction deleteFunction, const luaL_Reg* statics, const std::vector<std::string>& scopePath)
  144. {
  145. ScriptController* sc = Game::getInstance()->getScriptController();
  146. // If the type is an inner type, get the correct parent
  147. // table on the stack before creating the table for the class.
  148. if (!scopePath.empty())
  149. {
  150. std::string tablename = name;
  151. // Strip off the scope path part of the name.
  152. lua_getglobal(sc->_lua, scopePath[0].c_str());
  153. std::size_t index = tablename.find(scopePath[0]);
  154. if (index != std::string::npos)
  155. tablename = tablename.substr(index + scopePath[0].size());
  156. for (unsigned int i = 1; i < scopePath.size(); i++)
  157. {
  158. lua_pushstring(sc->_lua, scopePath[i].c_str());
  159. lua_gettable(sc->_lua, -2);
  160. index = tablename.find(scopePath[i]);
  161. if (index != std::string::npos)
  162. tablename = tablename.substr(index + scopePath[i].size());
  163. }
  164. lua_pushstring(sc->_lua, tablename.c_str());
  165. lua_newtable(sc->_lua);
  166. }
  167. else
  168. {
  169. // If the type is not an inner type, set it as a global table.
  170. lua_newtable(sc->_lua);
  171. lua_pushvalue(sc->_lua, -1);
  172. lua_setglobal(sc->_lua, name);
  173. }
  174. // Create the metatable and populate it with the member functions.
  175. lua_pushliteral(sc->_lua, "__metatable");
  176. luaL_newmetatable(sc->_lua, name);
  177. if (members)
  178. luaL_setfuncs(sc->_lua, members, 0);
  179. lua_pushstring(sc->_lua, "__index");
  180. lua_pushvalue(sc->_lua, -2);
  181. lua_settable(sc->_lua, -3);
  182. // Add the delete function if it was specified.
  183. if (deleteFunction)
  184. {
  185. lua_pushstring(sc->_lua, "__gc");
  186. lua_pushcfunction(sc->_lua, deleteFunction);
  187. lua_settable(sc->_lua, -3);
  188. }
  189. // Set the metatable on the main table.
  190. lua_settable(sc->_lua, -3);
  191. // Populate the main table with the static functions.
  192. if (statics)
  193. luaL_setfuncs(sc->_lua, statics, 0);
  194. // Set the new function(s) for the class.
  195. if (newFunction)
  196. {
  197. lua_pushliteral(sc->_lua, "new");
  198. lua_pushcfunction(sc->_lua, newFunction);
  199. lua_settable(sc->_lua, -3);
  200. }
  201. // Set the table we just created within the correct parent table.
  202. if (!scopePath.empty())
  203. {
  204. lua_settable(sc->_lua, -3);
  205. // Pop all the parent tables off the stack.
  206. int size = scopePath.size();
  207. lua_pop(sc->_lua, size);
  208. }
  209. else
  210. {
  211. // Pop the main table off the stack.
  212. lua_pop(sc->_lua, 1);
  213. }
  214. }
  215. void ScriptUtil::registerFunction(const char* luaFunction, lua_CFunction cppFunction)
  216. {
  217. lua_pushcfunction(Game::getInstance()->getScriptController()->_lua, cppFunction);
  218. lua_setglobal(Game::getInstance()->getScriptController()->_lua, luaFunction);
  219. }
  220. void ScriptUtil::setGlobalHierarchyPair(const std::string& base, const std::string& derived)
  221. {
  222. Game::getInstance()->getScriptController()->_hierarchy[base].push_back(derived);
  223. }
  224. void ScriptUtil::addStringFromEnumConversionFunction(luaStringEnumConversionFunction stringFromEnum)
  225. {
  226. Game::getInstance()->getScriptController()->_stringFromEnum.push_back(stringFromEnum);
  227. }
  228. ScriptUtil::LuaArray<bool> ScriptUtil::getBoolPointer(int index)
  229. {
  230. GENERATE_LUA_GET_POINTER(bool, luaCheckBool);
  231. }
  232. ScriptUtil::LuaArray<short> ScriptUtil::getShortPointer(int index)
  233. {
  234. GENERATE_LUA_GET_POINTER(short, (short)luaL_checkint);
  235. }
  236. ScriptUtil::LuaArray<int> ScriptUtil::getIntPointer(int index)
  237. {
  238. GENERATE_LUA_GET_POINTER(int, (int)luaL_checkint);
  239. }
  240. ScriptUtil::LuaArray<long> ScriptUtil::getLongPointer(int index)
  241. {
  242. GENERATE_LUA_GET_POINTER(long, (long)luaL_checkint);
  243. }
  244. ScriptUtil::LuaArray<unsigned char> ScriptUtil::getUnsignedCharPointer(int index)
  245. {
  246. GENERATE_LUA_GET_POINTER(unsigned char, (unsigned char)luaL_checkunsigned);
  247. }
  248. ScriptUtil::LuaArray<unsigned short> ScriptUtil::getUnsignedShortPointer(int index)
  249. {
  250. GENERATE_LUA_GET_POINTER(unsigned short, (unsigned short)luaL_checkunsigned);
  251. }
  252. ScriptUtil::LuaArray<unsigned int> ScriptUtil::getUnsignedIntPointer(int index)
  253. {
  254. GENERATE_LUA_GET_POINTER(unsigned int, (unsigned int)luaL_checkunsigned);
  255. }
  256. ScriptUtil::LuaArray<unsigned long> ScriptUtil::getUnsignedLongPointer(int index)
  257. {
  258. GENERATE_LUA_GET_POINTER(unsigned long, (unsigned long)luaL_checkunsigned);
  259. }
  260. ScriptUtil::LuaArray<float> ScriptUtil::getFloatPointer(int index)
  261. {
  262. GENERATE_LUA_GET_POINTER(float, (float)luaL_checknumber);
  263. }
  264. ScriptUtil::LuaArray<double> ScriptUtil::getDoublePointer(int index)
  265. {
  266. GENERATE_LUA_GET_POINTER(double, (double)luaL_checknumber);
  267. }
  268. const char* ScriptUtil::getString(int index, bool isStdString)
  269. {
  270. if (lua_type(Game::getInstance()->getScriptController()->_lua, index) == LUA_TSTRING)
  271. return luaL_checkstring(Game::getInstance()->getScriptController()->_lua, index);
  272. else if (lua_type(Game::getInstance()->getScriptController()->_lua, index) == LUA_TNIL && !isStdString)
  273. return NULL;
  274. else
  275. {
  276. GP_ERROR("Invalid string parameter (index = %d).", index);
  277. return NULL;
  278. }
  279. }
  280. bool ScriptUtil::luaCheckBool(lua_State* state, int n)
  281. {
  282. if (!lua_isboolean(state, n))
  283. {
  284. const char* msg = lua_pushfstring(state, "%s expected, got %s", lua_typename(state, LUA_TBOOLEAN), luaL_typename(state, n));
  285. luaL_argerror(state, n, msg);
  286. return false;
  287. }
  288. return (lua_toboolean(state, n) != 0);
  289. }
  290. void ScriptController::loadScript(const char* path, bool forceReload)
  291. {
  292. std::set<std::string>::iterator iter = _loadedScripts.find(path);
  293. if (iter == _loadedScripts.end() || forceReload)
  294. {
  295. const char* scriptContents = FileSystem::readAll(path);
  296. if (luaL_dostring(_lua, scriptContents))
  297. GP_WARN("Failed to run Lua script with error: '%s'.", lua_tostring(_lua, -1));
  298. SAFE_DELETE_ARRAY(scriptContents);
  299. if (iter == _loadedScripts.end())
  300. _loadedScripts.insert(path);
  301. }
  302. }
  303. std::string ScriptController::loadUrl(const char* url)
  304. {
  305. std::string file;
  306. std::string id;
  307. splitURL(url, &file, &id);
  308. // Make sure the function isn't empty.
  309. if (id.size() <= 0)
  310. {
  311. GP_ERROR("Got an empty function name when parsing function url '%s'.", url);
  312. return std::string();
  313. }
  314. // Ensure the script is loaded.
  315. if (file.size() > 0)
  316. Game::getInstance()->getScriptController()->loadScript(file.c_str());
  317. // Return the function name.
  318. return id;
  319. }
  320. bool ScriptController::getBool(const char* name)
  321. {
  322. lua_getglobal(_lua, name);
  323. return ScriptUtil::luaCheckBool(_lua, -1);
  324. }
  325. char ScriptController::getChar(const char* name)
  326. {
  327. lua_getglobal(_lua, name);
  328. return (char)luaL_checkint(_lua, -1);
  329. }
  330. short ScriptController::getShort(const char* name)
  331. {
  332. lua_getglobal(_lua, name);
  333. return (short)luaL_checkint(_lua, -1);
  334. }
  335. int ScriptController::getInt(const char* name)
  336. {
  337. lua_getglobal(_lua, name);
  338. return luaL_checkint(_lua, -1);
  339. }
  340. long ScriptController::getLong(const char* name)
  341. {
  342. lua_getglobal(_lua, name);
  343. return luaL_checklong(_lua, -1);
  344. }
  345. unsigned char ScriptController::getUnsignedChar(const char* name)
  346. {
  347. lua_getglobal(_lua, name);
  348. return (unsigned char)luaL_checkunsigned(_lua, -1);
  349. }
  350. unsigned short ScriptController::getUnsignedShort(const char* name)
  351. {
  352. lua_getglobal(_lua, name);
  353. return (unsigned short)luaL_checkunsigned(_lua, -1);
  354. }
  355. unsigned int ScriptController::getUnsignedInt(const char* name)
  356. {
  357. lua_getglobal(_lua, name);
  358. return (unsigned int)luaL_checkunsigned(_lua, -1);
  359. }
  360. unsigned long ScriptController::getUnsignedLong(const char* name)
  361. {
  362. lua_getglobal(_lua, name);
  363. return (unsigned long)luaL_checkunsigned(_lua, -1);
  364. }
  365. float ScriptController::getFloat(const char* name)
  366. {
  367. lua_getglobal(_lua, name);
  368. return (float)luaL_checknumber(_lua, -1);
  369. }
  370. double ScriptController::getDouble(const char* name)
  371. {
  372. lua_getglobal(_lua, name);
  373. return (double)luaL_checknumber(_lua, -1);
  374. }
  375. const char* ScriptController::getString(const char* name)
  376. {
  377. lua_getglobal(_lua, name);
  378. return luaL_checkstring(_lua, -1);
  379. }
  380. void ScriptController::setBool(const char* name, bool v)
  381. {
  382. lua_pushboolean(_lua, v);
  383. lua_setglobal(_lua, name);
  384. }
  385. void ScriptController::setChar(const char* name, char v)
  386. {
  387. lua_pushinteger(_lua, v);
  388. lua_setglobal(_lua, name);
  389. }
  390. void ScriptController::setShort(const char* name, short v)
  391. {
  392. lua_pushinteger(_lua, v);
  393. lua_setglobal(_lua, name);
  394. }
  395. void ScriptController::setInt(const char* name, int v)
  396. {
  397. lua_pushinteger(_lua, v);
  398. lua_setglobal(_lua, name);
  399. }
  400. void ScriptController::setLong(const char* name, long v)
  401. {
  402. lua_pushinteger(_lua, v);
  403. lua_setglobal(_lua, name);
  404. }
  405. void ScriptController::setUnsignedChar(const char* name, unsigned char v)
  406. {
  407. lua_pushunsigned(_lua, v);
  408. lua_setglobal(_lua, name);
  409. }
  410. void ScriptController::setUnsignedShort(const char* name, unsigned short v)
  411. {
  412. lua_pushunsigned(_lua, v);
  413. lua_setglobal(_lua, name);
  414. }
  415. void ScriptController::setUnsignedInt(const char* name, unsigned int v)
  416. {
  417. lua_pushunsigned(_lua, v);
  418. lua_setglobal(_lua, name);
  419. }
  420. void ScriptController::setUnsignedLong(const char* name, unsigned long v)
  421. {
  422. lua_pushunsigned(_lua, v);
  423. lua_setglobal(_lua, name);
  424. }
  425. void ScriptController::setFloat(const char* name, float v)
  426. {
  427. lua_pushnumber(_lua, v);
  428. lua_setglobal(_lua, name);
  429. }
  430. void ScriptController::setDouble(const char* name, double v)
  431. {
  432. lua_pushnumber(_lua, v);
  433. lua_setglobal(_lua, name);
  434. }
  435. void ScriptController::setString(const char* name, const char* v)
  436. {
  437. lua_pushstring(_lua, v);
  438. lua_setglobal(_lua, name);
  439. }
  440. void ScriptController::print(const char* str)
  441. {
  442. gameplay::print("%s", str);
  443. }
  444. void ScriptController::print(const char* str1, const char* str2)
  445. {
  446. gameplay::print("%s%s", str1, str2);
  447. }
  448. ScriptController::ScriptController() : _lua(NULL)
  449. {
  450. memset(_callbacks, 0, sizeof(std::string*) * CALLBACK_COUNT);
  451. }
  452. ScriptController::~ScriptController()
  453. {
  454. for (unsigned int i = 0; i < CALLBACK_COUNT; i++)
  455. {
  456. SAFE_DELETE(_callbacks[i]);
  457. }
  458. }
  459. static const char* lua_print_function =
  460. "function print(...)\n"
  461. " ScriptController.print(table.concat({...},\"\\t\"), \"\\n\")\n"
  462. "end\n";
  463. #ifndef WIN32
  464. static const char* lua_loadfile_function =
  465. "do\n"
  466. " local oldLoadfile = loadfile\n"
  467. " loadfile = function(filename)\n"
  468. " if filename ~= nil and not FileSystem.isAbsolutePath(filename) then\n"
  469. " FileSystem.createFileFromAsset(filename)\n"
  470. " filename = FileSystem.getResourcePath() .. filename\n"
  471. " end\n"
  472. " return oldLoadfile(filename)\n"
  473. " end\n"
  474. "end\n";
  475. static const char* lua_dofile_function =
  476. "do\n"
  477. " local oldDofile = dofile\n"
  478. " dofile = function(filename)\n"
  479. " if filename ~= nil and not FileSystem.isAbsolutePath(filename) then\n"
  480. " FileSystem.createFileFromAsset(filename)\n"
  481. " filename = FileSystem.getResourcePath() .. filename\n"
  482. " end\n"
  483. " return oldDofile(filename)\n"
  484. " end\n"
  485. "end\n";
  486. #endif
  487. void ScriptController::initialize()
  488. {
  489. _lua = luaL_newstate();
  490. if (!_lua)
  491. GP_ERROR("Failed to initialize Lua scripting engine.");
  492. luaL_openlibs(_lua);
  493. lua_RegisterAllBindings();
  494. // Create our own print() function that uses gameplay::print.
  495. if (luaL_dostring(_lua, lua_print_function))
  496. GP_ERROR("Failed to load custom print() function with error: '%s'.", lua_tostring(_lua, -1));
  497. #ifndef WIN32
  498. // Change the functions that read a file to use FileSystem.getResourcePath as their base path.
  499. if (luaL_dostring(_lua, lua_loadfile_function))
  500. GP_ERROR("Failed to load custom loadfile() function with error: '%s'.", lua_tostring(_lua, -1));
  501. if (luaL_dostring(_lua, lua_dofile_function))
  502. GP_ERROR("Failed to load custom dofile() function with error: '%s'.", lua_tostring(_lua, -1));
  503. #endif
  504. }
  505. void ScriptController::initializeGame()
  506. {
  507. if (_callbacks[INITIALIZE])
  508. {
  509. executeFunction<void>(_callbacks[INITIALIZE]->c_str());
  510. }
  511. }
  512. void ScriptController::finalize()
  513. {
  514. if (_lua)
  515. lua_close(_lua);
  516. }
  517. void ScriptController::finalizeGame()
  518. {
  519. if (_callbacks[FINALIZE])
  520. {
  521. executeFunction<void>(_callbacks[FINALIZE]->c_str());
  522. }
  523. // Perform a full garbage collection cycle.
  524. lua_gc(_lua, LUA_GCCOLLECT, 0);
  525. }
  526. void ScriptController::update(float elapsedTime)
  527. {
  528. if (_callbacks[UPDATE])
  529. {
  530. executeFunction<void>(_callbacks[UPDATE]->c_str(), "f", elapsedTime);
  531. }
  532. }
  533. void ScriptController::render(float elapsedTime)
  534. {
  535. if (_callbacks[RENDER])
  536. {
  537. executeFunction<void>(_callbacks[RENDER]->c_str(), "f", elapsedTime);
  538. }
  539. }
  540. void ScriptController::keyEvent(Keyboard::KeyEvent evt, int key)
  541. {
  542. if (_callbacks[KEY_EVENT])
  543. {
  544. executeFunction<void>(_callbacks[KEY_EVENT]->c_str(), "[Keyboard::KeyEvent][Keyboard::Key]", evt, key);
  545. }
  546. }
  547. void ScriptController::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  548. {
  549. if (_callbacks[TOUCH_EVENT])
  550. {
  551. executeFunction<void>(_callbacks[TOUCH_EVENT]->c_str(), "[Touch::TouchEvent]iiui", evt, x, y, contactIndex);
  552. }
  553. }
  554. bool ScriptController::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
  555. {
  556. if (_callbacks[MOUSE_EVENT])
  557. {
  558. return executeFunction<bool>(_callbacks[MOUSE_EVENT]->c_str(), "[Mouse::MouseEvent]iiii", evt, x, y, wheelDelta);
  559. }
  560. return false;
  561. }
  562. void ScriptController::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
  563. {
  564. if (_callbacks[GAMEPAD_EVENT])
  565. {
  566. executeFunction<void>(_callbacks[GAMEPAD_EVENT]->c_str(), "[Gamepad::GamepadEvent]<Gamepad>", evt, gamepad);
  567. }
  568. }
  569. void ScriptController::executeFunctionHelper(int resultCount, const char* func, const char* args, va_list* list)
  570. {
  571. if (func == NULL)
  572. {
  573. GP_ERROR("Lua function name must be non-null.");
  574. return;
  575. }
  576. const char* sig = args;
  577. int argumentCount = 0;
  578. lua_getglobal(_lua, func);
  579. // Push the arguments to the Lua stack if there are any.
  580. if (sig)
  581. {
  582. while (true)
  583. {
  584. if (!(*sig))
  585. break;
  586. switch(*sig++)
  587. {
  588. // Signed integers.
  589. case 'c':
  590. case 'h':
  591. case 'i':
  592. case 'l':
  593. lua_pushinteger(_lua, va_arg(*list, int));
  594. break;
  595. // Unsigned integers.
  596. case 'u':
  597. // Skip past the actual type (long, int, short, char).
  598. sig++;
  599. lua_pushunsigned(_lua, va_arg(*list, int));
  600. break;
  601. // Booleans.
  602. case 'b':
  603. lua_pushboolean(_lua, va_arg(*list, int));
  604. break;
  605. // Floating point numbers.
  606. case 'f':
  607. case 'd':
  608. lua_pushnumber(_lua, va_arg(*list, double));
  609. break;
  610. // Strings.
  611. case 's':
  612. lua_pushstring(_lua, va_arg(*list, char*));
  613. break;
  614. // Pointers.
  615. case 'p':
  616. lua_pushlightuserdata(_lua, va_arg(*list, void*));
  617. break;
  618. // Enums.
  619. case '[':
  620. {
  621. std::string type = sig;
  622. type = type.substr(0, type.find("]"));
  623. // Skip past the closing ']' (the semi-colon here is intentional-do not remove).
  624. while (*sig++ != ']');
  625. unsigned int value = va_arg(*list, int);
  626. std::string enumStr = "";
  627. for (unsigned int i = 0; enumStr.size() == 0 && i < _stringFromEnum.size(); i++)
  628. {
  629. enumStr = (*_stringFromEnum[i])(type, value);
  630. }
  631. lua_pushstring(_lua, enumStr.c_str());
  632. break;
  633. }
  634. // Object references/pointers (Lua userdata).
  635. case '<':
  636. {
  637. std::string type = sig;
  638. type = type.substr(0, type.find(">"));
  639. // Skip past the closing '>' (the semi-colon here is intentional-do not remove).
  640. while (*sig++ != '>');
  641. // Calculate the unique Lua type name.
  642. size_t i = type.find("::");
  643. while (i != std::string::npos)
  644. {
  645. // We use "" as the replacement here-this must match the preprocessor
  646. // define SCOPE_REPLACEMENT from the gameplay-luagen project.
  647. type.replace(i, 2, "");
  648. i = type.find("::");
  649. }
  650. void* ptr = va_arg(*list, void*);
  651. if (ptr == NULL)
  652. {
  653. lua_pushnil(_lua);
  654. }
  655. else
  656. {
  657. ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(_lua, sizeof(ScriptUtil::LuaObject));
  658. object->instance = ptr;
  659. object->owns = false;
  660. luaL_getmetatable(_lua, type.c_str());
  661. lua_setmetatable(_lua, -2);
  662. }
  663. break;
  664. }
  665. default:
  666. GP_ERROR("Invalid argument type '%d'.", *(sig - 1));
  667. break;
  668. }
  669. argumentCount++;
  670. luaL_checkstack(_lua, 1, "Too many arguments.");
  671. }
  672. }
  673. // Perform the function call.
  674. if (lua_pcall(_lua, argumentCount, resultCount, 0) != 0)
  675. GP_WARN("Failed to call function '%s' with error '%s'.", func, lua_tostring(_lua, -1));
  676. }
  677. void ScriptController::registerCallback(ScriptCallback callback, const std::string& function)
  678. {
  679. SAFE_DELETE(_callbacks[callback]);
  680. _callbacks[callback] = new std::string(function);
  681. }
  682. ScriptController::ScriptCallback ScriptController::toCallback(const char* name)
  683. {
  684. if (strcmp(name, "initialize") == 0)
  685. return ScriptController::INITIALIZE;
  686. else if (strcmp(name, "update") == 0)
  687. return ScriptController::UPDATE;
  688. else if (strcmp(name, "render") == 0)
  689. return ScriptController::RENDER;
  690. else if (strcmp(name, "finalize") == 0)
  691. return ScriptController::FINALIZE;
  692. else if (strcmp(name, "keyEvent") == 0)
  693. return ScriptController::KEY_EVENT;
  694. else if (strcmp(name, "touchEvent") == 0)
  695. return ScriptController::TOUCH_EVENT;
  696. else if (strcmp(name, "mouseEvent") == 0)
  697. return ScriptController::MOUSE_EVENT;
  698. else if (strcmp(name, "gamepadEvent") == 0)
  699. return ScriptController::GAMEPAD_EVENT;
  700. else
  701. return ScriptController::INVALID_CALLBACK;
  702. }
  703. // Helper macros.
  704. #define SCRIPT_EXECUTE_FUNCTION_NO_PARAM(type, checkfunc) \
  705. executeFunctionHelper(1, func, NULL, NULL); \
  706. type value = (type)checkfunc(_lua, -1); \
  707. lua_pop(_lua, -1); \
  708. return value;
  709. #define SCRIPT_EXECUTE_FUNCTION_PARAM(type, checkfunc) \
  710. va_list list; \
  711. va_start(list, args); \
  712. executeFunctionHelper(1, func, args, &list); \
  713. type value = (type)checkfunc(_lua, -1); \
  714. lua_pop(_lua, -1); \
  715. va_end(list); \
  716. return value;
  717. #define SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(type, checkfunc) \
  718. executeFunctionHelper(1, func, args, list); \
  719. type value = (type)checkfunc(_lua, -1); \
  720. lua_pop(_lua, -1); \
  721. return value;
  722. template<> void ScriptController::executeFunction<void>(const char* func)
  723. {
  724. executeFunctionHelper(0, func, NULL, NULL);
  725. }
  726. template<> bool ScriptController::executeFunction<bool>(const char* func)
  727. {
  728. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(bool, ScriptUtil::luaCheckBool);
  729. }
  730. template<> char ScriptController::executeFunction<char>(const char* func)
  731. {
  732. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(char, luaL_checkint);
  733. }
  734. template<> short ScriptController::executeFunction<short>(const char* func)
  735. {
  736. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(short, luaL_checkint);
  737. }
  738. template<> int ScriptController::executeFunction<int>(const char* func)
  739. {
  740. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(int, luaL_checkint);
  741. }
  742. template<> long ScriptController::executeFunction<long>(const char* func)
  743. {
  744. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(long, luaL_checklong);
  745. }
  746. template<> unsigned char ScriptController::executeFunction<unsigned char>(const char* func)
  747. {
  748. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned char, luaL_checkunsigned);
  749. }
  750. template<> unsigned short ScriptController::executeFunction<unsigned short>(const char* func)
  751. {
  752. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned short, luaL_checkunsigned);
  753. }
  754. template<> unsigned int ScriptController::executeFunction<unsigned int>(const char* func)
  755. {
  756. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned int, luaL_checkunsigned);
  757. }
  758. template<> unsigned long ScriptController::executeFunction<unsigned long>(const char* func)
  759. {
  760. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned long, luaL_checkunsigned);
  761. }
  762. template<> float ScriptController::executeFunction<float>(const char* func)
  763. {
  764. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(float, luaL_checknumber);
  765. }
  766. template<> double ScriptController::executeFunction<double>(const char* func)
  767. {
  768. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(double, luaL_checknumber);
  769. }
  770. template<> std::string ScriptController::executeFunction<std::string>(const char* func)
  771. {
  772. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(std::string, luaL_checkstring);
  773. }
  774. /** Template specialization. */
  775. template<> void ScriptController::executeFunction<void>(const char* func, const char* args, ...)
  776. {
  777. va_list list;
  778. va_start(list, args);
  779. executeFunctionHelper(0, func, args, &list);
  780. va_end(list);
  781. }
  782. /** Template specialization. */
  783. template<> bool ScriptController::executeFunction<bool>(const char* func, const char* args, ...)
  784. {
  785. SCRIPT_EXECUTE_FUNCTION_PARAM(bool, ScriptUtil::luaCheckBool);
  786. }
  787. /** Template specialization. */
  788. template<> char ScriptController::executeFunction<char>(const char* func, const char* args, ...)
  789. {
  790. SCRIPT_EXECUTE_FUNCTION_PARAM(char, luaL_checkint);
  791. }
  792. /** Template specialization. */
  793. template<> short ScriptController::executeFunction<short>(const char* func, const char* args, ...)
  794. {
  795. SCRIPT_EXECUTE_FUNCTION_PARAM(short, luaL_checkint);
  796. }
  797. /** Template specialization. */
  798. template<> int ScriptController::executeFunction<int>(const char* func, const char* args, ...)
  799. {
  800. SCRIPT_EXECUTE_FUNCTION_PARAM(int, luaL_checkint);
  801. }
  802. /** Template specialization. */
  803. template<> long ScriptController::executeFunction<long>(const char* func, const char* args, ...)
  804. {
  805. SCRIPT_EXECUTE_FUNCTION_PARAM(long, luaL_checklong);
  806. }
  807. /** Template specialization. */
  808. template<> unsigned char ScriptController::executeFunction<unsigned char>(const char* func, const char* args, ...)
  809. {
  810. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned char, luaL_checkunsigned);
  811. }
  812. /** Template specialization. */
  813. template<> unsigned short ScriptController::executeFunction<unsigned short>(const char* func, const char* args, ...)
  814. {
  815. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned short, luaL_checkunsigned);
  816. }
  817. /** Template specialization. */
  818. template<> unsigned int ScriptController::executeFunction<unsigned int>(const char* func, const char* args, ...)
  819. {
  820. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned int, luaL_checkunsigned);
  821. }
  822. /** Template specialization. */
  823. template<> unsigned long ScriptController::executeFunction<unsigned long>(const char* func, const char* args, ...)
  824. {
  825. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned long, luaL_checkunsigned);
  826. }
  827. /** Template specialization. */
  828. template<> float ScriptController::executeFunction<float>(const char* func, const char* args, ...)
  829. {
  830. SCRIPT_EXECUTE_FUNCTION_PARAM(float, luaL_checknumber);
  831. }
  832. /** Template specialization. */
  833. template<> double ScriptController::executeFunction<double>(const char* func, const char* args, ...)
  834. {
  835. SCRIPT_EXECUTE_FUNCTION_PARAM(double, luaL_checknumber);
  836. }
  837. /** Template specialization. */
  838. template<> std::string ScriptController::executeFunction<std::string>(const char* func, const char* args, ...)
  839. {
  840. SCRIPT_EXECUTE_FUNCTION_PARAM(std::string, luaL_checkstring);
  841. }
  842. /** Template specialization. */
  843. template<> void ScriptController::executeFunction<void>(const char* func, const char* args, va_list* list)
  844. {
  845. executeFunctionHelper(0, func, args, list);
  846. }
  847. /** Template specialization. */
  848. template<> bool ScriptController::executeFunction<bool>(const char* func, const char* args, va_list* list)
  849. {
  850. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(bool, ScriptUtil::luaCheckBool);
  851. }
  852. /** Template specialization. */
  853. template<> char ScriptController::executeFunction<char>(const char* func, const char* args, va_list* list)
  854. {
  855. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(char, luaL_checkint);
  856. }
  857. /** Template specialization. */
  858. template<> short ScriptController::executeFunction<short>(const char* func, const char* args, va_list* list)
  859. {
  860. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(short, luaL_checkint);
  861. }
  862. /** Template specialization. */
  863. template<> int ScriptController::executeFunction<int>(const char* func, const char* args, va_list* list)
  864. {
  865. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(int, luaL_checkint);
  866. }
  867. /** Template specialization. */
  868. template<> long ScriptController::executeFunction<long>(const char* func, const char* args, va_list* list)
  869. {
  870. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(long, luaL_checklong);
  871. }
  872. /** Template specialization. */
  873. template<> unsigned char ScriptController::executeFunction<unsigned char>(const char* func, const char* args, va_list* list)
  874. {
  875. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned char, luaL_checkunsigned);
  876. }
  877. /** Template specialization. */
  878. template<> unsigned short ScriptController::executeFunction<unsigned short>(const char* func, const char* args, va_list* list)
  879. {
  880. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned short, luaL_checkunsigned);
  881. }
  882. /** Template specialization. */
  883. template<> unsigned int ScriptController::executeFunction<unsigned int>(const char* func, const char* args, va_list* list)
  884. {
  885. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned int, luaL_checkunsigned);
  886. }
  887. /** Template specialization. */
  888. template<> unsigned long ScriptController::executeFunction<unsigned long>(const char* func, const char* args, va_list* list)
  889. {
  890. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned long, luaL_checkunsigned);
  891. }
  892. /** Template specialization. */
  893. template<> float ScriptController::executeFunction<float>(const char* func, const char* args, va_list* list)
  894. {
  895. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(float, luaL_checknumber);
  896. }
  897. /** Template specialization. */
  898. template<> double ScriptController::executeFunction<double>(const char* func, const char* args, va_list* list)
  899. {
  900. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(double, luaL_checknumber);
  901. }
  902. /** Template specialization. */
  903. template<> std::string ScriptController::executeFunction<std::string>(const char* func, const char* args, va_list* list)
  904. {
  905. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(std::string, luaL_checkstring);
  906. }
  907. }