lua_stack.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #pragma once
  6. #include "types.h"
  7. #include "lua_system.h"
  8. #include "vector3.h"
  9. #include "vector2.h"
  10. #include "quaternion.h"
  11. #include "matrix4x4.h"
  12. #include "string_utils.h"
  13. #include "color4.h"
  14. #include "lua.hpp"
  15. #if CROWN_DEBUG
  16. static void* checkudata(lua_State* L, int index, const char* expected)
  17. {
  18. luaL_checktype(L, index, LUA_TUSERDATA);
  19. return luaL_checkudata(L, index, expected);
  20. }
  21. typedef bool (*checkfn)(int);
  22. static void* checklightdata(lua_State* L, int index, checkfn cf, const char* expected)
  23. {
  24. luaL_checktype(L, index, LUA_TLIGHTUSERDATA);
  25. if (!cf(index)) luaL_typerror(L, index, expected);
  26. return lua_touserdata(L, index);
  27. }
  28. static bool always_true(int index)
  29. {
  30. return index == index;
  31. }
  32. #define CHECKUDATA(stack, index, expected) checkudata(stack, index, expected)
  33. #define CHECKLIGHTDATA(stack, index, cf, expected) checklightdata(stack, index, cf, expected)
  34. #define CHECKBOOLEAN(stack, index) lua_toboolean(stack, index)
  35. #define CHECKINTEGER(stack, index) luaL_checkinteger(stack, index)
  36. #define CHECKNUMBER(stack, index) luaL_checknumber(stack, index)
  37. #define CHECKSTRING(stack, index) luaL_checkstring(stack, index)
  38. #else
  39. #define CHECKUDATA(stack, index, expected) lua_touserdata(stack, index)
  40. #define CHECKLIGHTDATA(stack, index, cf, expected) lua_touserdata(stack, index)
  41. #define CHECKBOOLEAN(stack, index) lua_toboolean(stack, index)
  42. #define CHECKINTEGER(stack, index) lua_tointeger(stack, index)
  43. #define CHECKNUMBER(stack, index) lua_tonumber(stack, index)
  44. #define CHECKSTRING(stack, index) lua_tostring(stack, index)
  45. #endif // CROWN_DEBUG
  46. namespace crown
  47. {
  48. class PhysicsWorld;
  49. class SoundWorld;
  50. class World;
  51. struct Actor;
  52. struct Camera;
  53. struct Controller;
  54. struct Gui;
  55. struct Mesh;
  56. struct ResourcePackage;
  57. struct Sprite;
  58. struct Unit;
  59. struct DebugLine;
  60. struct Raycast;
  61. struct Material;
  62. typedef Id SoundInstanceId;
  63. typedef Id GuiId;
  64. typedef int (*MetamethodFunction)(lua_State*);
  65. struct LuaStack
  66. {
  67. LuaStack(lua_State* L)
  68. : L(L)
  69. {
  70. }
  71. lua_State* state()
  72. {
  73. return L;
  74. }
  75. /// Returns the number of elements in the stack.
  76. /// When called inside a function, it can be used to count
  77. /// the number of arguments passed to the function itself.
  78. int32_t num_args()
  79. {
  80. return lua_gettop(L);
  81. }
  82. /// Removes the element at the given valid index, shifting down the elements
  83. /// above this index to fill the gap. Cannot be called with a pseudo-index,
  84. /// because a pseudo-index is not an actual stack position.
  85. void remove(int32_t index)
  86. {
  87. lua_remove(L, index);
  88. }
  89. /// Pops @a n elements from the stack.
  90. void pop(int32_t n)
  91. {
  92. lua_pop(L, n);
  93. }
  94. bool is_nil(int32_t index)
  95. {
  96. return lua_isnil(L, index) == 1;
  97. }
  98. bool is_number(int32_t index)
  99. {
  100. return lua_isnumber(L, index) == 1;
  101. }
  102. /// Wraps lua_type.
  103. int value_type(uint32_t index)
  104. {
  105. return lua_type(L, index);
  106. }
  107. void push_nil()
  108. {
  109. lua_pushnil(L);
  110. }
  111. void push_bool(bool value)
  112. {
  113. lua_pushboolean(L, value);
  114. }
  115. void push_int32(int32_t value)
  116. {
  117. lua_pushinteger(L, value);
  118. }
  119. void push_uint32(uint32_t value)
  120. {
  121. lua_pushinteger(L, value);
  122. }
  123. void push_string_id(StringId32 value)
  124. {
  125. lua_pushinteger(L, value.id());
  126. }
  127. void push_float(float value)
  128. {
  129. lua_pushnumber(L, value);
  130. }
  131. void push_string(const char* s)
  132. {
  133. lua_pushstring(L, s);
  134. }
  135. void push_fstring(const char* fmt, ...)
  136. {
  137. va_list vl;
  138. va_start(vl, fmt);
  139. lua_pushvfstring(L, fmt, vl);
  140. va_end(vl);
  141. }
  142. void push_literal(const char* s, size_t len)
  143. {
  144. lua_pushlstring(L, s, len);
  145. }
  146. bool get_bool(int32_t index)
  147. {
  148. return CHECKBOOLEAN(L, index) == 1;
  149. }
  150. int32_t get_int(int32_t index)
  151. {
  152. return CHECKINTEGER(L, index);
  153. }
  154. StringId32 get_string_id(int32_t index)
  155. {
  156. return StringId32(uint32_t(CHECKINTEGER(L, index)));
  157. }
  158. float get_float(int32_t index)
  159. {
  160. return (float) CHECKNUMBER(L, index);
  161. }
  162. const char* get_string(int32_t index)
  163. {
  164. return CHECKSTRING(L, index);
  165. }
  166. /// Pushes an empty table onto the stack.
  167. /// When you want to set keys on the table, you have to use LuaStack::push_key_begin()
  168. /// and LuaStack::push_key_end() as in the following example:
  169. ///
  170. /// LuaStack stack(L)
  171. /// stack.push_table()
  172. /// stack.push_key_begin("foo"); stack.push_foo(); stack.push_key_end()
  173. /// stack.push_key_begin("bar"); stack.push_bar(); stack.push_key_end()
  174. /// return 1;
  175. void push_table()
  176. {
  177. lua_newtable(L);
  178. }
  179. /// See Stack::push_table()
  180. void push_key_begin(const char* key)
  181. {
  182. lua_pushstring(L, key);
  183. }
  184. /// See Stack::push_table()
  185. void push_key_begin(int32_t i)
  186. {
  187. lua_pushnumber(L, i);
  188. }
  189. /// See Stack::push_table()
  190. void push_key_end()
  191. {
  192. lua_settable(L, -3);
  193. }
  194. int next(int32_t i)
  195. {
  196. return lua_next(L, i);
  197. }
  198. StringId64 get_resource_id(int index)
  199. {
  200. return StringId64(CHECKSTRING(L, index));
  201. }
  202. void push_resource_package(ResourcePackage* package)
  203. {
  204. ResourcePackage** p = (ResourcePackage**) lua_newuserdata(L, sizeof(ResourcePackage*));
  205. *p = package;
  206. luaL_getmetatable(L, "ResourcePackage");
  207. lua_setmetatable(L, -2);
  208. }
  209. ResourcePackage* get_resource_package(int32_t index)
  210. {
  211. ResourcePackage* pkg = *(ResourcePackage**) CHECKUDATA(L, index, "ResourcePackage");
  212. return pkg;
  213. }
  214. void push_world(World* world)
  215. {
  216. World** w = (World**) lua_newuserdata(L, sizeof(World*));
  217. *w = world;
  218. luaL_getmetatable(L, "World");
  219. lua_setmetatable(L, -2);
  220. };
  221. World* get_world(int32_t index)
  222. {
  223. World* w = *(World**) CHECKUDATA(L, index, "World");
  224. return w;
  225. };
  226. void push_physics_world(PhysicsWorld* world)
  227. {
  228. PhysicsWorld** w = (PhysicsWorld**) lua_newuserdata(L, sizeof(PhysicsWorld*));
  229. luaL_getmetatable(L, "PhysicsWorld");
  230. lua_setmetatable(L, -2);
  231. *w = world;
  232. }
  233. PhysicsWorld* get_physics_world(int32_t index)
  234. {
  235. PhysicsWorld* w = *(PhysicsWorld**) CHECKUDATA(L, index, "PhysicsWorld");
  236. return w;
  237. }
  238. void push_sound_world(SoundWorld* world)
  239. {
  240. SoundWorld** w = (SoundWorld**) lua_newuserdata(L, sizeof(SoundWorld*));
  241. *w = world;
  242. luaL_getmetatable(L, "SoundWorld");
  243. lua_setmetatable(L, -2);
  244. }
  245. SoundWorld* get_sound_world(int32_t index)
  246. {
  247. SoundWorld* w = *(SoundWorld**) CHECKUDATA(L, index, "SoundWorld");
  248. return w;
  249. }
  250. void push_unit(Unit* unit)
  251. {
  252. lua_pushlightuserdata(L, unit);
  253. }
  254. Unit* get_unit(int32_t index)
  255. {
  256. return (Unit*) CHECKLIGHTDATA(L, index, always_true, "Unit");
  257. }
  258. void push_camera(Camera* camera)
  259. {
  260. lua_pushlightuserdata(L, camera);
  261. }
  262. Camera* get_camera(int32_t index)
  263. {
  264. return (Camera*) CHECKLIGHTDATA(L, index, always_true, "Camera");
  265. }
  266. void push_mesh(Mesh* mesh)
  267. {
  268. lua_pushlightuserdata(L, mesh);
  269. }
  270. Mesh* get_mesh(int32_t index)
  271. {
  272. return (Mesh*) CHECKLIGHTDATA(L, index, always_true, "Mesh");
  273. }
  274. void push_sprite(Sprite* sprite)
  275. {
  276. lua_pushlightuserdata(L, sprite);
  277. }
  278. Sprite* get_sprite(int32_t index)
  279. {
  280. return (Sprite*) CHECKLIGHTDATA(L, index, always_true, "Sprite");
  281. }
  282. void push_material(Material* material)
  283. {
  284. lua_pushlightuserdata(L, material);
  285. }
  286. Material* get_material(int32_t index)
  287. {
  288. return (Material*) CHECKLIGHTDATA(L, index, always_true, "Material");
  289. }
  290. void push_actor(Actor* actor)
  291. {
  292. lua_pushlightuserdata(L, actor);
  293. }
  294. Actor* get_actor(int32_t index)
  295. {
  296. return (Actor*) CHECKLIGHTDATA(L, index, always_true, "Actor");
  297. }
  298. void push_controller(Controller* controller)
  299. {
  300. lua_pushlightuserdata(L, controller);
  301. }
  302. Controller* get_controller(int32_t index)
  303. {
  304. return (Controller*) CHECKLIGHTDATA(L, index, always_true, "Controller");
  305. }
  306. void push_raycast(Raycast* raycast)
  307. {
  308. lua_pushlightuserdata(L, raycast);
  309. }
  310. Raycast* get_raycast(int32_t index)
  311. {
  312. return (Raycast*) CHECKLIGHTDATA(L, index, always_true, "Raycast");
  313. }
  314. void push_sound_instance_id(const SoundInstanceId id)
  315. {
  316. uintptr_t enc = id.encode();
  317. lua_pushlightuserdata(L, (void*)enc);
  318. }
  319. SoundInstanceId get_sound_instance_id(int32_t index)
  320. {
  321. uint32_t enc = (uintptr_t) CHECKLIGHTDATA(L, index, always_true, "SoundInstanceId");
  322. SoundInstanceId id;
  323. id.decode(enc);
  324. return id;
  325. }
  326. void push_gui(Gui* gui)
  327. {
  328. lua_pushlightuserdata(L, gui);
  329. }
  330. Gui* get_gui(int32_t index)
  331. {
  332. return (Gui*) CHECKLIGHTDATA(L, index, always_true, "Gui");
  333. }
  334. void push_debug_line(DebugLine* line)
  335. {
  336. DebugLine** l = (DebugLine**) lua_newuserdata(L, sizeof(DebugLine*));
  337. *l = line;
  338. luaL_getmetatable(L, "DebugLine");
  339. lua_setmetatable(L, -2);
  340. }
  341. DebugLine* get_debug_line(int32_t index)
  342. {
  343. DebugLine* l = *(DebugLine**) CHECKUDATA(L, index, "DebugLine");
  344. return l;
  345. }
  346. Vector2 get_vector2(int32_t index)
  347. {
  348. void* v = CHECKLIGHTDATA(L, index, lua_globals::is_vector3, "Vector2");
  349. Vector3& vv = *(Vector3*)v;
  350. return Vector2(vv.x, vv.y);
  351. }
  352. Vector3& get_vector3(int32_t index)
  353. {
  354. void* v = CHECKLIGHTDATA(L, index, lua_globals::is_vector3, "Vector3");
  355. return *(Vector3*)v;
  356. }
  357. Matrix4x4& get_matrix4x4(int32_t index)
  358. {
  359. void* m = CHECKLIGHTDATA(L, index, lua_globals::is_matrix4x4, "Matrix4x4");
  360. return *(Matrix4x4*)m;
  361. }
  362. Quaternion& get_quaternion(int32_t index)
  363. {
  364. void* q = CHECKLIGHTDATA(L, index, lua_globals::is_quaternion, "Quaternion");
  365. return *(Quaternion*)q;
  366. }
  367. Color4 get_color4(int32_t index)
  368. {
  369. // Color4 represented as Quaternion
  370. void* c = CHECKLIGHTDATA(L, index, lua_globals::is_quaternion, "Color4");
  371. Quaternion& q = *(Quaternion*)c;
  372. return Color4(q.x, q.y, q.z, q.w);
  373. }
  374. void push_vector2(const Vector2& v)
  375. {
  376. push_vector3(Vector3(v.x, v.y, 0.0f));
  377. }
  378. void push_vector3(const Vector3& v)
  379. {
  380. lua_pushlightuserdata(L, lua_globals::next_vector3(v));
  381. luaL_getmetatable(L, "Lightuserdata_mt");
  382. lua_setmetatable(L, -2);
  383. }
  384. void push_matrix4x4(const Matrix4x4& m)
  385. {
  386. lua_pushlightuserdata(L, lua_globals::next_matrix4x4(m));
  387. luaL_getmetatable(L, "Lightuserdata_mt");
  388. lua_setmetatable(L, -2);
  389. }
  390. void push_quaternion(const Quaternion& q)
  391. {
  392. lua_pushlightuserdata(L, lua_globals::next_quaternion(q));
  393. luaL_getmetatable(L, "Lightuserdata_mt");
  394. lua_setmetatable(L, -2);
  395. }
  396. void push_vector2box(const Vector2& v)
  397. {
  398. Vector2* vec = (Vector2*) lua_newuserdata(L, sizeof(Vector2));
  399. luaL_getmetatable(L, "Vector2Box");
  400. lua_setmetatable(L, -2);
  401. *vec = v;
  402. }
  403. Vector2& get_vector2box(uint32_t index)
  404. {
  405. Vector2* v = (Vector2*) CHECKUDATA(L, index, "Vector2Box");
  406. return *v;
  407. }
  408. void push_vector3box(const Vector3& v)
  409. {
  410. Vector3* vec = (Vector3*) lua_newuserdata(L, sizeof(Vector3));
  411. luaL_getmetatable(L, "Vector3Box");
  412. lua_setmetatable(L, -2);
  413. *vec = v;
  414. }
  415. Vector3& get_vector3box(uint32_t index)
  416. {
  417. Vector3* v = (Vector3*) CHECKUDATA(L, index, "Vector3Box");
  418. return *v;
  419. }
  420. void push_quaternionbox(const Quaternion& q)
  421. {
  422. Quaternion* quat = (Quaternion*) lua_newuserdata(L, sizeof(Quaternion));
  423. luaL_getmetatable(L, "QuaternionBox");
  424. lua_setmetatable(L, -2);
  425. *quat = q;
  426. }
  427. Quaternion& get_quaternionbox(uint32_t index)
  428. {
  429. Quaternion* q = (Quaternion*) CHECKUDATA(L, index, "QuaternionBox");
  430. return *q;
  431. }
  432. void push_matrix4x4box(const Matrix4x4& m)
  433. {
  434. Matrix4x4* mat = (Matrix4x4*) lua_newuserdata(L, sizeof(Matrix4x4));
  435. luaL_getmetatable(L, "Matrix4x4Box");
  436. lua_setmetatable(L, -2);
  437. *mat = m;
  438. }
  439. Matrix4x4& get_matrix4x4box(uint32_t index)
  440. {
  441. Matrix4x4* m = (Matrix4x4*) CHECKUDATA(L, index, "Matrix4x4Box");
  442. return *m;
  443. }
  444. private:
  445. lua_State* L;
  446. };
  447. } // namespace crown