diff --git a/doc/en/scripting/ui.md b/doc/en/scripting/ui.md index 80750501..c35bf908 100644 --- a/doc/en/scripting/ui.md +++ b/doc/en/scripting/ui.md @@ -37,6 +37,7 @@ Properties that apply to all elements: | Name | Type | Read | Write | Description | | ------------- | ------- | ---- | ----- | ------------------------------------------- | | id | string | yes | *no* | element id | +| exists | bool | yes | *no* | checks if element exists | | pos | vec2 | yes | yes | element position inside a container | | wpos | vec2 | yes | yes | element position inside the window | | size | vec2 | yes | yes | element size | diff --git a/doc/ru/scripting/ui.md b/doc/ru/scripting/ui.md index c6c769ac..a6d6006d 100644 --- a/doc/ru/scripting/ui.md +++ b/doc/ru/scripting/ui.md @@ -37,6 +37,7 @@ document["worlds-panel"]:clear() | Название | Тип | Чтение | Запись | Описание | | ------------- | ------- | ------ | ------ | ----------------------------------------- | | id | string | да | *нет* | идентификатор элемента | +| exists | bool | да | *нет* | проверяет, существует ли элемент | | pos | vec2 | да | да | позиция элемента внутри контейнера | | wpos | vec2 | да | да | позиция элемента в окне | | size | vec2 | да | да | размер элемента | diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 89789e29..5cc16119 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -469,6 +469,7 @@ void Hud::showExchangeSlot() { gui, SlotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr) ); + exchangeSlot->setId("hud.exchange-slot"); exchangeSlot->bind(exchangeSlotInv->getId(), exchangeSlotInv->getSlot(0), &content); exchangeSlot->setColor(glm::vec4()); exchangeSlot->setInteractive(false); diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 3697d39c..cdf65898 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -30,14 +30,17 @@ using namespace gui; using namespace scripting; static DocumentNode get_document_node_impl( - lua::State*, const std::string& name, const std::string& nodeName + lua::State*, const std::string& name, const std::string& nodeName, bool throwable=true ) { auto doc = engine->getAssets()->get(name); if (doc == nullptr) { - throw std::runtime_error("document '" + name + "' not found"); + if (throwable) { + throw std::runtime_error("document '" + name + "' not found"); + } + return {nullptr, nullptr}; } auto node = doc->get(nodeName); - if (node == nullptr) { + if (node == nullptr && throwable) { throw std::runtime_error( "document '" + name + "' has no element with id '" + nodeName + "'" ); @@ -459,6 +462,9 @@ static int p_get_content_offset(UINode* node, lua::State* L) { return lua::pushvec(L, node->getContentOffset()); } static int p_get_id(UINode* node, lua::State* L) { + if (node == nullptr) { + return 0; + } return lua::pushstring(L, node->getId()); } static int p_get_color(UINode* node, lua::State* L) { @@ -540,6 +546,14 @@ static int p_get_options(UINode* node, lua::State* L) { return 0; } +static int p_is_exists(UINode* node, lua::State* L) { + return lua::pushboolean(L, node != nullptr); +} + +static bool is_node_required(std::string_view attr) { + return attr != "exists"; +} + static int l_gui_getattr(lua::State* L) { if (!lua::isstring(L, 1)) { throw std::runtime_error("document name is not a string"); @@ -568,12 +582,14 @@ static int l_gui_getattr(lua::State* L) { throw std::runtime_error("attribute name is not a string"); } auto attr = lua::require_string(L, 3); + bool required = is_node_required(attr); static const std::unordered_map< std::string_view, std::function> getters { {"id", p_get_id}, + {"exists", p_is_exists}, {"color", p_get_color}, {"hoverColor", p_get_hover_color}, {"pressedColor", p_get_pressed_color}, @@ -630,7 +646,7 @@ static int l_gui_getattr(lua::State* L) { }; auto func = getters.find(attr); if (func != getters.end()) { - auto docnode = get_document_node_impl(L, docname, element); + auto docnode = get_document_node_impl(L, docname, element, required); auto node = docnode.node; return func->second(node.get(), L); }