lua_stack.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #pragma once
  6. #include "lua.hpp"
  7. #include "types.h"
  8. #include "lua_system.h"
  9. #include "vector3.h"
  10. #include "vector2.h"
  11. #include "quaternion.h"
  12. #include "matrix4x4.h"
  13. #include "string_utils.h"
  14. #include "color4.h"
  15. #if defined(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
  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_float(float value)
  124. {
  125. lua_pushnumber(_L, value);
  126. }
  127. void push_string(const char* s)
  128. {
  129. lua_pushstring(_L, s);
  130. }
  131. void push_fstring(const char* fmt, ...)
  132. {
  133. va_list vl;
  134. va_start(vl, fmt);
  135. lua_pushvfstring(_L, fmt, vl);
  136. va_end(vl);
  137. }
  138. void push_literal(const char* s, size_t len)
  139. {
  140. lua_pushlstring(_L, s, len);
  141. }
  142. bool get_bool(int32_t index)
  143. {
  144. return CHECKBOOLEAN(_L, index) == 1;
  145. }
  146. int32_t get_int(int32_t index)
  147. {
  148. return CHECKINTEGER(_L, index);
  149. }
  150. float get_float(int32_t index)
  151. {
  152. return (float) CHECKNUMBER(_L, index);
  153. }
  154. const char* get_string(int32_t index)
  155. {
  156. return CHECKSTRING(_L, index);
  157. }
  158. /// Pushes an empty table onto the stack.
  159. /// When you want to set keys on the table, you have to use LuaStack::push_key_begin()
  160. /// and LuaStack::push_key_end() as in the following example:
  161. ///
  162. /// LuaStack stack(L)
  163. /// stack.push_table()
  164. /// stack.push_key_begin("foo"); stack.push_foo(); stack.push_key_end()
  165. /// stack.push_key_begin("bar"); stack.push_bar(); stack.push_key_end()
  166. /// return 1;
  167. void push_table()
  168. {
  169. lua_newtable(_L);
  170. }
  171. /// See Stack::push_table()
  172. void push_key_begin(const char* key)
  173. {
  174. lua_pushstring(_L, key);
  175. }
  176. /// See Stack::push_table()
  177. void push_key_begin(int32_t i)
  178. {
  179. lua_pushnumber(_L, i);
  180. }
  181. /// See Stack::push_table()
  182. void push_key_end()
  183. {
  184. lua_settable(_L, -3);
  185. }
  186. int next(int32_t i)
  187. {
  188. return lua_next(_L, i);
  189. }
  190. void push_resource_package(ResourcePackage* package)
  191. {
  192. ResourcePackage** p = (ResourcePackage**) lua_newuserdata(_L, sizeof(ResourcePackage*));
  193. *p = package;
  194. luaL_getmetatable(_L, "ResourcePackage");
  195. lua_setmetatable(_L, -2);
  196. }
  197. ResourcePackage* get_resource_package(int32_t index)
  198. {
  199. ResourcePackage* pkg = *(ResourcePackage**) CHECKUDATA(_L, index, "ResourcePackage");
  200. return pkg;
  201. }
  202. void push_world(World* world)
  203. {
  204. World** w = (World**) lua_newuserdata(_L, sizeof(World*));
  205. *w = world;
  206. luaL_getmetatable(_L, "World");
  207. lua_setmetatable(_L, -2);
  208. };
  209. World* get_world(int32_t index)
  210. {
  211. World* w = *(World**) CHECKUDATA(_L, index, "World");
  212. return w;
  213. };
  214. void push_physics_world(PhysicsWorld* world)
  215. {
  216. PhysicsWorld** w = (PhysicsWorld**) lua_newuserdata(_L, sizeof(PhysicsWorld*));
  217. luaL_getmetatable(_L, "PhysicsWorld");
  218. lua_setmetatable(_L, -2);
  219. *w = world;
  220. }
  221. PhysicsWorld* get_physics_world(int32_t index)
  222. {
  223. PhysicsWorld* w = *(PhysicsWorld**) CHECKUDATA(_L, index, "PhysicsWorld");
  224. return w;
  225. }
  226. void push_sound_world(SoundWorld* world)
  227. {
  228. SoundWorld** w = (SoundWorld**) lua_newuserdata(_L, sizeof(SoundWorld*));
  229. *w = world;
  230. luaL_getmetatable(_L, "SoundWorld");
  231. lua_setmetatable(_L, -2);
  232. }
  233. SoundWorld* get_sound_world(int32_t index)
  234. {
  235. SoundWorld* w = *(SoundWorld**) CHECKUDATA(_L, index, "SoundWorld");
  236. return w;
  237. }
  238. void push_unit(Unit* unit)
  239. {
  240. lua_pushlightuserdata(_L, unit);
  241. }
  242. Unit* get_unit(int32_t index)
  243. {
  244. return (Unit*) CHECKLIGHTDATA(_L, index, always_true, "Unit");
  245. }
  246. void push_camera(Camera* camera)
  247. {
  248. lua_pushlightuserdata(_L, camera);
  249. }
  250. Camera* get_camera(int32_t index)
  251. {
  252. return (Camera*) CHECKLIGHTDATA(_L, index, always_true, "Camera");
  253. }
  254. void push_mesh(Mesh* mesh)
  255. {
  256. lua_pushlightuserdata(_L, mesh);
  257. }
  258. Mesh* get_mesh(int32_t index)
  259. {
  260. return (Mesh*) CHECKLIGHTDATA(_L, index, always_true, "Mesh");
  261. }
  262. void push_sprite(Sprite* sprite)
  263. {
  264. lua_pushlightuserdata(_L, sprite);
  265. }
  266. Sprite* get_sprite(int32_t index)
  267. {
  268. return (Sprite*) CHECKLIGHTDATA(_L, index, always_true, "Sprite");
  269. }
  270. void push_material(Material* material)
  271. {
  272. lua_pushlightuserdata(_L, material);
  273. }
  274. Material* get_material(int32_t index)
  275. {
  276. return (Material*) CHECKLIGHTDATA(_L, index, always_true, "Material");
  277. }
  278. void push_actor(Actor* actor)
  279. {
  280. lua_pushlightuserdata(_L, actor);
  281. }
  282. Actor* get_actor(int32_t index)
  283. {
  284. return (Actor*) CHECKLIGHTDATA(_L, index, always_true, "Actor");
  285. }
  286. void push_controller(Controller* controller)
  287. {
  288. lua_pushlightuserdata(_L, controller);
  289. }
  290. Controller* get_controller(int32_t index)
  291. {
  292. return (Controller*) CHECKLIGHTDATA(_L, index, always_true, "Controller");
  293. }
  294. void push_raycast(Raycast* raycast)
  295. {
  296. lua_pushlightuserdata(_L, raycast);
  297. }
  298. Raycast* get_raycast(int32_t index)
  299. {
  300. return (Raycast*) CHECKLIGHTDATA(_L, index, always_true, "Raycast");
  301. }
  302. void push_sound_instance_id(const SoundInstanceId id)
  303. {
  304. uintptr_t enc = id.encode();
  305. lua_pushlightuserdata(_L, (void*)enc);
  306. }
  307. SoundInstanceId get_sound_instance_id(int32_t index)
  308. {
  309. uint32_t enc = (uintptr_t) CHECKLIGHTDATA(_L, index, always_true, "SoundInstanceId");
  310. SoundInstanceId id;
  311. id.decode(enc);
  312. return id;
  313. }
  314. void push_gui(Gui* gui)
  315. {
  316. lua_pushlightuserdata(_L, gui);
  317. }
  318. Gui* get_gui(int32_t index)
  319. {
  320. return (Gui*) CHECKLIGHTDATA(_L, index, always_true, "Gui");
  321. }
  322. void push_debug_line(DebugLine* line)
  323. {
  324. DebugLine** l = (DebugLine**) lua_newuserdata(_L, sizeof(DebugLine*));
  325. *l = line;
  326. luaL_getmetatable(_L, "DebugLine");
  327. lua_setmetatable(_L, -2);
  328. }
  329. DebugLine* get_debug_line(int32_t index)
  330. {
  331. DebugLine* l = *(DebugLine**) CHECKUDATA(_L, index, "DebugLine");
  332. return l;
  333. }
  334. Vector2 get_vector2(int32_t index)
  335. {
  336. void* v = CHECKLIGHTDATA(_L, index, lua_globals::is_vector3, "Vector2");
  337. Vector3& vv = *(Vector3*)v;
  338. return Vector2(vv.x, vv.y);
  339. }
  340. Vector3& get_vector3(int32_t index)
  341. {
  342. void* v = CHECKLIGHTDATA(_L, index, lua_globals::is_vector3, "Vector3");
  343. return *(Vector3*)v;
  344. }
  345. Matrix4x4& get_matrix4x4(int32_t index)
  346. {
  347. void* m = CHECKLIGHTDATA(_L, index, lua_globals::is_matrix4x4, "Matrix4x4");
  348. return *(Matrix4x4*)m;
  349. }
  350. Quaternion& get_quaternion(int32_t index)
  351. {
  352. void* q = CHECKLIGHTDATA(_L, index, lua_globals::is_quaternion, "Quaternion");
  353. return *(Quaternion*)q;
  354. }
  355. Color4 get_color4(int32_t index)
  356. {
  357. // Color4 represented as Quaternion
  358. void* c = CHECKLIGHTDATA(_L, index, lua_globals::is_quaternion, "Color4");
  359. Quaternion& q = *(Quaternion*)c;
  360. return Color4(q.x, q.y, q.z, q.w);
  361. }
  362. void push_vector2(const Vector2& v)
  363. {
  364. push_vector3(Vector3(v.x, v.y, 0.0f));
  365. }
  366. void push_vector3(const Vector3& v)
  367. {
  368. lua_pushlightuserdata(_L, lua_globals::next_vector3(v));
  369. luaL_getmetatable(_L, "Lightuserdata_mt");
  370. lua_setmetatable(_L, -2);
  371. }
  372. void push_matrix4x4(const Matrix4x4& m)
  373. {
  374. lua_pushlightuserdata(_L, lua_globals::next_matrix4x4(m));
  375. luaL_getmetatable(_L, "Lightuserdata_mt");
  376. lua_setmetatable(_L, -2);
  377. }
  378. void push_quaternion(const Quaternion& q)
  379. {
  380. lua_pushlightuserdata(_L, lua_globals::next_quaternion(q));
  381. luaL_getmetatable(_L, "Lightuserdata_mt");
  382. lua_setmetatable(_L, -2);
  383. }
  384. void push_vector2box(const Vector2& v)
  385. {
  386. Vector2* vec = (Vector2*) lua_newuserdata(_L, sizeof(Vector2));
  387. luaL_getmetatable(_L, "Vector2Box");
  388. lua_setmetatable(_L, -2);
  389. *vec = v;
  390. }
  391. Vector2& get_vector2box(uint32_t index)
  392. {
  393. Vector2* v = (Vector2*) CHECKUDATA(_L, index, "Vector2Box");
  394. return *v;
  395. }
  396. void push_vector3box(const Vector3& v)
  397. {
  398. Vector3* vec = (Vector3*) lua_newuserdata(_L, sizeof(Vector3));
  399. luaL_getmetatable(_L, "Vector3Box");
  400. lua_setmetatable(_L, -2);
  401. *vec = v;
  402. }
  403. Vector3& get_vector3box(uint32_t index)
  404. {
  405. Vector3* v = (Vector3*) CHECKUDATA(_L, index, "Vector3Box");
  406. return *v;
  407. }
  408. void push_quaternionbox(const Quaternion& q)
  409. {
  410. Quaternion* quat = (Quaternion*) lua_newuserdata(_L, sizeof(Quaternion));
  411. luaL_getmetatable(_L, "QuaternionBox");
  412. lua_setmetatable(_L, -2);
  413. *quat = q;
  414. }
  415. Quaternion& get_quaternionbox(uint32_t index)
  416. {
  417. Quaternion* q = (Quaternion*) CHECKUDATA(_L, index, "QuaternionBox");
  418. return *q;
  419. }
  420. void push_matrix4x4box(const Matrix4x4& m)
  421. {
  422. Matrix4x4* mat = (Matrix4x4*) lua_newuserdata(_L, sizeof(Matrix4x4));
  423. luaL_getmetatable(_L, "Matrix4x4Box");
  424. lua_setmetatable(_L, -2);
  425. *mat = m;
  426. }
  427. Matrix4x4& get_matrix4x4box(uint32_t index)
  428. {
  429. Matrix4x4* m = (Matrix4x4*) CHECKUDATA(_L, index, "Matrix4x4Box");
  430. return *m;
  431. }
  432. private:
  433. lua_State* _L;
  434. };
  435. } // namespace crown