LuaScriptInstance.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. //
  2. // Copyright (c) 2008-2013 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "CoreEvents.h"
  24. #include "Context.h"
  25. #include "Log.h"
  26. #include "LuaFile.h"
  27. #include "LuaScript.h"
  28. #include "LuaScriptInstance.h"
  29. #include "MemoryBuffer.h"
  30. #include "PhysicsEvents.h"
  31. #include "ResourceCache.h"
  32. #include "ToluaUrho3DEx.h"
  33. #include "ProcessUtils.h"
  34. #include "VectorBuffer.h"
  35. extern "C"
  36. {
  37. #include <lua.h>
  38. #include <lualib.h>
  39. #include <lauxlib.h>
  40. }
  41. #include "tolua++.h"
  42. namespace Urho3D
  43. {
  44. static const char* scriptObjectMethodNames[] = {
  45. ".Start",
  46. ".Stop",
  47. // ".DelayedStart",
  48. ".Update",
  49. ".PostUpdate",
  50. ".FixedUpdate",
  51. ".FixedPostUpdate",
  52. ".Load",
  53. ".Save",
  54. ".ReadNetworkUpdate",
  55. ".WriteNetworkUpdate",
  56. ".ApplyAttributes"
  57. };
  58. LuaScriptInstance::LuaScriptInstance(Context* context) :
  59. Component(context),
  60. scriptObjectRef_(LUA_REFNIL)
  61. {
  62. luaScript_ = GetSubsystem<LuaScript>();
  63. luaState_ = luaScript_->GetLuaState();
  64. for (unsigned i = 0; i < MAX_LUA_SCRIPT_OBJECT_METHODS; ++i)
  65. scriptObjectMethodRefs_[i] = LUA_REFNIL;
  66. }
  67. LuaScriptInstance::~LuaScriptInstance()
  68. {
  69. ReleaseObject();
  70. }
  71. void LuaScriptInstance::RegisterObject(Context* context)
  72. {
  73. context->RegisterFactory<LuaScriptInstance>(LOGIC_CATEGORY);
  74. // ACCESSOR_ATTRIBUTE(LuaScriptInstance, VAR_BOOL, "Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
  75. REF_ACCESSOR_ATTRIBUTE(LuaScriptInstance, VAR_STRING, "Script File Name", GetScriptFileName, SetScriptFileName, String, String::EMPTY, AM_DEFAULT);
  76. REF_ACCESSOR_ATTRIBUTE(LuaScriptInstance, VAR_STRING, "Script Object Type", GetScriptObjectType, SetScriptObjectType, String, String::EMPTY, AM_DEFAULT);
  77. ACCESSOR_ATTRIBUTE(LuaScriptInstance, VAR_BUFFER, "Script Data", GetScriptDataAttr, SetScriptDataAttr, PODVector<unsigned char>, Variant::emptyBuffer, AM_FILE | AM_NOEDIT);
  78. ACCESSOR_ATTRIBUTE(LuaScriptInstance, VAR_BUFFER, "Script Network Data", GetScriptNetworkDataAttr, SetScriptNetworkDataAttr, PODVector<unsigned char>, Variant::emptyBuffer, AM_NET | AM_NOEDIT);
  79. }
  80. void LuaScriptInstance::ApplyAttributes()
  81. {
  82. CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_APPLYATTRIBUTES]);
  83. }
  84. void LuaScriptInstance::OnSetEnabled()
  85. {
  86. if (enabled_)
  87. SubscribeToScriptMethodEvents();
  88. else
  89. UnsubscribeFromScriptMethodEvents();
  90. }
  91. bool LuaScriptInstance::CreateObject(const String& scriptObjectType)
  92. {
  93. SetScriptFileName(String::EMPTY);
  94. SetScriptObjectType(scriptObjectType);
  95. return scriptObjectRef_ != LUA_REFNIL;
  96. }
  97. bool LuaScriptInstance::CreateObject(const String& scriptFileName, const String& scriptObjectType)
  98. {
  99. SetScriptFileName(scriptFileName);
  100. SetScriptObjectType(scriptObjectType);
  101. return scriptObjectRef_ != LUA_REFNIL;
  102. }
  103. void LuaScriptInstance::SetScriptFileName(const String& scriptFileName)
  104. {
  105. if (scriptFileName_ == scriptFileName)
  106. return;
  107. scriptFileName_ = scriptFileName;
  108. if (scriptFileName_.Empty())
  109. return;
  110. ResourceCache* cache = GetSubsystem<ResourceCache>();
  111. LuaFile* luaFile = cache->GetResource<LuaFile>(scriptFileName_);
  112. if (!luaFile)
  113. return;
  114. if (!luaFile->LoadAndExecute(luaState_))
  115. LOGERROR("Execute Lua file failed: " + scriptFileName_);
  116. }
  117. void LuaScriptInstance::SetScriptObjectType(const String& scriptObjectType)
  118. {
  119. if (scriptObjectType_ == scriptObjectType)
  120. return;
  121. ReleaseObject();
  122. int top = lua_gettop(luaState_);
  123. lua_getglobal(luaState_, "CreateScriptObjectInstance");
  124. if (!lua_isfunction(luaState_, -1))
  125. {
  126. LOGERROR("Could not find lua function CreateScriptObjectInstance");
  127. lua_settop(luaState_, top);
  128. return;
  129. }
  130. // Get table as first paramter.
  131. lua_getglobal(luaState_, scriptObjectType.CString());
  132. if (!lua_istable(luaState_, -1))
  133. {
  134. LOGERROR("Could not find lua table " + scriptObjectType);
  135. lua_settop(luaState_, top);
  136. return;
  137. }
  138. // Push this as second parameter.
  139. tolua_pushusertype(luaState_, (void*)this, "LuaScriptInstance");
  140. // Call ObjectType:new function.
  141. if (lua_pcall(luaState_, 2, 1, 0) != 0)
  142. {
  143. const char* message = lua_tostring(luaState_, -1);
  144. LOGERROR("Execute Lua function failed: " + String(message));
  145. lua_settop(luaState_, top);
  146. return;
  147. }
  148. scriptObjectType_ = scriptObjectType;
  149. scriptObjectRef_ = luaL_ref(luaState_, LUA_REGISTRYINDEX);
  150. // Find script object method refs.
  151. FindScriptObjectMethodRefs();
  152. }
  153. void LuaScriptInstance::SetScriptDataAttr(PODVector<unsigned char> data)
  154. {
  155. int functionRef = scriptObjectMethodRefs_[LSOM_LOAD];
  156. if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
  157. return;
  158. MemoryBuffer buf(data);
  159. CallScriptObjectFunction(functionRef, (Deserializer&)buf);
  160. }
  161. void LuaScriptInstance::SetScriptNetworkDataAttr(PODVector<unsigned char> data)
  162. {
  163. int functionRef = scriptObjectMethodRefs_[LSOM_READNETWORKUPDATE];
  164. if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
  165. return;
  166. MemoryBuffer buf(data);
  167. CallScriptObjectFunction(functionRef, (Deserializer&)buf);
  168. }
  169. void LuaScriptInstance::ScriptSubscribeToEvent(const String& eventName, const String& functionName)
  170. {
  171. String realFunctionName = functionName.Replaced(":", ".");
  172. int functionRef = luaScript_->GetScriptFunctionRef(realFunctionName);
  173. if (functionRef != LUA_REFNIL)
  174. {
  175. StringHash eventType(eventName);
  176. SubscribeToEvent(eventType, HANDLER(LuaScriptInstance, HandleEvent));
  177. eventTypeToFunctionRefMap_[eventType] = functionRef;
  178. }
  179. }
  180. void LuaScriptInstance::ScriptUnsubscribeFromEvent(const String& eventName)
  181. {
  182. StringHash eventType(eventName);
  183. HashMap<StringHash, int>::Iterator i = eventTypeToFunctionRefMap_.Find(eventType);
  184. if (i != eventTypeToFunctionRefMap_.End())
  185. {
  186. UnsubscribeFromEvent(eventType);
  187. eventTypeToFunctionRefMap_.Erase(i);
  188. }
  189. }
  190. void LuaScriptInstance::ScriptUnsubscribeFromAllEvents()
  191. {
  192. if (eventTypeToFunctionRefMap_.Empty())
  193. return;
  194. UnsubscribeFromAllEvents();
  195. eventTypeToFunctionRefMap_.Clear();
  196. }
  197. void LuaScriptInstance::ScriptSubscribeToEvent(void* sender, const String& eventName, const String& functionName)
  198. {
  199. String realFunctionName = functionName.Replaced(":", ".");
  200. int functionRef = luaScript_->GetScriptFunctionRef(realFunctionName);
  201. if (functionRef != LUA_REFNIL)
  202. {
  203. Object* object = (Object*)sender;
  204. StringHash eventType(eventName);
  205. SubscribeToEvent(object, eventType, HANDLER(LuaScriptInstance, HandleObjectEvent));
  206. objectToEventTypeToFunctionRefMap_[object][eventType] = functionRef;
  207. }
  208. }
  209. void LuaScriptInstance::ScriptUnsubscribeFromEvent(void* sender, const String& eventName)
  210. {
  211. StringHash eventType(eventName);
  212. Object* object = (Object*)sender ;
  213. HashMap<StringHash, int>::Iterator i = objectToEventTypeToFunctionRefMap_[object].Find(eventType);
  214. if (i != objectToEventTypeToFunctionRefMap_[object].End())
  215. {
  216. UnsubscribeFromEvent(object, eventType);
  217. objectToEventTypeToFunctionRefMap_[object].Erase(i);
  218. }
  219. }
  220. void LuaScriptInstance::ScriptUnsubscribeFromEvents(void* sender)
  221. {
  222. Object* object = (Object*)sender;
  223. HashMap<Object*, HashMap<StringHash, int> >::Iterator it = objectToEventTypeToFunctionRefMap_.Find(object);
  224. if (it == objectToEventTypeToFunctionRefMap_.End())
  225. return;
  226. UnsubscribeFromEvents(object);
  227. objectToEventTypeToFunctionRefMap_.Erase(it);
  228. }
  229. bool LuaScriptInstance::ExecuteFunction(const String& functionName, const VariantVector& parameters)
  230. {
  231. if (scriptObjectRef_ == LUA_REFNIL)
  232. return false;
  233. int functionRef = luaScript_->GetScriptFunctionRef(scriptObjectType_ + "." + functionName);
  234. if (functionRef == LUA_REFNIL)
  235. return false;
  236. return CallScriptObjectFunction(functionRef, parameters);
  237. }
  238. PODVector<unsigned char> LuaScriptInstance::GetScriptDataAttr() const
  239. {
  240. int functionRef = scriptObjectMethodRefs_[LSOM_SAVE];
  241. if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
  242. return PODVector<unsigned char>();
  243. VectorBuffer buf;
  244. CallScriptObjectFunction(functionRef, (Serializer&)buf);
  245. return buf.GetBuffer();
  246. }
  247. PODVector<unsigned char> LuaScriptInstance::GetScriptNetworkDataAttr() const
  248. {
  249. int functionRef = scriptObjectMethodRefs_[LSOM_WRITENETWORKUPDATE];
  250. if (scriptObjectRef_ == LUA_REFNIL || functionRef == LUA_REFNIL)
  251. return PODVector<unsigned char>();
  252. VectorBuffer buf;
  253. CallScriptObjectFunction(functionRef, (Serializer&)buf);
  254. return buf.GetBuffer();
  255. }
  256. void LuaScriptInstance::FindScriptObjectMethodRefs()
  257. {
  258. for (unsigned i = 0; i < MAX_LUA_SCRIPT_OBJECT_METHODS; ++i)
  259. scriptObjectMethodRefs_[i] = luaScript_->GetScriptFunctionRef(scriptObjectType_ + scriptObjectMethodNames[i], true);
  260. if (enabled_)
  261. SubscribeToScriptMethodEvents();
  262. }
  263. void LuaScriptInstance::SubscribeToScriptMethodEvents()
  264. {
  265. if (scriptObjectMethodRefs_[LSOM_UPDATE] != LUA_REFNIL)
  266. SubscribeToEvent(E_UPDATE, HANDLER(LuaScriptInstance, HandleUpdate));
  267. if (scriptObjectMethodRefs_[LSOM_POSTUPDATE] != LUA_REFNIL)
  268. SubscribeToEvent(E_POSTUPDATE, HANDLER(LuaScriptInstance, HandlePostUpdate));
  269. if (scriptObjectMethodRefs_[LSOM_FIXEDUPDATE] != LUA_REFNIL)
  270. SubscribeToEvent(E_PHYSICSPRESTEP, HANDLER(LuaScriptInstance, HandleFixedUpdate));
  271. if (scriptObjectMethodRefs_[LSOM_FIXEDPOSTUPDATE] != LUA_REFNIL)
  272. SubscribeToEvent(E_PHYSICSPOSTSTEP, HANDLER(LuaScriptInstance, HandlePostFixedUpdate));
  273. }
  274. void LuaScriptInstance::UnsubscribeFromScriptMethodEvents()
  275. {
  276. if (scriptObjectMethodRefs_[LSOM_UPDATE] != LUA_REFNIL)
  277. UnsubscribeFromEvent(E_UPDATE);
  278. if (scriptObjectMethodRefs_[LSOM_POSTUPDATE] != LUA_REFNIL)
  279. UnsubscribeFromEvent(E_POSTUPDATE);
  280. if (scriptObjectMethodRefs_[LSOM_FIXEDUPDATE] != LUA_REFNIL)
  281. UnsubscribeFromEvent(E_PHYSICSPRESTEP);
  282. if (scriptObjectMethodRefs_[LSOM_FIXEDPOSTUPDATE] != LUA_REFNIL)
  283. UnsubscribeFromEvent(E_PHYSICSPOSTSTEP);
  284. }
  285. void LuaScriptInstance::HandleUpdate(StringHash eventType, VariantMap& eventData)
  286. {
  287. using namespace Update;
  288. float timeStep = eventData[P_TIMESTEP].GetFloat();
  289. CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_UPDATE], timeStep);
  290. }
  291. void LuaScriptInstance::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
  292. {
  293. using namespace PostUpdate;
  294. float timeStep = eventData[P_TIMESTEP].GetFloat();
  295. CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_POSTUPDATE], timeStep);
  296. }
  297. void LuaScriptInstance::HandleFixedUpdate(StringHash eventType, VariantMap& eventData)
  298. {
  299. using namespace PhysicsPreStep;
  300. float timeStep = eventData[P_TIMESTEP].GetFloat();
  301. CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_FIXEDUPDATE], timeStep);
  302. }
  303. void LuaScriptInstance::HandlePostFixedUpdate(StringHash eventType, VariantMap& eventData)
  304. {
  305. using namespace PhysicsPostStep;
  306. float timeStep = eventData[P_TIMESTEP].GetFloat();
  307. CallScriptObjectFunction(scriptObjectMethodRefs_[LSOM_FIXEDPOSTUPDATE], timeStep);
  308. }
  309. void LuaScriptInstance::HandleEvent(StringHash eventType, VariantMap& eventData)
  310. {
  311. if (scriptObjectRef_ == LUA_REFNIL)
  312. return;
  313. int functionRef = eventTypeToFunctionRefMap_[eventType];
  314. if (functionRef == LUA_REFNIL)
  315. return;
  316. CallScriptObjectFunction(functionRef, eventType, eventData);
  317. }
  318. void LuaScriptInstance::HandleObjectEvent(StringHash eventType, VariantMap& eventData)
  319. {
  320. if (scriptObjectRef_ == LUA_REFNIL)
  321. return;
  322. Object* object = GetEventSender();
  323. int functionRef = objectToEventTypeToFunctionRefMap_[object][eventType];
  324. if (functionRef == LUA_REFNIL)
  325. return;
  326. CallScriptObjectFunction(functionRef, eventType, eventData);
  327. }
  328. void LuaScriptInstance::ReleaseObject()
  329. {
  330. if (scriptObjectRef_ == LUA_REFNIL)
  331. return;
  332. if (enabled_)
  333. UnsubscribeFromScriptMethodEvents();
  334. // Unref script object.
  335. luaL_unref(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  336. scriptObjectRef_ = LUA_REFNIL;
  337. int top = lua_gettop(luaState_);
  338. lua_getglobal(luaState_, "DestroyScriptObjectInstance");
  339. if (!lua_isfunction(luaState_, -1))
  340. {
  341. LOGERROR("Could not find lua function DestroyScriptObjectInstance");
  342. lua_settop(luaState_, top);
  343. return;
  344. }
  345. // Push this as second parameter.
  346. tolua_pushusertype(luaState_, (void*)this, "LuaScriptInstance");
  347. if (lua_pcall(luaState_, 1, 0, 0) != 0)
  348. {
  349. const char* message = lua_tostring(luaState_, -1);
  350. LOGERROR("Execute Lua function failed: " + String(message));
  351. lua_settop(luaState_, top);
  352. }
  353. }
  354. void LuaScriptInstance::CallScriptObjectFunction(int functionRef)
  355. {
  356. if (functionRef == LUA_REFNIL)
  357. return;
  358. int top = lua_gettop(luaState_);
  359. // Push function.
  360. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
  361. // Push script object.
  362. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  363. // Call script object function.
  364. if (lua_pcall(luaState_, 1, 0, 0) != 0)
  365. {
  366. const char* message = lua_tostring(luaState_, -1);
  367. LOGERROR("Execute Lua function failed: " + String(message));
  368. lua_settop(luaState_, top);
  369. return;
  370. }
  371. }
  372. void LuaScriptInstance::CallScriptObjectFunction(int functionRef, float timeStep)
  373. {
  374. if (functionRef == LUA_REFNIL)
  375. return;
  376. int top = lua_gettop(luaState_);
  377. // Push function.
  378. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
  379. // Push script object.
  380. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  381. // Push time step.
  382. tolua_pushnumber(luaState_, timeStep);
  383. // Call script object function.
  384. if (lua_pcall(luaState_, 2, 0, 0) != 0)
  385. {
  386. const char* message = lua_tostring(luaState_, -1);
  387. LOGERROR("Execute Lua function failed: " + String(message));
  388. lua_settop(luaState_, top);
  389. return;
  390. }
  391. }
  392. void LuaScriptInstance::CallScriptObjectFunction(int functionRef, Deserializer& deserializer)
  393. {
  394. if (functionRef == LUA_REFNIL)
  395. return;
  396. int top = lua_gettop(luaState_);
  397. // Push function.
  398. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
  399. // Push script object.
  400. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  401. // Push Deserializer.
  402. tolua_pushusertype(luaState_, (void*)&deserializer, "Deserializer");
  403. // Call script object function.
  404. if (lua_pcall(luaState_, 2, 0, 0) != 0)
  405. {
  406. const char* message = lua_tostring(luaState_, -1);
  407. LOGERROR("Execute Lua function failed: " + String(message));
  408. lua_settop(luaState_, top);
  409. }
  410. }
  411. void LuaScriptInstance::CallScriptObjectFunction(int functionRef, Serializer& serializer) const
  412. {
  413. if (functionRef == LUA_REFNIL)
  414. return;
  415. int top = lua_gettop(luaState_);
  416. // Push function.
  417. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
  418. // Push script object.
  419. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  420. // Push Deserializer.
  421. tolua_pushusertype(luaState_, (void*)&serializer, "Serializer");
  422. // Call script object function.
  423. if (lua_pcall(luaState_, 2, 0, 0) != 0)
  424. {
  425. const char* message = lua_tostring(luaState_, -1);
  426. LOGERROR("Execute Lua function failed: " + String(message));
  427. lua_settop(luaState_, top);
  428. }
  429. }
  430. void LuaScriptInstance::CallScriptObjectFunction(int functionRef, StringHash eventType, VariantMap& eventData)
  431. {
  432. if (functionRef == LUA_REFNIL)
  433. return;
  434. int top = lua_gettop(luaState_);
  435. // Push function.
  436. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
  437. // Push script object.
  438. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  439. // Push event type.
  440. tolua_pushusertype(luaState_, (void*)&eventType, "StringHash");
  441. // Push event data.
  442. tolua_pushusertype(luaState_, (void*)&eventData, "VariantMap");
  443. // Call script object function.
  444. if (lua_pcall(luaState_, 3, 0, 0) != 0)
  445. {
  446. const char* message = lua_tostring(luaState_, -1);
  447. LOGERROR("Execute Lua function failed: " + String(message));
  448. lua_settop(luaState_, top);
  449. }
  450. }
  451. bool LuaScriptInstance::CallScriptObjectFunction(int functionRef, const VariantVector& parameters)
  452. {
  453. if (functionRef == LUA_REFNIL)
  454. return false;
  455. int top = lua_gettop(luaState_);
  456. // Push function.
  457. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, functionRef);
  458. // Push script object.
  459. lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_);
  460. // Push parameters.
  461. if (!tolua_pushurho3dvariantvector(luaState_, parameters))
  462. {
  463. lua_settop(luaState_, top);
  464. return false;
  465. }
  466. // Call script object function.
  467. if (lua_pcall(luaState_, 1 + parameters.Size(), 0, 0) != 0)
  468. {
  469. const char* message = lua_tostring(luaState_, -1);
  470. LOGERROR("Execute Lua function failed: " + String(message));
  471. lua_settop(luaState_, top);
  472. return false;
  473. }
  474. return true;
  475. }
  476. }