lua_stack.h 9.9 KB

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