ScriptController.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  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 (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 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 NULL; \
  23. \
  24. /* Create an array to store the values. */ \
  25. type* values = (type*)malloc(sizeof(type)*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. values[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 values
  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(std::string name, bool value, 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.size() > 0)
  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(std::string name, double value, 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.size() > 0)
  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(std::string name, std::string value, 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.size() > 0)
  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, 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.size() > 0)
  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 != tablename.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 != tablename.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.size() > 0)
  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(std::string base, 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. bool* ScriptUtil::getBoolPointer(int index)
  229. {
  230. GENERATE_LUA_GET_POINTER(bool, luaCheckBool);
  231. }
  232. short* ScriptUtil::getShortPointer(int index)
  233. {
  234. GENERATE_LUA_GET_POINTER(short, (short)luaL_checkint);
  235. }
  236. int* ScriptUtil::getIntPointer(int index)
  237. {
  238. GENERATE_LUA_GET_POINTER(int, (int)luaL_checkint);
  239. }
  240. long* ScriptUtil::getLongPointer(int index)
  241. {
  242. GENERATE_LUA_GET_POINTER(long, (long)luaL_checkint);
  243. }
  244. unsigned char* ScriptUtil::getUnsignedCharPointer(int index)
  245. {
  246. GENERATE_LUA_GET_POINTER(unsigned char, (unsigned char)luaL_checkunsigned);
  247. }
  248. unsigned short* ScriptUtil::getUnsignedShortPointer(int index)
  249. {
  250. GENERATE_LUA_GET_POINTER(unsigned short, (unsigned short)luaL_checkunsigned);
  251. }
  252. unsigned int* ScriptUtil::getUnsignedIntPointer(int index)
  253. {
  254. GENERATE_LUA_GET_POINTER(unsigned int, (unsigned int)luaL_checkunsigned);
  255. }
  256. unsigned long* ScriptUtil::getUnsignedLongPointer(int index)
  257. {
  258. GENERATE_LUA_GET_POINTER(unsigned long, (unsigned long)luaL_checkunsigned);
  259. }
  260. float* ScriptUtil::getFloatPointer(int index)
  261. {
  262. GENERATE_LUA_GET_POINTER(float, (float)luaL_checknumber);
  263. }
  264. 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. " filename = FileSystem.getResourcePath() .. filename\n"
  470. " end\n"
  471. " return oldLoadfile(filename)\n"
  472. " end\n"
  473. "end\n";
  474. static const char* lua_dofile_function =
  475. "do\n"
  476. " local oldDofile = dofile\n"
  477. " dofile = function(filename)\n"
  478. " if filename ~= nil and not FileSystem.isAbsolutePath(filename) then\n"
  479. " filename = FileSystem.getResourcePath() .. filename\n"
  480. " end\n"
  481. " return oldDofile(filename)\n"
  482. " end\n"
  483. "end\n";
  484. #endif
  485. void ScriptController::initialize()
  486. {
  487. _lua = luaL_newstate();
  488. if (!_lua)
  489. GP_ERROR("Failed to initialize Lua scripting engine.");
  490. luaL_openlibs(_lua);
  491. lua_RegisterAllBindings();
  492. // Create our own print() function that uses gameplay::print.
  493. if (luaL_dostring(_lua, lua_print_function))
  494. GP_ERROR("Failed to load custom print() function with error: '%s'.", lua_tostring(_lua, -1));
  495. #ifndef WIN32
  496. // Change the functions that read a file to use FileSystem.getResourcePath as their base path.
  497. if (luaL_dostring(_lua, lua_loadfile_function))
  498. GP_ERROR("Failed to load custom loadfile() function with error: '%s'.", lua_tostring(_lua, -1));
  499. if (luaL_dostring(_lua, lua_dofile_function))
  500. GP_ERROR("Failed to load custom dofile() function with error: '%s'.", lua_tostring(_lua, -1));
  501. #endif
  502. }
  503. void ScriptController::initializeGame()
  504. {
  505. if (_callbacks[INITIALIZE])
  506. {
  507. executeFunction<void>(_callbacks[INITIALIZE]->c_str());
  508. }
  509. }
  510. void ScriptController::finalize()
  511. {
  512. if (_lua)
  513. lua_close(_lua);
  514. }
  515. void ScriptController::finalizeGame()
  516. {
  517. if (_callbacks[FINALIZE])
  518. {
  519. executeFunction<void>(_callbacks[FINALIZE]->c_str());
  520. }
  521. // Perform a full garbage collection cycle.
  522. lua_gc(_lua, LUA_GCCOLLECT, 0);
  523. }
  524. void ScriptController::update(float elapsedTime)
  525. {
  526. if (_callbacks[UPDATE])
  527. {
  528. executeFunction<void>(_callbacks[UPDATE]->c_str(), "f", elapsedTime);
  529. }
  530. }
  531. void ScriptController::render(float elapsedTime)
  532. {
  533. if (_callbacks[RENDER])
  534. {
  535. executeFunction<void>(_callbacks[RENDER]->c_str(), "f", elapsedTime);
  536. }
  537. }
  538. void ScriptController::keyEvent(Keyboard::KeyEvent evt, int key)
  539. {
  540. if (_callbacks[KEY_EVENT])
  541. {
  542. executeFunction<void>(_callbacks[KEY_EVENT]->c_str(), "[Keyboard::KeyEvent][Keyboard::Key]", evt, key);
  543. }
  544. }
  545. void ScriptController::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  546. {
  547. if (_callbacks[TOUCH_EVENT])
  548. {
  549. executeFunction<void>(_callbacks[TOUCH_EVENT]->c_str(), "[Touch::TouchEvent]iiui", evt, x, y, contactIndex);
  550. }
  551. }
  552. bool ScriptController::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
  553. {
  554. if (_callbacks[MOUSE_EVENT])
  555. {
  556. return executeFunction<bool>(_callbacks[MOUSE_EVENT]->c_str(), "[Mouse::MouseEvent]iiii", evt, x, y, wheelDelta);
  557. }
  558. return false;
  559. }
  560. void ScriptController::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
  561. {
  562. if (_callbacks[GAMEPAD_EVENT])
  563. {
  564. executeFunction<void>(_callbacks[GAMEPAD_EVENT]->c_str(), "[Gamepad::GamepadEvent]<Gamepad>", evt, gamepad);
  565. }
  566. }
  567. void ScriptController::executeFunctionHelper(int resultCount, const char* func, const char* args, va_list* list)
  568. {
  569. if (func == NULL)
  570. {
  571. GP_ERROR("Lua function name must be non-null.");
  572. return;
  573. }
  574. const char* sig = args;
  575. int argumentCount = 0;
  576. lua_getglobal(_lua, func);
  577. // Push the arguments to the Lua stack if there are any.
  578. if (sig)
  579. {
  580. while (true)
  581. {
  582. if (!(*sig))
  583. break;
  584. switch(*sig++)
  585. {
  586. // Signed integers.
  587. case 'c':
  588. case 'h':
  589. case 'i':
  590. case 'l':
  591. lua_pushinteger(_lua, va_arg(*list, int));
  592. break;
  593. // Unsigned integers.
  594. case 'u':
  595. // Skip past the actual type (long, int, short, char).
  596. sig++;
  597. lua_pushunsigned(_lua, va_arg(*list, int));
  598. break;
  599. // Booleans.
  600. case 'b':
  601. lua_pushboolean(_lua, va_arg(*list, int));
  602. break;
  603. // Floating point numbers.
  604. case 'f':
  605. case 'd':
  606. lua_pushnumber(_lua, va_arg(*list, double));
  607. break;
  608. // Strings.
  609. case 's':
  610. lua_pushstring(_lua, va_arg(*list, char*));
  611. break;
  612. // Pointers.
  613. case 'p':
  614. lua_pushlightuserdata(_lua, va_arg(*list, void*));
  615. break;
  616. // Enums.
  617. case '[':
  618. {
  619. std::string type = sig;
  620. type = type.substr(0, type.find("]"));
  621. // Skip past the closing ']' (the semi-colon here is intentional-do not remove).
  622. while (*sig++ != ']');
  623. unsigned int value = va_arg(*list, int);
  624. std::string enumStr = "";
  625. for (unsigned int i = 0; enumStr.size() == 0 && i < _stringFromEnum.size(); i++)
  626. {
  627. enumStr = (*_stringFromEnum[i])(type, value);
  628. }
  629. lua_pushstring(_lua, enumStr.c_str());
  630. break;
  631. }
  632. // Object references/pointers (Lua userdata).
  633. case '<':
  634. {
  635. std::string type = sig;
  636. type = type.substr(0, type.find(">"));
  637. // Skip past the closing '>' (the semi-colon here is intentional-do not remove).
  638. while (*sig++ != '>');
  639. // Calculate the unique Lua type name.
  640. size_t i = type.find("::");
  641. while (i != type.npos)
  642. {
  643. // We use "" as the replacement here-this must match the preprocessor
  644. // define SCOPE_REPLACEMENT from the gameplay-luagen project.
  645. type.replace(i, 2, "");
  646. i = type.find("::");
  647. }
  648. void* ptr = va_arg(*list, void*);
  649. if (ptr == NULL)
  650. {
  651. lua_pushnil(_lua);
  652. }
  653. else
  654. {
  655. ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(_lua, sizeof(ScriptUtil::LuaObject));
  656. object->instance = ptr;
  657. object->owns = false;
  658. luaL_getmetatable(_lua, type.c_str());
  659. lua_setmetatable(_lua, -2);
  660. }
  661. break;
  662. }
  663. default:
  664. GP_ERROR("Invalid argument type '%d'.", *(sig - 1));
  665. }
  666. argumentCount++;
  667. luaL_checkstack(_lua, 1, "Too many arguments.");
  668. }
  669. }
  670. // Perform the function call.
  671. if (lua_pcall(_lua, argumentCount, resultCount, 0) != 0)
  672. GP_WARN("Failed to call function '%s' with error '%s'.", func, lua_tostring(_lua, -1));
  673. }
  674. void ScriptController::registerCallback(ScriptCallback callback, std::string function)
  675. {
  676. SAFE_DELETE(_callbacks[callback]);
  677. _callbacks[callback] = new std::string(function);
  678. }
  679. ScriptController::ScriptCallback ScriptController::toCallback(const char* name)
  680. {
  681. if (strcmp(name, "initialize") == 0)
  682. return ScriptController::INITIALIZE;
  683. else if (strcmp(name, "update") == 0)
  684. return ScriptController::UPDATE;
  685. else if (strcmp(name, "render") == 0)
  686. return ScriptController::RENDER;
  687. else if (strcmp(name, "finalize") == 0)
  688. return ScriptController::FINALIZE;
  689. else if (strcmp(name, "keyEvent") == 0)
  690. return ScriptController::KEY_EVENT;
  691. else if (strcmp(name, "touchEvent") == 0)
  692. return ScriptController::TOUCH_EVENT;
  693. else if (strcmp(name, "mouseEvent") == 0)
  694. return ScriptController::MOUSE_EVENT;
  695. else if (strcmp(name, "gamepadEvent") == 0)
  696. return ScriptController::GAMEPAD_EVENT;
  697. else
  698. return ScriptController::INVALID_CALLBACK;
  699. }
  700. // Helper macros.
  701. #define SCRIPT_EXECUTE_FUNCTION_NO_PARAM(type, checkfunc) \
  702. executeFunctionHelper(1, func, NULL, NULL); \
  703. type value = (type)checkfunc(_lua, -1); \
  704. lua_pop(_lua, -1); \
  705. return value;
  706. #define SCRIPT_EXECUTE_FUNCTION_PARAM(type, checkfunc) \
  707. va_list list; \
  708. va_start(list, args); \
  709. executeFunctionHelper(1, func, args, &list); \
  710. type value = (type)checkfunc(_lua, -1); \
  711. lua_pop(_lua, -1); \
  712. va_end(list); \
  713. return value;
  714. #define SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(type, checkfunc) \
  715. executeFunctionHelper(1, func, args, list); \
  716. type value = (type)checkfunc(_lua, -1); \
  717. lua_pop(_lua, -1); \
  718. return value;
  719. template<> void ScriptController::executeFunction<void>(const char* func)
  720. {
  721. executeFunctionHelper(0, func, NULL, NULL);
  722. }
  723. template<> bool ScriptController::executeFunction<bool>(const char* func)
  724. {
  725. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(bool, ScriptUtil::luaCheckBool);
  726. }
  727. template<> char ScriptController::executeFunction<char>(const char* func)
  728. {
  729. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(char, luaL_checkint);
  730. }
  731. template<> short ScriptController::executeFunction<short>(const char* func)
  732. {
  733. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(short, luaL_checkint);
  734. }
  735. template<> int ScriptController::executeFunction<int>(const char* func)
  736. {
  737. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(int, luaL_checkint);
  738. }
  739. template<> long ScriptController::executeFunction<long>(const char* func)
  740. {
  741. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(long, luaL_checklong);
  742. }
  743. template<> unsigned char ScriptController::executeFunction<unsigned char>(const char* func)
  744. {
  745. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned char, luaL_checkunsigned);
  746. }
  747. template<> unsigned short ScriptController::executeFunction<unsigned short>(const char* func)
  748. {
  749. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned short, luaL_checkunsigned);
  750. }
  751. template<> unsigned int ScriptController::executeFunction<unsigned int>(const char* func)
  752. {
  753. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned int, luaL_checkunsigned);
  754. }
  755. template<> unsigned long ScriptController::executeFunction<unsigned long>(const char* func)
  756. {
  757. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(unsigned long, luaL_checkunsigned);
  758. }
  759. template<> float ScriptController::executeFunction<float>(const char* func)
  760. {
  761. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(float, luaL_checknumber);
  762. }
  763. template<> double ScriptController::executeFunction<double>(const char* func)
  764. {
  765. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(double, luaL_checknumber);
  766. }
  767. template<> std::string ScriptController::executeFunction<std::string>(const char* func)
  768. {
  769. SCRIPT_EXECUTE_FUNCTION_NO_PARAM(std::string, luaL_checkstring);
  770. }
  771. /** Template specialization. */
  772. template<> void ScriptController::executeFunction<void>(const char* func, const char* args, ...)
  773. {
  774. va_list list;
  775. va_start(list, args);
  776. executeFunctionHelper(0, func, args, &list);
  777. va_end(list);
  778. }
  779. /** Template specialization. */
  780. template<> bool ScriptController::executeFunction<bool>(const char* func, const char* args, ...)
  781. {
  782. SCRIPT_EXECUTE_FUNCTION_PARAM(bool, ScriptUtil::luaCheckBool);
  783. }
  784. /** Template specialization. */
  785. template<> char ScriptController::executeFunction<char>(const char* func, const char* args, ...)
  786. {
  787. SCRIPT_EXECUTE_FUNCTION_PARAM(char, luaL_checkint);
  788. }
  789. /** Template specialization. */
  790. template<> short ScriptController::executeFunction<short>(const char* func, const char* args, ...)
  791. {
  792. SCRIPT_EXECUTE_FUNCTION_PARAM(short, luaL_checkint);
  793. }
  794. /** Template specialization. */
  795. template<> int ScriptController::executeFunction<int>(const char* func, const char* args, ...)
  796. {
  797. SCRIPT_EXECUTE_FUNCTION_PARAM(int, luaL_checkint);
  798. }
  799. /** Template specialization. */
  800. template<> long ScriptController::executeFunction<long>(const char* func, const char* args, ...)
  801. {
  802. SCRIPT_EXECUTE_FUNCTION_PARAM(long, luaL_checklong);
  803. }
  804. /** Template specialization. */
  805. template<> unsigned char ScriptController::executeFunction<unsigned char>(const char* func, const char* args, ...)
  806. {
  807. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned char, luaL_checkunsigned);
  808. }
  809. /** Template specialization. */
  810. template<> unsigned short ScriptController::executeFunction<unsigned short>(const char* func, const char* args, ...)
  811. {
  812. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned short, luaL_checkunsigned);
  813. }
  814. /** Template specialization. */
  815. template<> unsigned int ScriptController::executeFunction<unsigned int>(const char* func, const char* args, ...)
  816. {
  817. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned int, luaL_checkunsigned);
  818. }
  819. /** Template specialization. */
  820. template<> unsigned long ScriptController::executeFunction<unsigned long>(const char* func, const char* args, ...)
  821. {
  822. SCRIPT_EXECUTE_FUNCTION_PARAM(unsigned long, luaL_checkunsigned);
  823. }
  824. /** Template specialization. */
  825. template<> float ScriptController::executeFunction<float>(const char* func, const char* args, ...)
  826. {
  827. SCRIPT_EXECUTE_FUNCTION_PARAM(float, luaL_checknumber);
  828. }
  829. /** Template specialization. */
  830. template<> double ScriptController::executeFunction<double>(const char* func, const char* args, ...)
  831. {
  832. SCRIPT_EXECUTE_FUNCTION_PARAM(double, luaL_checknumber);
  833. }
  834. /** Template specialization. */
  835. template<> std::string ScriptController::executeFunction<std::string>(const char* func, const char* args, ...)
  836. {
  837. SCRIPT_EXECUTE_FUNCTION_PARAM(std::string, luaL_checkstring);
  838. }
  839. /** Template specialization. */
  840. template<> void ScriptController::executeFunction<void>(const char* func, const char* args, va_list* list)
  841. {
  842. executeFunctionHelper(0, func, args, list);
  843. }
  844. /** Template specialization. */
  845. template<> bool ScriptController::executeFunction<bool>(const char* func, const char* args, va_list* list)
  846. {
  847. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(bool, ScriptUtil::luaCheckBool);
  848. }
  849. /** Template specialization. */
  850. template<> char ScriptController::executeFunction<char>(const char* func, const char* args, va_list* list)
  851. {
  852. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(char, luaL_checkint);
  853. }
  854. /** Template specialization. */
  855. template<> short ScriptController::executeFunction<short>(const char* func, const char* args, va_list* list)
  856. {
  857. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(short, luaL_checkint);
  858. }
  859. /** Template specialization. */
  860. template<> int ScriptController::executeFunction<int>(const char* func, const char* args, va_list* list)
  861. {
  862. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(int, luaL_checkint);
  863. }
  864. /** Template specialization. */
  865. template<> long ScriptController::executeFunction<long>(const char* func, const char* args, va_list* list)
  866. {
  867. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(long, luaL_checklong);
  868. }
  869. /** Template specialization. */
  870. template<> unsigned char ScriptController::executeFunction<unsigned char>(const char* func, const char* args, va_list* list)
  871. {
  872. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned char, luaL_checkunsigned);
  873. }
  874. /** Template specialization. */
  875. template<> unsigned short ScriptController::executeFunction<unsigned short>(const char* func, const char* args, va_list* list)
  876. {
  877. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned short, luaL_checkunsigned);
  878. }
  879. /** Template specialization. */
  880. template<> unsigned int ScriptController::executeFunction<unsigned int>(const char* func, const char* args, va_list* list)
  881. {
  882. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned int, luaL_checkunsigned);
  883. }
  884. /** Template specialization. */
  885. template<> unsigned long ScriptController::executeFunction<unsigned long>(const char* func, const char* args, va_list* list)
  886. {
  887. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(unsigned long, luaL_checkunsigned);
  888. }
  889. /** Template specialization. */
  890. template<> float ScriptController::executeFunction<float>(const char* func, const char* args, va_list* list)
  891. {
  892. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(float, luaL_checknumber);
  893. }
  894. /** Template specialization. */
  895. template<> double ScriptController::executeFunction<double>(const char* func, const char* args, va_list* list)
  896. {
  897. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(double, luaL_checknumber);
  898. }
  899. /** Template specialization. */
  900. template<> std::string ScriptController::executeFunction<std::string>(const char* func, const char* args, va_list* list)
  901. {
  902. SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(std::string, luaL_checkstring);
  903. }
  904. }