| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- /*
- * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
- * License: https://github.com/dbartolini/crown/blob/master/LICENSE
- */
- #pragma once
- #include "config.h"
- #include "core/math/types.h"
- #include "core/strings/string_id.h"
- #include "core/types.h"
- #include "resource/types.h"
- #include "world/types.h"
- #include <lua.hpp>
- #ifndef LUA_OK
- #define LUA_OK 0
- #endif
- #if CROWN_DEBUG
- #define LUA_ASSERT(condition, stack, msg, ...) \
- do \
- { \
- if (CE_UNLIKELY(!(condition))) \
- { \
- stack.push_fstring("Assertion failed: %s\n " msg "\n" \
- , # condition \
- , ## __VA_ARGS__ \
- ); \
- lua_error(stack.L); \
- CE_UNREACHABLE(); \
- } \
- } \
- while (0)
- #else
- #define LUA_ASSERT(...) CE_NOOP()
- #endif // CROWN_DEBUG
- #define LIGHTDATA_TYPE_MASK uintptr_t(0x3)
- #define LIGHTDATA_TYPE_SHIFT uintptr_t(0)
- #define LIGHTDATA_POINTER_MARKER uintptr_t(0)
- #define LIGHTDATA_UNIT_MARKER uintptr_t(1)
- #define LIGHTDATA_UNIT_ID_MASK uintptr_t(0xfffffffc)
- #define LIGHTDATA_UNIT_ID_SHIFT uintptr_t(2)
- #define LUA_VECTOR3_MARKER_MASK uintptr_t(0x03)
- #define LUA_VECTOR3_MARKER_SHIFT uintptr_t(0)
- #define LUA_QUATERNION_MARKER_MASK uintptr_t(0x0f)
- #define LUA_QUATERNION_MARKER_SHIFT uintptr_t(0)
- #define LUA_MATRIX4X4_MARKER_MASK uintptr_t(0x3f)
- #define LUA_MATRIX4X4_MARKER_SHIFT uintptr_t(0)
- namespace crown
- {
- /// Wrapper to manipulate Lua stack.
- ///
- /// @ingroup Lua
- struct LuaStack
- {
- lua_State* L;
- LuaStack(lua_State* L)
- : L(L)
- {
- }
- /// Returns the number of elements in the stack.
- /// When called inside a function, it can be used to count
- /// the number of arguments passed to the function itself.
- int num_args()
- {
- return lua_gettop(L);
- }
- /// Removes the element at the given valid index, shifting down the elements
- /// above this index to fill the gap. Cannot be called with a pseudo-index,
- /// because a pseudo-index is not an actual stack position.
- void remove(int i)
- {
- lua_remove(L, i);
- }
- /// Pops @a n elements from the stack.
- void pop(int n)
- {
- lua_pop(L, n);
- }
- bool is_nil(int i)
- {
- return lua_isnil(L, i) == 1;
- }
- bool is_bool(int i)
- {
- return lua_isboolean(L, i) == 1;
- }
- bool is_number(int i)
- {
- return lua_isnumber(L, i) == 1;
- }
- bool is_string(int i)
- {
- return lua_isstring(L, i) == 1;
- }
- bool is_pointer(int i)
- {
- return lua_islightuserdata(L, i) == 1
- && ((uintptr_t)lua_touserdata(L, i) & LIGHTDATA_TYPE_MASK) == LIGHTDATA_POINTER_MARKER;
- }
- bool is_function(int i)
- {
- return lua_isfunction(L, i) == 1;
- }
- bool is_table(int i)
- {
- return lua_istable(L, i) == 1;
- }
- bool is_vector3(int i);
- bool is_quaternion(int i);
- bool is_matrix4x4(int i);
- /// Wraps lua_type.
- int value_type(int i)
- {
- return lua_type(L, i);
- }
- bool get_bool(int i)
- {
- return lua_toboolean(L, i) == 1;
- }
- int get_int(int i)
- {
- #if CROWN_DEBUG
- return (int)luaL_checknumber(L, i);
- #else
- return (int)lua_tonumber(L, i);
- #endif
- }
- f32 get_float(int i)
- {
- #if CROWN_DEBUG
- return (f32)luaL_checknumber(L, i);
- #else
- return (f32)lua_tonumber(L, i);
- #endif
- }
- const char* get_string(int i)
- {
- #if CROWN_DEBUG
- return luaL_checkstring(L, i);
- #else
- return lua_tostring(L, i);
- #endif
- }
- void* get_pointer(int i)
- {
- #if CROWN_DEBUG
- if (CE_UNLIKELY(lua_isuserdata(L, i) == 0))
- {
- luaL_typerror(L, i, "userdata");
- CE_UNREACHABLE();
- }
- #endif
- void* p = lua_touserdata(L, i);
- CE_ENSURE(p != NULL); // NULL iff object is not userdata
- return p;
- }
- u32 get_id(int i)
- {
- #if CROWN_DEBUG
- return (u32)luaL_checknumber(L, i);
- #else
- return (u32)lua_tonumber(L, i);
- #endif
- }
- StringId32 get_string_id_32(int i)
- {
- return StringId32(get_string(i));
- }
- StringId64 get_string_id_64(int i)
- {
- return StringId64(get_string(i));
- }
- StringId64 get_resource_name(int i)
- {
- return get_string_id_64(i);
- }
- Gui* get_gui(int i)
- {
- Gui* p = (Gui*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- DebugLine* get_debug_line(int i)
- {
- DebugLine* p = (DebugLine*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- ResourcePackage* get_resource_package(int i)
- {
- ResourcePackage* p = (ResourcePackage*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- World* get_world(int i)
- {
- World* p = (World*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- SceneGraph* get_scene_graph(int i)
- {
- SceneGraph* p = (SceneGraph*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- Level* get_level(int i)
- {
- Level* p = (Level*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- RenderWorld* get_render_world(int i)
- {
- RenderWorld* p = (RenderWorld*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- PhysicsWorld* get_physics_world(int i)
- {
- PhysicsWorld* p = (PhysicsWorld*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- SoundWorld* get_sound_world(int i)
- {
- SoundWorld* p = (SoundWorld*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- ScriptWorld* get_script_world(int i)
- {
- ScriptWorld* p = (ScriptWorld*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- AnimationStateMachine* get_animation_state_machine(int i)
- {
- AnimationStateMachine* p = (AnimationStateMachine*)get_pointer(i);
- #if CROWN_DEBUG
- check_type(i, p);
- #endif // CROWN_DEBUG
- return p;
- }
- UnitId get_unit(int i)
- {
- uintptr_t enc = (uintptr_t)get_pointer(i);
- #if CROWN_DEBUG
- if ((enc & LIGHTDATA_TYPE_MASK) != LIGHTDATA_UNIT_MARKER)
- {
- luaL_typerror(L, i, "UnitId");
- CE_UNREACHABLE();
- }
- #endif // CROWN_DEBUG
- UnitId id;
- id._idx = u32((enc & LIGHTDATA_UNIT_ID_MASK) >> LIGHTDATA_UNIT_ID_SHIFT);
- return id;
- }
- CameraInstance get_camera(int i)
- {
- CameraInstance inst = { get_id(i) };
- return inst;
- }
- TransformInstance get_transform(int i)
- {
- TransformInstance inst = { get_id(i) };
- return inst;
- }
- MeshInstance get_mesh_instance(int i)
- {
- MeshInstance inst = { get_id(i) };
- return inst;
- }
- SpriteInstance get_sprite_instance(int i)
- {
- SpriteInstance inst = { get_id(i) };
- return inst;
- }
- LightInstance get_light_instance(int i)
- {
- LightInstance inst = { get_id(i) };
- return inst;
- }
- Material* get_material(int i)
- {
- return (Material*)get_pointer(i);
- }
- ActorInstance get_actor(int i)
- {
- ActorInstance inst = { get_id(i) };
- return inst;
- }
- SoundInstanceId get_sound_instance_id(int i)
- {
- return get_id(i);
- }
- ScriptInstance get_script_instance(int i)
- {
- ScriptInstance inst = { get_id(i) };
- return inst;
- }
- Vector2 get_vector2(int i)
- {
- Vector3 v = get_vector3(i);
- Vector2 a;
- a.x = v.x;
- a.y = v.y;
- return a;
- }
- Vector3& get_vector3(int i)
- {
- #if CROWN_DEBUG
- return *check_temporary(i, (Vector3*)get_pointer(i));
- #else
- return *(Vector3*)get_pointer(i);
- #endif
- }
- Vector4 get_vector4(int i)
- {
- Quaternion q = get_quaternion(i);
- Vector4 a;
- a.x = q.x;
- a.y = q.y;
- a.z = q.z;
- a.w = q.w;
- return a;
- }
- Quaternion& get_quaternion(int i)
- {
- #if CROWN_DEBUG
- return *check_temporary(i, (Quaternion*)get_pointer(i));
- #else
- return *(Quaternion*)get_pointer(i);
- #endif
- }
- Matrix4x4& get_matrix4x4(int i)
- {
- #if CROWN_DEBUG
- return *check_temporary(i, (Matrix4x4*)get_pointer(i));
- #else
- return *(Matrix4x4*)get_pointer(i);
- #endif
- }
- Color4 get_color4(int i)
- {
- Quaternion q = get_quaternion(i);
- Color4 c;
- c.x = q.x;
- c.y = q.y;
- c.z = q.z;
- c.w = q.w;
- return c;
- }
- Vector2& get_vector2box(int i)
- {
- Vector2* v = (Vector2*)luaL_checkudata(L, i, "Vector2Box");
- return *v;
- }
- Vector3& get_vector3box(int i)
- {
- Vector3* v = (Vector3*)luaL_checkudata(L, i, "Vector3Box");
- return *v;
- }
- Quaternion& get_quaternionbox(int i)
- {
- Quaternion* q = (Quaternion*)luaL_checkudata(L, i, "QuaternionBox");
- return *q;
- }
- Matrix4x4& get_matrix4x4box(int i)
- {
- Matrix4x4* m = (Matrix4x4*)luaL_checkudata(L, i, "Matrix4x4Box");
- return *m;
- }
- void push_nil()
- {
- lua_pushnil(L);
- }
- void push_bool(bool value)
- {
- lua_pushboolean(L, value);
- }
- void push_int(int value)
- {
- lua_pushnumber(L, value);
- }
- void push_float(f32 value)
- {
- lua_pushnumber(L, value);
- }
- void push_string(const char* s)
- {
- lua_pushstring(L, s);
- }
- void push_fstring(const char* fmt, ...)
- {
- va_list vl;
- va_start(vl, fmt);
- lua_pushvfstring(L, fmt, vl);
- va_end(vl);
- }
- void push_lstring(const char* s, u32 len)
- {
- lua_pushlstring(L, s, len);
- }
- void push_string_id(StringId32 value)
- {
- lua_pushnumber(L, value._id);
- }
- void push_pointer(void* p)
- {
- CE_ENSURE(NULL != p);
- lua_pushlightuserdata(L, p);
- }
- void push_function(lua_CFunction f)
- {
- lua_pushcfunction(L, f);
- }
- void push_id(u32 value)
- {
- lua_pushnumber(L, value);
- }
- /// Pushes an empty table onto the stack.
- /// When you want to set keys on the table, you have to use LuaStack::push_key_begin()
- /// and LuaStack::push_key_end() as in the following example:
- ///
- /// LuaStack stack(L)
- /// stack.push_table()
- /// stack.push_key_begin("foo"); stack.push_foo(); stack.push_key_end()
- /// stack.push_key_begin("bar"); stack.push_bar(); stack.push_key_end()
- /// return 1;
- void push_table(int narr = 0, int nrec = 0)
- {
- lua_createtable(L, narr, nrec);
- }
- /// See Stack::push_table()
- void push_key_begin(const char* key)
- {
- lua_pushstring(L, key);
- }
- /// See Stack::push_table()
- void push_key_begin(int i)
- {
- lua_pushnumber(L, i);
- }
- /// See Stack::push_table()
- void push_key_end()
- {
- lua_settable(L, -3);
- }
- int next(int i)
- {
- return lua_next(L, i);
- }
- void push_gui(Gui* dg)
- {
- push_pointer(dg);
- }
- void push_debug_line(DebugLine* line)
- {
- push_pointer(line);
- }
- void push_resource_package(ResourcePackage* package)
- {
- push_pointer(package);
- }
- void push_world(World* world)
- {
- push_pointer(world);
- };
- void push_scene_graph(SceneGraph* sg)
- {
- push_pointer(sg);
- }
- void push_level(Level* level)
- {
- push_pointer(level);
- }
- void push_render_world(RenderWorld* world)
- {
- push_pointer(world);
- }
- void push_physics_world(PhysicsWorld* world)
- {
- push_pointer(world);
- }
- void push_sound_world(SoundWorld* world)
- {
- push_pointer(world);
- }
- void push_script_world(ScriptWorld* world)
- {
- push_pointer(world);
- }
- void push_animation_state_machine(AnimationStateMachine* sm)
- {
- push_pointer(sm);
- }
- void push_unit(UnitId id)
- {
- uintptr_t enc = (uintptr_t(id._idx) << LIGHTDATA_UNIT_ID_SHIFT) | LIGHTDATA_UNIT_MARKER;
- push_pointer((void*)enc);
- }
- void push_camera(CameraInstance i)
- {
- push_id(i.i);
- }
- void push_transform(TransformInstance i)
- {
- push_id(i.i);
- }
- void push_mesh_instance(MeshInstance i)
- {
- push_id(i.i);
- }
- void push_sprite_instance(SpriteInstance i)
- {
- push_id(i.i);
- }
- void push_light_instance(LightInstance i)
- {
- push_id(i.i);
- }
- void push_material(Material* material)
- {
- push_pointer(material);
- }
- void push_actor(ActorInstance i)
- {
- push_id(i.i);
- }
- void push_sound_instance_id(SoundInstanceId id)
- {
- push_id(id);
- }
- void push_script_instance(ScriptInstance i)
- {
- push_id(i.i);
- }
- void push_vector2(const Vector2& v);
- void push_vector3(const Vector3& v);
- void push_matrix4x4(const Matrix4x4& m);
- void push_quaternion(const Quaternion& q);
- void push_color4(const Color4& c);
- void push_vector2box(const Vector2& v)
- {
- Vector2* vec = (Vector2*)lua_newuserdata(L, sizeof(Vector2));
- luaL_getmetatable(L, "Vector2Box");
- lua_setmetatable(L, -2);
- *vec = v;
- }
- void push_vector3box(const Vector3& v)
- {
- Vector3* vec = (Vector3*)lua_newuserdata(L, sizeof(Vector3));
- luaL_getmetatable(L, "Vector3Box");
- lua_setmetatable(L, -2);
- *vec = v;
- }
- void push_quaternionbox(const Quaternion& q)
- {
- Quaternion* quat = (Quaternion*)lua_newuserdata(L, sizeof(Quaternion));
- luaL_getmetatable(L, "QuaternionBox");
- lua_setmetatable(L, -2);
- *quat = q;
- }
- void push_matrix4x4box(const Matrix4x4& m)
- {
- Matrix4x4* mat = (Matrix4x4*)lua_newuserdata(L, sizeof(Matrix4x4));
- luaL_getmetatable(L, "Matrix4x4Box");
- lua_setmetatable(L, -2);
- *mat = m;
- }
- void push_value(int i)
- {
- lua_pushvalue(L, i);
- }
- void call(int nresults)
- {
- lua_pcall(L, 2, nresults, 0);
- }
- #if CROWN_DEBUG
- Vector3* check_temporary(int i, const Vector3* p);
- Quaternion* check_temporary(int i, const Quaternion* p);
- Matrix4x4* check_temporary(int i, const Matrix4x4* p);
- void check_type(int i, const Gui* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != DEBUG_GUI_MARKER))
- {
- luaL_typerror(L, i, "Gui");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const DebugLine* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != DEBUG_LINE_MARKER))
- {
- luaL_typerror(L, i, "DebugLine");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const ResourcePackage* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != RESOURCE_PACKAGE_MARKER))
- {
- luaL_typerror(L, i, "ResourcePackage");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const World* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != WORLD_MARKER))
- {
- luaL_typerror(L, i, "World");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const SceneGraph* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != SCENE_GRAPH_MARKER))
- {
- luaL_typerror(L, i, "SceneGraph");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const RenderWorld* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != RENDER_WORLD_MARKER))
- {
- luaL_typerror(L, i, "RenderWorld");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const PhysicsWorld* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != PHYSICS_WORLD_MARKER))
- {
- luaL_typerror(L, i, "PhysicsWorld");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const SoundWorld* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != SOUND_WORLD_MARKER))
- {
- luaL_typerror(L, i, "SoundWorld");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const Level* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != LEVEL_MARKER))
- {
- luaL_typerror(L, i, "Level");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const ScriptWorld* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != SCRIPT_WORLD_MARKER))
- {
- luaL_typerror(L, i, "ScriptWorld");
- CE_UNREACHABLE();
- }
- }
- void check_type(int i, const AnimationStateMachine* p)
- {
- if (CE_UNLIKELY(!is_pointer(i) || *(u32*)p != ANIMATION_STATE_MACHINE_MARKER))
- {
- luaL_typerror(L, i, "AnimationStateMachine");
- CE_UNREACHABLE();
- }
- }
- #endif // CROWN_DEBUG
- };
- } // namespace crown
|