From 05589b721e11f1f908bb24b57e84965ace7e3e96 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 13 Feb 2024 18:16:18 +0300 Subject: [PATCH 1/7] lua: gui library (WIP) --- res/layouts/inventory.xml | 9 ++- res/layouts/inventory.xml.lua | 11 ++-- res/modules/document.lua | 22 +++++++ res/scripts/stdlib.lua | 20 +++++++ src/frontend/UiDocument.cpp | 8 +++ src/frontend/UiDocument.h | 1 + src/frontend/gui/UINode.cpp | 4 ++ src/frontend/gui/UINode.h | 1 + src/logic/scripting/LuaState.cpp | 4 +- src/logic/scripting/{ => api}/api_lua.h | 38 ++++++------ src/logic/scripting/api/libgui.cpp | 77 +++++++++++++++++++++++++ src/logic/scripting/api/libgui.h | 15 +++++ src/logic/scripting/lua_util.h | 75 ++++++++++++++++++++++++ src/logic/scripting/scripting.cpp | 2 + 14 files changed, 262 insertions(+), 25 deletions(-) create mode 100644 res/modules/document.lua rename src/logic/scripting/{ => api}/api_lua.h (95%) create mode 100644 src/logic/scripting/api/libgui.cpp create mode 100644 src/logic/scripting/api/libgui.h diff --git a/res/layouts/inventory.xml b/res/layouts/inventory.xml index c33d57d6..1ef2b20f 100644 --- a/res/layouts/inventory.xml +++ b/res/layouts/inventory.xml @@ -1,3 +1,10 @@ - + + diff --git a/res/layouts/inventory.xml.lua b/res/layouts/inventory.xml.lua index 532b9ee5..dfcd39a5 100644 --- a/res/layouts/inventory.xml.lua +++ b/res/layouts/inventory.xml.lua @@ -1,9 +1,12 @@ -function on_open(inv) - print("OPEN", inv) +local Document = require("core:document") +document = Document.new(DOC_NAME) + +function on_open(invid) + print("OPEN", invid) end -function on_close(inv) - print("CLOSE", inv) +function on_close(invid) + print("CLOSE", invid) end function inventory_share_func(invid, slotid) diff --git a/res/modules/document.lua b/res/modules/document.lua new file mode 100644 index 00000000..02877064 --- /dev/null +++ b/res/modules/document.lua @@ -0,0 +1,22 @@ +local Element = {} +function Element.new(docname, name) + return setmetatable({docname=docname, name=name}, { + __index=function(self, k) + return gui.getattr(self.docname, self.name, k) + end, + __newindex=function(self, k, v) + gui.setattr(self.docname, self.name, k, v) + end + }) +end + +local Document = {} +function Document.new(docname) + return setmetatable({name=docname}, { + __index=function(self, k) + return Element.new(self.name, k) + end + }) +end + +return Document diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 09d28f55..e2644f02 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -91,3 +91,23 @@ end function pack.is_installed(packid) return file.isfile(packid..":package.json") end + +vec2_mt = {} +function vec2_mt.__tostring(self) + return "vec2("..self[1]..", "..self[2]..")" +end + +vec3_mt = {} +function vec3_mt.__tostring(self) + return "vec3("..self[1]..", "..self[2]..", "..self[3]..")" +end + +vec4_mt = {} +function vec4_mt.__tostring(self) + return "vec4("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")" +end + +color_mt = {} +function color_mt.__tostring(self) + return "rgba("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")" +end \ No newline at end of file diff --git a/src/frontend/UiDocument.cpp b/src/frontend/UiDocument.cpp index 9df8f123..301c1f7c 100644 --- a/src/frontend/UiDocument.cpp +++ b/src/frontend/UiDocument.cpp @@ -30,6 +30,14 @@ const std::shared_ptr UiDocument::getRoot() const { return root; } +const std::shared_ptr UiDocument::get(const std::string& id) const { + auto found = map.find(id); + if (found == map.end()) { + return nullptr; + } + return found->second; +} + const uidocscript& UiDocument::getScript() const { return script; } diff --git a/src/frontend/UiDocument.h b/src/frontend/UiDocument.h index 7668a414..8dad5cb0 100644 --- a/src/frontend/UiDocument.h +++ b/src/frontend/UiDocument.h @@ -43,6 +43,7 @@ public: const std::string& getId() const; const uinodes_map& getMap() const; const std::shared_ptr getRoot() const; + const std::shared_ptr get(const std::string& id) const; const uidocscript& getScript() const; int getEnvironment() const; /* Collect map of all uinodes having identifiers */ diff --git a/src/frontend/gui/UINode.cpp b/src/frontend/gui/UINode.cpp index 95e8e4b7..1a726cc8 100644 --- a/src/frontend/gui/UINode.cpp +++ b/src/frontend/gui/UINode.cpp @@ -110,6 +110,10 @@ void UINode::setCoord(glm::vec2 coord) { this->coord = coord; } +glm::vec2 UINode::getCoord() const { + return coord; +} + glm::vec2 UINode::getSize() const { return size; } diff --git a/src/frontend/gui/UINode.h b/src/frontend/gui/UINode.h index 1e195932..45d6ca8b 100644 --- a/src/frontend/gui/UINode.h +++ b/src/frontend/gui/UINode.h @@ -112,6 +112,7 @@ namespace gui { /* Calculate screen position of the element */ virtual glm::vec2 calcCoord() const; virtual void setCoord(glm::vec2 coord); + glm::vec2 getCoord() const; virtual glm::vec2 getSize() const; virtual void setSize(glm::vec2 size); virtual void refresh() {}; diff --git a/src/logic/scripting/LuaState.cpp b/src/logic/scripting/LuaState.cpp index 246f4647..8a42e42a 100644 --- a/src/logic/scripting/LuaState.cpp +++ b/src/logic/scripting/LuaState.cpp @@ -1,6 +1,7 @@ #include "LuaState.h" -#include "api_lua.h" +#include "api/api_lua.h" +#include "api/libgui.h" #include "../../util/stringutil.h" lua::luaerror::luaerror(const std::string& message) : std::runtime_error(message) { @@ -98,6 +99,7 @@ void lua::LuaState::createFuncs() { openlib("item", itemlib, 0); openlib("time", timelib, 0); openlib("file", filelib, 0); + openlib("gui", guilib, 0); addfunc("print", l_print); diff --git a/src/logic/scripting/api_lua.h b/src/logic/scripting/api/api_lua.h similarity index 95% rename from src/logic/scripting/api_lua.h rename to src/logic/scripting/api/api_lua.h index 2bb3a2aa..812498cf 100644 --- a/src/logic/scripting/api_lua.h +++ b/src/logic/scripting/api/api_lua.h @@ -1,29 +1,29 @@ #ifndef LOGIC_SCRIPTING_API_LUA_H_ #define LOGIC_SCRIPTING_API_LUA_H_ -#include "scripting.h" -#include "lua_util.h" +#include "../scripting.h" +#include "../lua_util.h" #include #include -#include "../../files/files.h" -#include "../../physics/Hitbox.h" -#include "../../objects/Player.h" -#include "../../world/Level.h" -#include "../../world/World.h" -#include "../../content/Content.h" -#include "../../voxels/Block.h" -#include "../../voxels/Chunks.h" -#include "../../voxels/voxel.h" -#include "../../items/ItemDef.h" -#include "../../items/ItemStack.h" -#include "../../items/Inventory.h" -#include "../../items/Inventories.h" -#include "../../lighting/Lighting.h" -#include "../../logic/BlocksController.h" -#include "../../window/Window.h" -#include "../../engine.h" +#include "../../../files/files.h" +#include "../../../physics/Hitbox.h" +#include "../../../objects/Player.h" +#include "../../../world/Level.h" +#include "../../../world/World.h" +#include "../../../content/Content.h" +#include "../../../voxels/Block.h" +#include "../../../voxels/Chunks.h" +#include "../../../voxels/voxel.h" +#include "../../../items/ItemDef.h" +#include "../../../items/ItemStack.h" +#include "../../../items/Inventory.h" +#include "../../../items/Inventories.h" +#include "../../../lighting/Lighting.h" +#include "../../../logic/BlocksController.h" +#include "../../../window/Window.h" +#include "../../../engine.h" /* == file library == */ static int l_file_resolve(lua_State* L) { diff --git a/src/logic/scripting/api/libgui.cpp b/src/logic/scripting/api/libgui.cpp new file mode 100644 index 00000000..b9889fb0 --- /dev/null +++ b/src/logic/scripting/api/libgui.cpp @@ -0,0 +1,77 @@ +#include "libgui.h" + +#include +#include "../scripting.h" +#include "../lua_util.h" + +#include "../../../engine.h" +#include "../../../assets/Assets.h" +#include "../../../frontend/gui/UINode.h" +#include "../../../frontend/gui/controls.h" +#include "../../../frontend/UiDocument.h" +#include "../../../util/stringutil.h" + +static gui::UINode* getDocumentNode(lua_State* L, const std::string& name, const std::string& nodeName) { + auto doc = scripting::engine->getAssets()->getLayout(name); + if (doc == nullptr) { + luaL_error(L, "document '%s' not found", name.c_str()); + } + auto node = doc->get(nodeName); + if (node == nullptr) { + luaL_error(L, "document '%s' has no element with id '%s'", name.c_str(), nodeName.c_str()); + } + return node.get(); +} + +static bool getattr(lua_State* L, gui::Button* button, const std::string& attr) { + if (button == nullptr) + return false; + if (attr == "text") { + lua_pushstring(L, util::wstr2str_utf8(button->getText()).c_str()); + return true; + } + return false; +} + +static bool setattr(lua_State* L, gui::Button* button, const std::string& attr) { + if (button == nullptr) + return false; + if (attr == "text") { + button->setText(util::str2wstr_utf8(lua_tostring(L, 4))); + return true; + } + return false; +} + +int l_gui_getattr(lua_State* L) { + auto docname = lua_tostring(L, 1); + auto element = lua_tostring(L, 2); + const std::string attr = lua_tostring(L, 3); + auto node = getDocumentNode(L, docname, element); + + if (attr == "color") { + return lua::pushcolor_arr(L, node->getColor()); + } else if (attr == "coord") { + return lua::pushvec2_arr(L, node->getCoord()); + } else if (attr == "size") { + return lua::pushvec2_arr(L, node->getSize()); + } + + if (getattr(L, dynamic_cast(node), attr)) + return 1; + + return 0; +} + +int l_gui_setattr(lua_State* L) { + auto docname = lua_tostring(L, 1); + auto element = lua_tostring(L, 2); + const std::string attr = lua_tostring(L, 3); + + auto node = getDocumentNode(L, docname, element); + + if (setattr(L, dynamic_cast(node), attr)) + return 0; + + return 0; +} diff --git a/src/logic/scripting/api/libgui.h b/src/logic/scripting/api/libgui.h new file mode 100644 index 00000000..6b83e223 --- /dev/null +++ b/src/logic/scripting/api/libgui.h @@ -0,0 +1,15 @@ +#ifndef LOGIC_SCRIPTING_API_LIBGUI_H_ +#define LOGIC_SCRIPTING_API_LIBGUI_H_ + +#include + +extern int l_gui_getattr(lua_State* L); +extern int l_gui_setattr(lua_State* L); + +static const luaL_Reg guilib [] = { + {"getattr", l_gui_getattr}, + {"setattr", l_gui_setattr}, + {NULL, NULL} +}; + +#endif // LOGIC_SCRIPTING_API_LIBGUI_H_ diff --git a/src/logic/scripting/lua_util.h b/src/logic/scripting/lua_util.h index 2ad5c9e2..95761bde 100644 --- a/src/logic/scripting/lua_util.h +++ b/src/logic/scripting/lua_util.h @@ -2,6 +2,8 @@ #define LOGIC_SCRIPTING_LUA_UTIL_H_ #include +#include +#include "LuaState.h" namespace lua { inline int pushivec3(lua_State* L, luaint x, luaint y, luaint z) { @@ -10,6 +12,79 @@ namespace lua { lua_pushinteger(L, z); return 3; } + + inline int pushvec3(lua_State* L, glm::vec3 vec) { + lua_pushnumber(L, vec.x); + lua_pushnumber(L, vec.y); + lua_pushnumber(L, vec.z); + return 3; + } + + inline int pushvec4(lua_State* L, glm::vec4 vec) { + lua_pushnumber(L, vec.x); + lua_pushnumber(L, vec.y); + lua_pushnumber(L, vec.z); + lua_pushnumber(L, vec.w); + return 4; + } + + inline int pushvec2_arr(lua_State* L, glm::vec2 vec) { + lua_createtable(L, 2, 0); + lua_getglobal(L, "vec2_mt"); + lua_setmetatable(L, -2); + + lua_pushnumber(L, vec.x); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, vec.y); + lua_rawseti(L, -2, 2); + return 1; + } + + inline int pushvec3_arr(lua_State* L, glm::vec3 vec) { + lua_createtable(L, 3, 0); + lua_getglobal(L, "vec3_mt"); + lua_setmetatable(L, -2); + + lua_pushnumber(L, vec.x); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, vec.y); + lua_rawseti(L, -2, 2); + lua_pushnumber(L, vec.z); + lua_rawseti(L, -2, 3); + return 1; + } + + inline int pushvec4_arr(lua_State* L, glm::vec4 vec) { + lua_createtable(L, 4, 0); + lua_getglobal(L, "vec4_mt"); + lua_setmetatable(L, -2); + + lua_pushnumber(L, vec.x); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, vec.y); + lua_rawseti(L, -2, 2); + lua_pushnumber(L, vec.z); + lua_rawseti(L, -2, 3); + lua_pushnumber(L, vec.w); + lua_rawseti(L, -2, 4); + return 1; + } + + inline int pushcolor_arr(lua_State* L, glm::vec4 vec) { + lua_createtable(L, 4, 0); + lua_getglobal(L, "color_mt"); + lua_setmetatable(L, -2); + + lua_pushinteger(L, vec.x*255); + lua_rawseti(L, -2, 1); + lua_pushinteger(L, vec.y*255); + lua_rawseti(L, -2, 2); + lua_pushinteger(L, vec.z*255); + lua_rawseti(L, -2, 3); + lua_pushinteger(L, vec.w*255); + lua_rawseti(L, -2, 4); + return 1; + } } #endif // LOGIC_SCRIPTING_LUA_UTIL_H_ diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 9daf7c77..e4be8adf 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -16,6 +16,7 @@ #include "../../engine.h" #include "LuaState.h" #include "../../util/stringutil.h" +#include "../../util/timeutil.h" using namespace scripting; @@ -245,6 +246,7 @@ bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, } void scripting::on_ui_open(UiDocument* layout, Inventory* inventory) { + timeutil::ScopeLogTimer log(555); std::string name = layout->getId()+".open"; if (state->getglobal(name)) { state->pushinteger(inventory->getId()); From ef0d4d69e4de0967c5536bf8b0d2b8affbaeb452 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 13 Feb 2024 20:54:33 +0300 Subject: [PATCH 2/7] auto document variable in ui-document lua script --- res/layouts/inventory.xml.lua | 3 --- res/modules/document.lua | 22 ---------------------- res/scripts/stdlib.lua | 25 ++++++++++++++++++++++++- src/logic/scripting/api/libgui.cpp | 24 ++++++++++++++++++++++++ src/logic/scripting/scripting.cpp | 11 ++++++++++- 5 files changed, 58 insertions(+), 27 deletions(-) diff --git a/res/layouts/inventory.xml.lua b/res/layouts/inventory.xml.lua index dfcd39a5..c5cd5791 100644 --- a/res/layouts/inventory.xml.lua +++ b/res/layouts/inventory.xml.lua @@ -1,6 +1,3 @@ -local Document = require("core:document") -document = Document.new(DOC_NAME) - function on_open(invid) print("OPEN", invid) end diff --git a/res/modules/document.lua b/res/modules/document.lua index 02877064..e69de29b 100644 --- a/res/modules/document.lua +++ b/res/modules/document.lua @@ -1,22 +0,0 @@ -local Element = {} -function Element.new(docname, name) - return setmetatable({docname=docname, name=name}, { - __index=function(self, k) - return gui.getattr(self.docname, self.name, k) - end, - __newindex=function(self, k, v) - gui.setattr(self.docname, self.name, k, v) - end - }) -end - -local Document = {} -function Document.new(docname) - return setmetatable({name=docname}, { - __index=function(self, k) - return Element.new(self.name, k) - end - }) -end - -return Document diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index e2644f02..b8dcfb47 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -110,4 +110,27 @@ end color_mt = {} function color_mt.__tostring(self) return "rgba("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")" -end \ No newline at end of file +end + +-- class designed for simple UI-nodes access via properties syntax +local Element = {} +function Element.new(docname, name) + return setmetatable({docname=docname, name=name}, { + __index=function(self, k) + return gui.getattr(self.docname, self.name, k) + end, + __newindex=function(self, k, v) + gui.setattr(self.docname, self.name, k, v) + end + }) +end + +-- the engine automatically creates an instance for every ui document (layout) +Document = {} +function Document.new(docname) + return setmetatable({name=docname}, { + __index=function(self, k) + return Element.new(self.name, k) + end + }) +end diff --git a/src/logic/scripting/api/libgui.cpp b/src/logic/scripting/api/libgui.cpp index b9889fb0..362d45d4 100644 --- a/src/logic/scripting/api/libgui.cpp +++ b/src/logic/scripting/api/libgui.cpp @@ -33,6 +33,16 @@ static bool getattr(lua_State* L, gui::Button* button, const std::string& attr) return false; } +static bool getattr(lua_State* L, gui::Label* label, const std::string& attr) { + if (label == nullptr) + return false; + if (attr == "text") { + lua_pushstring(L, util::wstr2str_utf8(label->getText()).c_str()); + return true; + } + return false; +} + static bool setattr(lua_State* L, gui::Button* button, const std::string& attr) { if (button == nullptr) return false; @@ -43,6 +53,16 @@ static bool setattr(lua_State* L, gui::Button* button, const std::string& attr) return false; } +static bool setattr(lua_State* L, gui::Label* label, const std::string& attr) { + if (label == nullptr) + return false; + if (attr == "text") { + label->setText(util::str2wstr_utf8(lua_tostring(L, 4))); + return true; + } + return false; +} + int l_gui_getattr(lua_State* L) { auto docname = lua_tostring(L, 1); auto element = lua_tostring(L, 2); @@ -59,6 +79,8 @@ int l_gui_getattr(lua_State* L) { if (getattr(L, dynamic_cast(node), attr)) return 1; + if (getattr(L, dynamic_cast(node), attr)) + return 1; return 0; } @@ -72,6 +94,8 @@ int l_gui_setattr(lua_State* L) { if (setattr(L, dynamic_cast(node), attr)) return 0; + if (setattr(L, dynamic_cast(node), attr)) + return 0; return 0; } diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index e4be8adf..826c3971 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -130,6 +130,16 @@ std::unique_ptr scripting::create_doc_environment(int parent, const state->setfield("DOC_ENV"); state->pushstring(name.c_str()); state->setfield("DOC_NAME"); + + if (state->getglobal("Document")) { + if (state->getfield("new")) { + state->pushstring(name.c_str()); + if (state->callNoThrow(1)) { + state->setfield("document", -3); + } + } + state->pop(); + } state->pop(); return std::make_unique(id); } @@ -246,7 +256,6 @@ bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, } void scripting::on_ui_open(UiDocument* layout, Inventory* inventory) { - timeutil::ScopeLogTimer log(555); std::string name = layout->getId()+".open"; if (state->getglobal(name)) { state->pushinteger(inventory->getId()); From c6bd52eed2589a75f900bc76b5c37c3897ab8d61 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 14 Feb 2024 00:31:45 +0300 Subject: [PATCH 3/7] gui: more xml and lua support --- res/layouts/inventory.xml | 32 ++++++++++++++----- res/layouts/inventory.xml.lua | 4 +++ src/delegates.h | 2 ++ src/engine.cpp | 4 +++ src/engine.h | 1 + src/frontend/gui/controls.h | 3 -- src/frontend/gui/gui_xml.cpp | 30 +++++++++++++++++- src/logic/scripting/api/api_lua.h | 6 ++++ src/logic/scripting/scripting.cpp | 52 ++++++++++++++++++++----------- src/logic/scripting/scripting.h | 6 ++++ 10 files changed, 110 insertions(+), 30 deletions(-) diff --git a/res/layouts/inventory.xml b/res/layouts/inventory.xml index 1ef2b20f..416778b6 100644 --- a/res/layouts/inventory.xml +++ b/res/layouts/inventory.xml @@ -1,10 +1,26 @@ - + - + + + + + + + + + + 4321.40 + + + + 120.0 + + + + -424.10 + + + + + diff --git a/res/layouts/inventory.xml.lua b/res/layouts/inventory.xml.lua index c5cd5791..2386812c 100644 --- a/res/layouts/inventory.xml.lua +++ b/res/layouts/inventory.xml.lua @@ -9,3 +9,7 @@ end function inventory_share_func(invid, slotid) inventory.set(invid, slotid, 0, 0) end + +function time_change(x) + world.set_day_time(x) +end diff --git a/src/delegates.h b/src/delegates.h index 61360464..c938cd02 100644 --- a/src/delegates.h +++ b/src/delegates.h @@ -8,5 +8,7 @@ using runnable = std::function; using stringconsumer = std::function; using wstringsupplier = std::function; using wstringconsumer = std::function; +using doublesupplier = std::function; +using doubleconsumer = std::function; #endif // DELEGATES_H_ diff --git a/src/engine.cpp b/src/engine.cpp index d1e85eeb..80d9114a 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -208,6 +208,10 @@ void Engine::loadAllPacks() { ContentPack::scan(paths, contentPacks); } +double Engine::getDelta() const { + return delta; +} + void Engine::setScreen(std::shared_ptr screen) { this->screen = screen; } diff --git a/src/engine.h b/src/engine.h index 1532e84b..90ffc8b5 100644 --- a/src/engine.h +++ b/src/engine.h @@ -63,6 +63,7 @@ public: void loadContent(); void loadWorldContent(const fs::path& folder); void loadAllPacks(); + double getDelta() const; std::shared_ptr getScreen(); }; diff --git a/src/frontend/gui/controls.h b/src/frontend/gui/controls.h index ae07b4d7..80e7d42f 100644 --- a/src/frontend/gui/controls.h +++ b/src/frontend/gui/controls.h @@ -17,9 +17,6 @@ class Batch2D; class Assets; namespace gui { - using doublesupplier = std::function; - using doubleconsumer = std::function; - using boolsupplier = std::function; using boolconsumer = std::function; diff --git a/src/frontend/gui/gui_xml.cpp b/src/frontend/gui/gui_xml.cpp index 2721b5c1..43daee3b 100644 --- a/src/frontend/gui/gui_xml.cpp +++ b/src/frontend/gui/gui_xml.cpp @@ -124,6 +124,13 @@ static std::shared_ptr readContainer(UiXmlReader& reader, xml::xmlelemen return container; } +static std::shared_ptr readPanel(UiXmlReader& reader, xml::xmlelement element) { + float interval = element->attr("interval", "2").asFloat(); + auto panel = std::make_shared(glm::vec2(), glm::vec4(), interval); + _readPanel(reader, element, *panel); + return panel; +} + static std::shared_ptr readButton(UiXmlReader& reader, xml::xmlelement element) { std::wstring text = readAndProcessInnerText(element); auto button = std::make_shared