lua_stack.inl 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /*
  2. * Copyright (c) 2012-2024 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #pragma once
  6. #include "core/error/error.inl"
  7. #include "lua/lua_stack.h"
  8. extern "C"
  9. {
  10. #include <lua.h>
  11. #include <lauxlib.h>
  12. #include <lualib.h>
  13. }
  14. #if CROWN_DEBUG
  15. #define LUA_ASSERT(condition, stack, msg, ...) \
  16. do \
  17. { \
  18. if (CE_UNLIKELY(!(condition))) \
  19. { \
  20. stack.push_fstring("Assertion failed: %s\n " msg "\n" \
  21. , # condition \
  22. , ## __VA_ARGS__ \
  23. ); \
  24. lua_error(stack.L); \
  25. CE_UNREACHABLE(); \
  26. } \
  27. } \
  28. while (0)
  29. #else
  30. #define LUA_ASSERT(...) CE_NOOP()
  31. #endif // if CROWN_DEBUG
  32. namespace crown
  33. {
  34. inline LuaStack::LuaStack(lua_State *L)
  35. : L(L)
  36. {
  37. }
  38. inline int LuaStack::num_args()
  39. {
  40. return lua_gettop(L);
  41. }
  42. inline void LuaStack::remove(int i)
  43. {
  44. lua_remove(L, i);
  45. }
  46. inline void LuaStack::pop(int n)
  47. {
  48. lua_pop(L, n);
  49. }
  50. inline bool LuaStack::is_nil(int i)
  51. {
  52. return lua_isnil(L, i) == 1;
  53. }
  54. inline bool LuaStack::is_bool(int i)
  55. {
  56. return lua_isboolean(L, i) == 1;
  57. }
  58. inline bool LuaStack::is_number(int i)
  59. {
  60. return lua_isnumber(L, i) == 1;
  61. }
  62. inline bool LuaStack::is_string(int i)
  63. {
  64. return lua_isstring(L, i) == 1;
  65. }
  66. inline bool LuaStack::is_pointer(int i)
  67. {
  68. return lua_islightuserdata(L, i) == 1
  69. && ((uintptr_t)lua_touserdata(L, i) & LIGHTDATA_TYPE_MASK) == LIGHTDATA_POINTER_MARKER;
  70. }
  71. inline bool LuaStack::is_function(int i)
  72. {
  73. return lua_isfunction(L, i) == 1;
  74. }
  75. inline bool LuaStack::is_table(int i)
  76. {
  77. return lua_istable(L, i) == 1;
  78. }
  79. inline int LuaStack::value_type(int i)
  80. {
  81. return lua_type(L, i);
  82. }
  83. inline bool LuaStack::get_bool(int i)
  84. {
  85. return lua_toboolean(L, i) == 1;
  86. }
  87. inline int LuaStack::get_int(int i)
  88. {
  89. #if CROWN_DEBUG
  90. return (int)luaL_checknumber(L, i);
  91. #else
  92. return (int)lua_tonumber(L, i);
  93. #endif
  94. }
  95. inline f32 LuaStack::get_float(int i)
  96. {
  97. #if CROWN_DEBUG
  98. return (f32)luaL_checknumber(L, i);
  99. #else
  100. return (f32)lua_tonumber(L, i);
  101. #endif
  102. }
  103. inline const char *LuaStack::get_string(int i)
  104. {
  105. #if CROWN_DEBUG
  106. return luaL_checkstring(L, i);
  107. #else
  108. return lua_tostring(L, i);
  109. #endif
  110. }
  111. inline void *LuaStack::get_pointer(int i)
  112. {
  113. #if CROWN_DEBUG
  114. if (CE_UNLIKELY(lua_isuserdata(L, i) == 0)) {
  115. luaL_typerror(L, i, "userdata");
  116. CE_UNREACHABLE();
  117. }
  118. #endif
  119. void *p = lua_touserdata(L, i);
  120. CE_ENSURE(p != NULL); // NULL iff object is not userdata
  121. return p;
  122. }
  123. inline u32 LuaStack::get_id(int i)
  124. {
  125. #if CROWN_DEBUG
  126. return (u32)luaL_checknumber(L, i);
  127. #else
  128. return (u32)lua_tonumber(L, i);
  129. #endif
  130. }
  131. inline StringId32 LuaStack::get_string_id_32(int i)
  132. {
  133. return StringId32(get_string(i));
  134. }
  135. inline StringId64 LuaStack::get_string_id_64(int i)
  136. {
  137. return StringId64(get_string(i));
  138. }
  139. inline StringId64 LuaStack::get_resource_name(int i)
  140. {
  141. return get_string_id_64(i);
  142. }
  143. inline Gui *LuaStack::get_gui(int i)
  144. {
  145. Gui *p = (Gui *)get_pointer(i);
  146. check_marker(i, p, DEBUG_GUI_MARKER, "Gui");
  147. return p;
  148. }
  149. inline DebugLine *LuaStack::get_debug_line(int i)
  150. {
  151. DebugLine *p = (DebugLine *)get_pointer(i);
  152. check_marker(i, p, DEBUG_LINE_MARKER, "DebugLine");
  153. return p;
  154. }
  155. inline ResourcePackage *LuaStack::get_resource_package(int i)
  156. {
  157. ResourcePackage *p = (ResourcePackage *)get_pointer(i);
  158. check_marker(i, p, RESOURCE_PACKAGE_MARKER, "ResourcePackage");
  159. return p;
  160. }
  161. inline World *LuaStack::get_world(int i)
  162. {
  163. World *p = (World *)get_pointer(i);
  164. check_marker(i, p, WORLD_MARKER, "World");
  165. return p;
  166. }
  167. inline SceneGraph *LuaStack::get_scene_graph(int i)
  168. {
  169. SceneGraph *p = (SceneGraph *)get_pointer(i);
  170. check_marker(i, p, SCENE_GRAPH_MARKER, "SceneGraph");
  171. return p;
  172. }
  173. inline Level *LuaStack::get_level(int i)
  174. {
  175. Level *p = (Level *)get_pointer(i);
  176. check_marker(i, p, LEVEL_MARKER, "Level");
  177. return p;
  178. }
  179. inline RenderWorld *LuaStack::get_render_world(int i)
  180. {
  181. RenderWorld *p = (RenderWorld *)get_pointer(i);
  182. check_marker(i, p, RENDER_WORLD_MARKER, "RenderWorld");
  183. return p;
  184. }
  185. inline PhysicsWorld *LuaStack::get_physics_world(int i)
  186. {
  187. PhysicsWorld *p = (PhysicsWorld *)get_pointer(i);
  188. check_marker(i, p, PHYSICS_WORLD_MARKER, "PhysicsWorld");
  189. return p;
  190. }
  191. inline SoundWorld *LuaStack::get_sound_world(int i)
  192. {
  193. SoundWorld *p = (SoundWorld *)get_pointer(i);
  194. check_marker(i, p, SOUND_WORLD_MARKER, "SoundWorld");
  195. return p;
  196. }
  197. inline ScriptWorld *LuaStack::get_script_world(int i)
  198. {
  199. ScriptWorld *p = (ScriptWorld *)get_pointer(i);
  200. check_marker(i, p, SCRIPT_WORLD_MARKER, "ScriptWorld");
  201. return p;
  202. }
  203. inline AnimationStateMachine *LuaStack::get_animation_state_machine(int i)
  204. {
  205. AnimationStateMachine *p = (AnimationStateMachine *)get_pointer(i);
  206. check_marker(i, p, ANIMATION_STATE_MACHINE_MARKER, "AnimationStateMachine");
  207. return p;
  208. }
  209. inline bool LuaStack::is_unit(int i)
  210. {
  211. uintptr_t enc = (uintptr_t)get_pointer(i);
  212. return (enc & LIGHTDATA_TYPE_MASK) == LIGHTDATA_UNIT_MARKER;
  213. }
  214. inline UnitId LuaStack::get_unit(int i)
  215. {
  216. uintptr_t enc = (uintptr_t)get_pointer(i);
  217. #if CROWN_DEBUG
  218. if ((enc & LIGHTDATA_TYPE_MASK) != LIGHTDATA_UNIT_MARKER) {
  219. luaL_typerror(L, i, "UnitId");
  220. CE_UNREACHABLE();
  221. }
  222. #endif
  223. UnitId unit;
  224. unit._idx = u32((enc & LIGHTDATA_UNIT_ID_MASK) >> LIGHTDATA_UNIT_ID_SHIFT);
  225. return unit;
  226. }
  227. inline CameraInstance LuaStack::get_camera_instance(int i)
  228. {
  229. CameraInstance inst = { get_id(i) };
  230. return inst;
  231. }
  232. inline TransformInstance LuaStack::get_transform_instance(int i)
  233. {
  234. TransformInstance inst = { get_id(i) };
  235. return inst;
  236. }
  237. inline MeshInstance LuaStack::get_mesh_instance(int i)
  238. {
  239. MeshInstance inst = { get_id(i) };
  240. return inst;
  241. }
  242. inline SpriteInstance LuaStack::get_sprite_instance(int i)
  243. {
  244. SpriteInstance inst = { get_id(i) };
  245. return inst;
  246. }
  247. inline LightInstance LuaStack::get_light_instance(int i)
  248. {
  249. LightInstance inst = { get_id(i) };
  250. return inst;
  251. }
  252. inline StateMachineInstance LuaStack::get_state_machine_instance(int i)
  253. {
  254. StateMachineInstance inst = { get_id(i) };
  255. return inst;
  256. }
  257. inline Material *LuaStack::get_material(int i)
  258. {
  259. return (Material *)get_pointer(i);
  260. }
  261. inline ActorInstance LuaStack::get_actor_instance(int i)
  262. {
  263. ActorInstance inst = { get_id(i) };
  264. return inst;
  265. }
  266. inline SoundInstanceId LuaStack::get_sound_instance_id(int i)
  267. {
  268. return get_id(i);
  269. }
  270. inline ScriptInstance LuaStack::get_script_instance(int i)
  271. {
  272. ScriptInstance inst = { get_id(i) };
  273. return inst;
  274. }
  275. inline Vector2 LuaStack::get_vector2(int i)
  276. {
  277. Vector3 v = get_vector3(i);
  278. Vector2 a;
  279. a.x = v.x;
  280. a.y = v.y;
  281. return a;
  282. }
  283. inline Vector3 &LuaStack::get_vector3(int i)
  284. {
  285. #if CROWN_DEBUG
  286. return *check_temporary(i, (Vector3 *)get_pointer(i));
  287. #else
  288. return *(Vector3 *)get_pointer(i);
  289. #endif
  290. }
  291. inline Vector4 LuaStack::get_vector4(int i)
  292. {
  293. Quaternion q = get_quaternion(i);
  294. Vector4 a;
  295. a.x = q.x;
  296. a.y = q.y;
  297. a.z = q.z;
  298. a.w = q.w;
  299. return a;
  300. }
  301. inline Quaternion &LuaStack::get_quaternion(int i)
  302. {
  303. #if CROWN_DEBUG
  304. return *check_temporary(i, (Quaternion *)get_pointer(i));
  305. #else
  306. return *(Quaternion *)get_pointer(i);
  307. #endif
  308. }
  309. inline Matrix4x4 &LuaStack::get_matrix4x4(int i)
  310. {
  311. #if CROWN_DEBUG
  312. return *check_temporary(i, (Matrix4x4 *)get_pointer(i));
  313. #else
  314. return *(Matrix4x4 *)get_pointer(i);
  315. #endif
  316. }
  317. inline Color4 LuaStack::get_color4(int i)
  318. {
  319. Quaternion q = get_quaternion(i);
  320. Color4 c;
  321. c.x = q.x;
  322. c.y = q.y;
  323. c.z = q.z;
  324. c.w = q.w;
  325. return c;
  326. }
  327. inline Vector2 &LuaStack::get_vector2box(int i)
  328. {
  329. Vector2 *v = (Vector2 *)luaL_checkudata(L, i, "Vector2Box");
  330. return *v;
  331. }
  332. inline Vector3 &LuaStack::get_vector3box(int i)
  333. {
  334. Vector3 *v = (Vector3 *)luaL_checkudata(L, i, "Vector3Box");
  335. return *v;
  336. }
  337. inline Quaternion &LuaStack::get_quaternionbox(int i)
  338. {
  339. Quaternion *q = (Quaternion *)luaL_checkudata(L, i, "QuaternionBox");
  340. return *q;
  341. }
  342. inline Matrix4x4 &LuaStack::get_matrix4x4box(int i)
  343. {
  344. Matrix4x4 *m = (Matrix4x4 *)luaL_checkudata(L, i, "Matrix4x4Box");
  345. return *m;
  346. }
  347. inline void LuaStack::push_nil()
  348. {
  349. lua_pushnil(L);
  350. }
  351. inline void LuaStack::push_bool(bool value)
  352. {
  353. lua_pushboolean(L, value);
  354. }
  355. inline void LuaStack::push_int(int value)
  356. {
  357. lua_pushnumber(L, value);
  358. }
  359. inline void LuaStack::push_float(f32 value)
  360. {
  361. lua_pushnumber(L, value);
  362. }
  363. inline void LuaStack::push_string(const char *s)
  364. {
  365. lua_pushstring(L, s);
  366. }
  367. inline void LuaStack::push_fstring(const char *fmt, ...)
  368. {
  369. va_list vl;
  370. va_start(vl, fmt);
  371. lua_pushvfstring(L, fmt, vl);
  372. va_end(vl);
  373. }
  374. inline void LuaStack::push_lstring(const char *s, u32 len)
  375. {
  376. lua_pushlstring(L, s, len);
  377. }
  378. inline void LuaStack::push_string_id(StringId32 value)
  379. {
  380. lua_pushnumber(L, value._id);
  381. }
  382. inline void LuaStack::push_pointer(void *p)
  383. {
  384. CE_ENSURE(NULL != p);
  385. lua_pushlightuserdata(L, p);
  386. }
  387. inline void LuaStack::push_function(lua_CFunction f)
  388. {
  389. lua_pushcfunction(L, f);
  390. }
  391. inline void LuaStack::push_id(u32 value)
  392. {
  393. lua_pushnumber(L, value);
  394. }
  395. inline void LuaStack::push_table(int narr, int nrec)
  396. {
  397. lua_createtable(L, narr, nrec);
  398. }
  399. inline void LuaStack::push_key_begin(const char *key)
  400. {
  401. lua_pushstring(L, key);
  402. }
  403. inline void LuaStack::push_key_begin(int i)
  404. {
  405. lua_pushnumber(L, i);
  406. }
  407. inline void LuaStack::push_key_end()
  408. {
  409. lua_settable(L, -3);
  410. }
  411. inline int LuaStack::next(int i)
  412. {
  413. return lua_next(L, i);
  414. }
  415. inline void LuaStack::push_gui(Gui *dg)
  416. {
  417. push_pointer(dg);
  418. }
  419. inline void LuaStack::push_debug_line(DebugLine *line)
  420. {
  421. push_pointer(line);
  422. }
  423. inline void LuaStack::push_resource_package(ResourcePackage *package)
  424. {
  425. push_pointer(package);
  426. }
  427. inline void LuaStack::push_world(World *world)
  428. {
  429. push_pointer(world);
  430. }
  431. inline void LuaStack::push_scene_graph(SceneGraph *sg)
  432. {
  433. push_pointer(sg);
  434. }
  435. inline void LuaStack::push_level(Level *level)
  436. {
  437. push_pointer(level);
  438. }
  439. inline void LuaStack::push_render_world(RenderWorld *world)
  440. {
  441. push_pointer(world);
  442. }
  443. inline void LuaStack::push_physics_world(PhysicsWorld *world)
  444. {
  445. push_pointer(world);
  446. }
  447. inline void LuaStack::push_sound_world(SoundWorld *world)
  448. {
  449. push_pointer(world);
  450. }
  451. inline void LuaStack::push_script_world(ScriptWorld *world)
  452. {
  453. push_pointer(world);
  454. }
  455. inline void LuaStack::push_animation_state_machine(AnimationStateMachine *sm)
  456. {
  457. push_pointer(sm);
  458. }
  459. inline void LuaStack::push_unit(UnitId unit)
  460. {
  461. uintptr_t enc = (uintptr_t(unit._idx) << LIGHTDATA_UNIT_ID_SHIFT) | LIGHTDATA_UNIT_MARKER;
  462. push_pointer((void *)enc);
  463. }
  464. inline void LuaStack::push_camera(CameraInstance i)
  465. {
  466. push_id(i.i);
  467. }
  468. inline void LuaStack::push_transform(TransformInstance i)
  469. {
  470. push_id(i.i);
  471. }
  472. inline void LuaStack::push_mesh_instance(MeshInstance i)
  473. {
  474. push_id(i.i);
  475. }
  476. inline void LuaStack::push_sprite_instance(SpriteInstance i)
  477. {
  478. push_id(i.i);
  479. }
  480. inline void LuaStack::push_light_instance(LightInstance i)
  481. {
  482. push_id(i.i);
  483. }
  484. inline void LuaStack::push_state_machine_instance(StateMachineInstance i)
  485. {
  486. push_id(i.i);
  487. }
  488. inline void LuaStack::push_material(Material *material)
  489. {
  490. push_pointer(material);
  491. }
  492. inline void LuaStack::push_actor(ActorInstance i)
  493. {
  494. push_id(i.i);
  495. }
  496. inline void LuaStack::push_sound_instance_id(SoundInstanceId id)
  497. {
  498. push_id(id);
  499. }
  500. inline void LuaStack::push_script_instance(ScriptInstance i)
  501. {
  502. push_id(i.i);
  503. }
  504. inline void LuaStack::push_vector2(const Vector2 &v)
  505. {
  506. Vector3 a;
  507. a.x = v.x;
  508. a.y = v.y;
  509. a.z = 0.0f;
  510. push_vector3(a);
  511. }
  512. inline void LuaStack::push_color4(const Color4 &c)
  513. {
  514. Quaternion q;
  515. q.x = c.x;
  516. q.y = c.y;
  517. q.z = c.z;
  518. q.w = c.w;
  519. push_quaternion(q);
  520. }
  521. inline void LuaStack::push_vector2box(const Vector2 &v)
  522. {
  523. Vector2 *vec = (Vector2 *)lua_newuserdata(L, sizeof(Vector2));
  524. luaL_getmetatable(L, "Vector2Box");
  525. lua_setmetatable(L, -2);
  526. *vec = v;
  527. }
  528. inline void LuaStack::push_vector3box(const Vector3 &v)
  529. {
  530. Vector3 *vec = (Vector3 *)lua_newuserdata(L, sizeof(Vector3));
  531. luaL_getmetatable(L, "Vector3Box");
  532. lua_setmetatable(L, -2);
  533. *vec = v;
  534. }
  535. inline void LuaStack::push_quaternionbox(const Quaternion &q)
  536. {
  537. Quaternion *quat = (Quaternion *)lua_newuserdata(L, sizeof(Quaternion));
  538. luaL_getmetatable(L, "QuaternionBox");
  539. lua_setmetatable(L, -2);
  540. *quat = q;
  541. }
  542. inline void LuaStack::push_matrix4x4box(const Matrix4x4 &m)
  543. {
  544. Matrix4x4 *mat = (Matrix4x4 *)lua_newuserdata(L, sizeof(Matrix4x4));
  545. luaL_getmetatable(L, "Matrix4x4Box");
  546. lua_setmetatable(L, -2);
  547. *mat = m;
  548. }
  549. inline void LuaStack::push_value(int i)
  550. {
  551. lua_pushvalue(L, i);
  552. }
  553. inline void LuaStack::call(int nresults)
  554. {
  555. lua_pcall(L, 2, nresults, 0);
  556. }
  557. #if CROWN_DEBUG
  558. inline void LuaStack::check_marker(int i, const void *p, u32 type_marker, const char *type_name)
  559. {
  560. if (CE_UNLIKELY(!is_pointer(i) || *(u32 *)p != type_marker)) {
  561. luaL_typerror(L, i, type_name);
  562. CE_UNREACHABLE();
  563. }
  564. }
  565. #else
  566. inline void LuaStack::check_marker(int /*i*/, const void * /*p*/, u32 /*type_marker*/, const char * /*type_name*/)
  567. {
  568. }
  569. #endif
  570. } // namespace crown