2
0

lua_stack.h 9.6 KB

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