From ee1f8f41a8cee37c675a90d0974035f33f0b8aa5 Mon Sep 17 00:00:00 2001 From: Mikulas Florek Date: Thu, 21 Sep 2023 21:01:55 +0200 Subject: [PATCH] array properties in lua api --- src/engine/lua_wrapper.cpp | 25 +++++ src/engine/lua_wrapper.h | 1 + src/engine/resource_manager.cpp | 5 + src/lua_script/lua_script_system.cpp | 131 ++++++++++++++++++--------- 4 files changed, 119 insertions(+), 43 deletions(-) diff --git a/src/engine/lua_wrapper.cpp b/src/engine/lua_wrapper.cpp index 0d1e45422..583beda74 100644 --- a/src/engine/lua_wrapper.cpp +++ b/src/engine/lua_wrapper.cpp @@ -151,6 +151,31 @@ void pushEntity(lua_State* L, EntityPtr value, World* world) { ASSERT(!error); } +void pushObject(lua_State* L, void* obj, StringView type_name) { + ASSERT(!type_name.empty()); + LuaWrapper::DebugGuard guard(L, 1); + lua_getglobal(L, "LumixAPI"); + char tmp[64]; + copyString(Span(tmp), type_name); + + if (LuaWrapper::getField(L, -1, tmp) != LUA_TTABLE) { + lua_pop(L, 2); + lua_newtable(L); + lua_pushlightuserdata(L, obj); + lua_setfield(L, -2, "_value"); + ASSERT(false); + return; + } + + lua_newtable(L); // [LumixAPI, class, obj] + lua_pushlightuserdata(L, obj); // [LumixAPI, class, obj, obj_ptr] + lua_setfield(L, -2, "_value"); // [LumixAPI, class, obj] + lua_pushvalue(L, -2); // [LumixAPI, class, obj, class] + lua_setmetatable(L, -2); // [LumixAPI, class, obj] + lua_remove(L, -2); // [LumixAPI, obj] + lua_remove(L, -2); // [obj] +} + int luaL_loadbuffer(lua_State* L, const char* buff, size_t size, const char* name) { size_t bytecode_size; char* bytecode = luau_compile(buff, size, nullptr, &bytecode_size); diff --git a/src/engine/lua_wrapper.h b/src/engine/lua_wrapper.h index 00fe3baae..4473e17d2 100644 --- a/src/engine/lua_wrapper.h +++ b/src/engine/lua_wrapper.h @@ -56,6 +56,7 @@ LUMIX_ENGINE_API int getField(lua_State* L, int idx, const char* k); LUMIX_ENGINE_API void luaL_unref(lua_State* L, int t, int ref); LUMIX_ENGINE_API int luaL_ref(lua_State* L, int idx); LUMIX_ENGINE_API int luaL_loadbuffer(lua_State* L, const char* buff, size_t size, const char* name); +LUMIX_ENGINE_API void pushObject(lua_State* L, void* obj, StringView type_name); template inline bool isType(lua_State* L, int index) { diff --git a/src/engine/resource_manager.cpp b/src/engine/resource_manager.cpp index 883b409fa..720fa835e 100644 --- a/src/engine/resource_manager.cpp +++ b/src/engine/resource_manager.cpp @@ -153,6 +153,11 @@ void ResourceManagerHub::init(FileSystem& fs) m_file_system = &fs; } +bool ResourceManagerHub::loadRaw(const Path& included_from, const Path& path, OutputMemoryStream& data) { + if (m_load_hook) m_load_hook->loadRaw(included_from, path); + return m_file_system->getContentSync(path, data); +} + Resource* ResourceManagerHub::load(ResourceType type, const Path& path) { ResourceManager* manager = get(type); diff --git a/src/lua_script/lua_script_system.cpp b/src/lua_script/lua_script_system.cpp index b7f78578b..d570b0617 100644 --- a/src/lua_script/lua_script_system.cpp +++ b/src/lua_script/lua_script_system.cpp @@ -44,33 +44,76 @@ static const char* toString(InputSystem::Event::Type type) { return "N/A"; } +static void convertPropertyToLuaName(const char* src, Span out) { + const u32 max_size = out.length(); + ASSERT(max_size > 0); + char* dest = out.begin(); + while (*src && dest - out.begin() < max_size - 1) { + if (isLetter(*src)) { + *dest = isUpperCase(*src) ? *src - 'A' + 'a' : *src; + ++dest; + } + else if (isNumeric(*src)) { + *dest = *src; + ++dest; + } + else { + *dest = '_'; + ++dest; + } + ++src; + } + *dest = 0; +} + +struct ArrayItemSetVisitor : reflection::IPropertyVisitor { + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::Property& prop) override { set(prop); } + void visit(const reflection::ArrayProperty& prop) override { ASSERT(false); } + void visit(const reflection::BlobProperty& prop) override { ASSERT(false); } + void visit(const reflection::DynamicProperties& prop) override { ASSERT(false); } + + template + void set(const reflection::Property& prop) { + char tmp[50]; + convertPropertyToLuaName(prop.name, Span(tmp)); + i32 type = lua_getfield(L, -1, tmp); + if (type == LUA_TNIL) { + lua_pop(L, 1); + return; + } + if (!LuaWrapper::isType(L, -1)) { + lua_pop(L, 1); + luaL_error(L, "%s has incorrect type", tmp); + } + + T val = LuaWrapper::toType(L, -1); + lua_pop(L, 1); + prop.set(cmp, idx, val); + } + + ComponentUID cmp; + const char* prop_name; + u32 idx; + lua_State* L; +}; static void pushObject(lua_State* L, void* obj, StringView type_name) { ASSERT(!type_name.empty()); - LuaWrapper::DebugGuard guard(L, 1); - lua_getglobal(L, "LumixAPI"); - char tmp[64]; const char* c = type_name.end - 1; while (*c != ':' && c != type_name.begin) --c; if (*c == ':') ++c; - copyString(Span(tmp), StringView(c, u32(type_name.end - c - 2))); - if (LuaWrapper::getField(L, -1, tmp) != LUA_TTABLE) { - lua_pop(L, 2); - lua_newtable(L); - lua_pushlightuserdata(L, obj); - lua_setfield(L, -2, "_value"); - ASSERT(false); - return; - } - - lua_newtable(L); // [LumixAPI, class, obj] - lua_pushlightuserdata(L, obj); // [LumixAPI, class, obj, obj_ptr] - lua_setfield(L, -2, "_value"); // [LumixAPI, class, obj] - lua_pushvalue(L, -2); // [LumixAPI, class, obj, class] - lua_setmetatable(L, -2); // [LumixAPI, class, obj] - lua_remove(L, -2); // [LumixAPI, obj] - lua_remove(L, -2); // [obj] + LuaWrapper::pushObject(L, obj, StringView(c, u32(type_name.end - c - 2))); } static void toVariant(reflection::Variant::Type type, lua_State* L, int idx, reflection::Variant& val) { @@ -1011,28 +1054,6 @@ public: return 1; } - static void convertPropertyToLuaName(const char* src, Span out) { - const u32 max_size = out.length(); - ASSERT(max_size > 0); - char* dest = out.begin(); - while (*src && dest - out.begin() < max_size - 1) { - if (isLetter(*src)) { - *dest = isUpperCase(*src) ? *src - 'A' + 'a' : *src; - ++dest; - } - else if (isNumeric(*src)) { - *dest = *src; - ++dest; - } - else { - *dest = '_'; - ++dest; - } - ++src; - } - *dest = 0; - } - static bool isSameProperty(const char* name, const char* lua_name) { char tmp[50]; convertPropertyToLuaName(name, Span(tmp)); @@ -1226,7 +1247,31 @@ public: prop.set(cmp, idx, val); } - void visit(const reflection::ArrayProperty& prop) override {} + void set(const reflection::ArrayProperty& prop, u32 idx) { + ArrayItemSetVisitor visitor; + visitor.idx = idx; + visitor.cmp = cmp; + visitor.prop_name = prop.name; + visitor.L = L; + + prop.visitChildren(visitor); + } + + void visit(const reflection::ArrayProperty& prop) override { + if (!isSameProperty(prop.name, prop_name)) return; + LuaWrapper::checkTableArg(L, 3); + + lua_pushnil(L); + while (prop.getCount(cmp) > 0) prop.removeItem(cmp, 0); + u32 idx = 0; + while (lua_next(L, 3)) { + prop.addItem(cmp, idx); + set(prop, idx); + ++idx; + lua_pop(L, 1); + } + } + void visit(const reflection::BlobProperty& prop) override {} ComponentUID cmp;