From b1974405c69596edf0cfd4a4b5cd42ba0d65448e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 31 May 2026 22:09:14 +0300 Subject: [PATCH] fix gui.load_document environment extension --- src/frontend/UiDocument.cpp | 19 ++++++++---------- src/frontend/UiDocument.hpp | 6 ++---- src/graphics/ui/gui_xml.cpp | 7 +++---- src/graphics/ui/gui_xml.hpp | 4 ++-- src/logic/scripting/lua/libs/libgui.cpp | 26 +++++++++++++++---------- src/logic/scripting/lua/lua_util.cpp | 11 +++++++++++ src/logic/scripting/lua/lua_util.hpp | 11 ++--------- 7 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/frontend/UiDocument.cpp b/src/frontend/UiDocument.cpp index a202c0d96..7e0c9bfc6 100644 --- a/src/frontend/UiDocument.cpp +++ b/src/frontend/UiDocument.cpp @@ -61,16 +61,19 @@ std::unique_ptr UiDocument::read( const scriptenv& penv, const std::string& name, const io::path& file, - const std::string& fileName + const std::string& fileName, + scriptenv&& env ) { const std::string text = io::read_string(file); auto xmldoc = xml::parse(file.string(), text); - auto env = penv == nullptr - ? scripting::create_doc_environment(scripting::get_root_environment(), name) - : scripting::create_doc_environment(penv, name); + if (env == nullptr) { + env = penv == nullptr + ? scripting::create_doc_environment(scripting::get_root_environment(), name) + : scripting::create_doc_environment(penv, name); + } - gui::UiXmlReader reader(gui, scriptenv(env)); + gui::UiXmlReader reader(gui, env); auto view = reader.readXML(file.string(), *xmldoc->getRoot()); view->setId("root"); UiDocScript script {}; @@ -82,9 +85,3 @@ std::unique_ptr UiDocument::read( } return std::make_unique(name, script, view, env); } - -std::shared_ptr UiDocument::readElement( - gui::GUI& gui, const io::path& file, const std::string& fileName -) { - return read(gui, nullptr, file.name(), file, fileName)->getRoot(); -} diff --git a/src/frontend/UiDocument.hpp b/src/frontend/UiDocument.hpp index 57077bec0..5b40ca8ca 100644 --- a/src/frontend/UiDocument.hpp +++ b/src/frontend/UiDocument.hpp @@ -50,9 +50,7 @@ public: const scriptenv& parent_env, const std::string& name, const io::path& file, - const std::string& fileName - ); - static std::shared_ptr readElement( - gui::GUI&, const io::path& file, const std::string& fileName + const std::string& fileName, + scriptenv&& env = nullptr ); }; diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 33d57aa9a..e91b4553f 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -889,8 +889,8 @@ static std::shared_ptr read_iframe( return iframe; } -UiXmlReader::UiXmlReader(gui::GUI& gui, scriptenv&& env) - : gui(gui), env(std::move(env)) { +UiXmlReader::UiXmlReader(gui::GUI& gui, const scriptenv& env) + : gui(gui), env(env) { contextStack.emplace(""); add("image", read_image); add("canvas", read_canvas); @@ -922,8 +922,7 @@ void UiXmlReader::addIgnore(const std::string& tag) { ignored.insert(tag); } -std::shared_ptr UiXmlReader::readUINode(const xml::xmlelement& element -) { +std::shared_ptr UiXmlReader::readUINode(const xml::xmlelement& element) { if (element.has("if")) { const auto& cond = element.attr("if").getText(); if (cond.empty() || cond == "false" || cond == "nil") return nullptr; diff --git a/src/graphics/ui/gui_xml.hpp b/src/graphics/ui/gui_xml.hpp index 4a8a301ff..733503526 100644 --- a/src/graphics/ui/gui_xml.hpp +++ b/src/graphics/ui/gui_xml.hpp @@ -20,9 +20,9 @@ namespace gui { std::unordered_set ignored; std::stack contextStack; std::string filename; - scriptenv env; + const scriptenv& env; public: - UiXmlReader(gui::GUI& gui, scriptenv&& env); + UiXmlReader(gui::GUI& gui, const scriptenv& env); void add(const std::string& tag, uinode_reader reader); bool hasReader(const std::string& tag) const; diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 58a2f2be1..42aa0facf 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -1116,28 +1116,34 @@ static int l_gui_load_document(lua::State* L) { auto args = lua::tovalue(L, 3); auto prefix = filename.entryPoint(); - auto env = scripting::get_root_environment(); + auto parentEnv = scripting::get_root_environment(); if (content) { if (auto runtime = content->getPackRuntime(prefix)) { - env = runtime->getEnvironment(); + parentEnv = runtime->getEnvironment(); } } - auto documentPtr = UiDocument::read( - engine->getGUI(), std::move(env), alias, filename, filename.string() - ); - auto document = documentPtr.get(); - engine->requireAssets().store(std::move(documentPtr), alias); - + auto env = scripting::create_doc_environment(parentEnv, alias); // namespace extension if (lua::istable(L, 4)) { - if (lua::get_from(L, "table", "merge")) { - lua::pushenv(L, *document->getEnvironment()); + if (lua::get_from(L, "table", "merge_replace")) { + lua::pushenv(L, *env); lua::pushvalue(L, 4); lua::call(L, 2, 0); lua::pop(L); } } + auto documentPtr = UiDocument::read( + engine->getGUI(), + nullptr, + alias, + filename, + filename.string(), + std::move(env) + ); + auto document = documentPtr.get(); + engine->requireAssets().store(std::move(documentPtr), alias); + scripting::on_ui_open(document, {args}); return 0; } diff --git a/src/logic/scripting/lua/lua_util.cpp b/src/logic/scripting/lua/lua_util.cpp index 090e47a5d..e28e6ad37 100644 --- a/src/logic/scripting/lua/lua_util.cpp +++ b/src/logic/scripting/lua/lua_util.cpp @@ -414,3 +414,14 @@ std::string_view lua::bytearray_as_string(lua::State* L, int idx) { return bytearray_as_string_indirect(L, idx); } } + +void lua::loadbuffer( + lua::State* L, int env, const std::string& src, const std::string& file +) { + if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) { + throw luaerror(tostring(L, -1)); + } + if (env && getregistry(L, ENVS_TABLE, env_name(env))) { + lua_setfenv(L, -2); + } +} diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index 562e641ef..d78afaad1 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -555,16 +555,9 @@ namespace lua { return lua_setfenv(L, idx); } - inline void loadbuffer( + void loadbuffer( lua::State* L, int env, const std::string& src, const std::string& file - ) { - if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) { - throw luaerror(tostring(L, -1)); - } - if (env && getregistry(L, ENVS_TABLE, env_name(env))) { - lua_setfenv(L, -2); - } - } + ); inline void store_in( lua::State* L, const std::string& tableName, const std::string& name