ScriptController.cpp 31 KB

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