From 50af44c9de57b3f1c9489eaa78c08ad15c7dcb53 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 9 Nov 2025 21:24:21 +0300 Subject: [PATCH 01/95] update doc/*/content-packs.md --- doc/en/content-packs.md | 75 +++++++++++++++++++++++++++++++++++++- doc/ru/content-packs.md | 79 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 151 insertions(+), 3 deletions(-) diff --git a/doc/en/content-packs.md b/doc/en/content-packs.md index a41f95f99..c193fb188 100644 --- a/doc/en/content-packs.md +++ b/doc/en/content-packs.md @@ -48,6 +48,79 @@ Example: Content pack picture should be added as *icon.png* file. Recommended size: 128x128 -See *res/content/base* as an example of content pack structure. +# File System +Every loaded pack is mounted to the internal file system as a new mount point, whose name matches the pack's id. +This means that accessing pack files does not require the use of additional functions: + +```lua +print(file.read("your_pack_id:package.json")) -- will output the contents of the pack's package.json +``` + +This is also one of the reasons why some ids are reserved and cannot be used. + +Mount points are mounted as read-only. To gain write access, use the `pack.request_writeable` function. + +Read more about the [file](scripting/builtins/libfile.md) library. + +# Content Pack Structure + +Don't be intimidated by the following text, as a minimal pack only requires `package.json`. + +- Content: + - `block_materials/` - Block material definitions + - `blocks/` - Block definitions + - `items/` - Item definitions + - `generators/` - World generators + - `entities/` - Entity definitions + - `skeletons/` - Entity skeleton definitions + - `presets/` - Presets (can also be used by packs for their own purposes) + - `text3d/` - 3D Text + - `weather/` - Weather +- Code: + - `modules/` - Script modules + - `scripts/` - Content scripts, world scripts + - `components/` - Entity components +- Assets (Client-side resources): + - `fonts/` - Fonts + - `models/` - 3D Models + - `textures/` - Textures + - `shaders/` - Shaders + - `effects/` - Post-processing effects + - `sounds/` - Sounds and Music + - `texts/` - Localization files +- GUI: + - `layouts/` - UI Layouts + - `pages/` - Menu page layouts (for the pagebox element) +- Configuration: + - `config/` - Configuration files + - `defaults.toml` - Overrides for standard content bindings, such as the player entity, default generator, etc. + - `bindings.toml` - Keyboard/Mouse bindings + - `user-props.toml` - User properties for content definitions + - `devtools/` - Auxiliary files for internal debugging tools + - `content.json` - Automatically generated content lists, used for validating world indices and for conversion when mismatched + - `icon.png` - Pack icon + - `package.json` - Pack definition file + - `preload.json` - Asset preload lists for assets that are not loaded automatically; avoid listing assets unnecessarily + - `resources.json` - Definition lists for [resources](resources.md) (not to be confused with assets) + - `resource-aliases.json` - Files declaring aliases for [resources](resources.md) + +> [!WARNING] +> Manually editing `content.json` is strongly discouraged and will most likely lead to irreversible world corruption. + +# Content Sources + +Content packs are searched for within **content sources**, which are paths in the engine's file system. + +Source priority determines the scan order: if the same pack is found in multiple sources, the one belonging to the source with the highest priority will be selected. + +Content sources in descending order of priority: +- `world:content` - Content in the world folder (`world/content/`) +- `user:content` - Content in the user folder (`$HOME/.voxeng/content/`) +- `project:content` - Content in the project folder (`project/content/`) +- `res:content` - Built-in content shipped with the engine core (`res/content/`) + +I.e., if the same pack exists in both `world:content` and `user:content`, the version from `world:content` will be selected. + +The pack version, however, is currently not taken into account. diff --git a/doc/ru/content-packs.md b/doc/ru/content-packs.md index 4245555f8..32f9be593 100644 --- a/doc/ru/content-packs.md +++ b/doc/ru/content-packs.md @@ -50,5 +50,80 @@ Изображение контент-пака добавляется в виде файла *icon.png* в папку пака (не в textures). Рекомендованный размер изображения: 128x128 -Новые блоки добавляются в под-папку **blocks**, предметы в **items**, текстуры в **textures** -С примером файловой структуры лучше ознакомиться через базовый пакет (*res/content/base*) +# Файловая система + +Каждый загруженный пак монтируется к внутренней файловой системе как новая точка входа, имя которой совпадает с id пака. + +Это значит, что для доступа к файлам пака не требуется использование дополнительных функций: + +```lua +print(file.read("пак:package.json")) -- выведет содержимое package.json пака +``` + +Также это является одной из причин того, что некоторые id зарезервированы от использования. + +Точки входа монтируются как read-only. Для получения доступа к записи существует функция pack.request_writeable. + +Подробнее про библиотеку [file](scripting/builtins/libfile.md). + +# Структура контент-пака + +Пусть вас не пугает следующий текст, ведь минимальный пак содержит только package.json. + +- Контент: + - `block_materials/` - определения материалов блоков + - `blocks/` - определения блоков + - `items/` - определения предметов + - `generators/` - генераторы мира + - `entities/` - определения сущностей + - `skeletons/` - определения скелетов сущностей + - `presets/` - пресеты (может использоваться и паками в своих целях) + - `text3d/` - 3D текст + - `weather/` - погода +- Код: + - `modules/` - скриптовые модули + - `scripts/` - скрипты контента, мира + - `components/` - компоненты сущностей +- Ассеты (ресурсы клиентской стороны): + - `fonts/` - шрифты + - `models/` - 3D модели + - `textures/` - текстуры + - `shaders/` - шейдеры + - `effects/` - эффекты пост-обработки + - `sounds/` - звуки и музыка + - `texts/` - файлы локализации +- GUI: + - `layouts/` - макеты UI + - `pages/` - макеты страниц меню (элемент pagebox) +- Конфигурация: + - `config/` - файлы конфигурации + - `defaults.toml` - переопределения стандартных привязок к контенту, такие как сущность игрока, генератор по-умолчанию и т.д. + - `bindings.toml` - привязки к клавишам / мыши + - `user-props.toml` - пользовательские свойства определений контента + - `devtools/` - вспомогательные файлы внутренних инструментов отладки + - `content.json` - генерируемые автоматически списки контента, используемое для проверки корректности индексов в мире и конвертации при несовпадении + - `icon.png` - иконка пака + - `package.json` - файл опеределения пака + - `preload.json` - списки предзагрузки ассетов, которые не загружаются автоматически, не следует указывать ассеты без надобности + - `resources.json` - списки определений [ресурсов](resources.md) (не путать с ассетами) + - `resource-aliases.json` - файлы объявления псевдонимов для [ресурсов](resources.md) + +> [!WARNING] +> Ручное редактирование `content.json` противопоказано и скорее всего приведёт к необратимой поломке миров. + +# Источники контента + +Поиск контент-паков производится среди **источников контента**, являющихся путями в файловой системе движка. + +Приоритет источника определяет порядок сканирования: если один и тот же пак найден в нескольких источниках, +будет выбран тот, что принадлежит источнику с наивысшим приоритетом. + +Источники контента в порядке убывания приоритета: +- `world:content` - контент папке с миром (`мир/content/`) +- `user:content` - контент в папке пользователя (`$HOME/.voxeng/content/`) +- `project:content` - контент в папке с проектом (`проект/content/`) +- `res:content` - встроенный контент, поставляемый вместе с ядром движка (`res/content/`) + +Т.е. если в `world:content` и в `user:content` есть один и тот же пак, будет выбрана версия из `world:content`. + +Версия пака, при этом, на данный момент, не учитывается. From 7d367a9793763c3c9cc98a75b248e749c6a0222c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 10 Nov 2025 20:48:26 +0300 Subject: [PATCH 02/95] add app.set_title --- res/scripts/stdlib.lua | 1 + src/engine/WindowControl.cpp | 9 +++++---- src/logic/scripting/lua/libs/libcore.cpp | 8 ++++++++ src/window/Window.hpp | 1 + src/window/detail/GLFWWindow.cpp | 4 ++++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index eedc9d43f..3cbf60a43 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -47,6 +47,7 @@ local function complete_app_lib(app) end app.reset_content = core.reset_content app.is_content_loaded = core.is_content_loaded + app.set_title = core.set_title function app.config_packs(packs_list) -- Check if packs are valid and add dependencies to the configuration diff --git a/src/engine/WindowControl.cpp b/src/engine/WindowControl.cpp index 5ae969650..a93c15997 100644 --- a/src/engine/WindowControl.cpp +++ b/src/engine/WindowControl.cpp @@ -33,11 +33,12 @@ WindowControl::Result WindowControl::initialize() { auto& settings = engine.getSettings(); std::string title = project.title; - if (title.empty()) { - title = "VoxelCore v" + - std::to_string(ENGINE_VERSION_MAJOR) + "." + - std::to_string(ENGINE_VERSION_MINOR); + if (!title.empty()) { + title += " - "; } + title += "VoxelCore v" + + std::to_string(ENGINE_VERSION_MAJOR) + "." + + std::to_string(ENGINE_VERSION_MINOR); if (ENGINE_DEBUG_BUILD) { title += " [debug]"; } diff --git a/src/logic/scripting/lua/libs/libcore.cpp b/src/logic/scripting/lua/libs/libcore.cpp index 8f8a7bc89..3989fd7ff 100644 --- a/src/logic/scripting/lua/libs/libcore.cpp +++ b/src/logic/scripting/lua/libs/libcore.cpp @@ -25,6 +25,7 @@ #include "graphics/ui/gui_util.hpp" #include "graphics/ui/GUI.hpp" #include "graphics/ui/elements/Menu.hpp" +#include "window/Window.hpp" using namespace scripting; @@ -298,6 +299,12 @@ static int l_capture_output(lua::State* L) { return 1; } +static int l_set_title(lua::State* L) { + auto title = lua::require_string(L, 1); + engine->getWindow().setTitle(title); + return 0; +} + const luaL_Reg corelib[] = { {"blank", lua::wrap}, {"get_version", lua::wrap}, @@ -319,5 +326,6 @@ const luaL_Reg corelib[] = { {"open_url", lua::wrap}, {"quit", lua::wrap}, {"capture_output", lua::wrap}, + {"set_title", lua::wrap}, {nullptr, nullptr} }; diff --git a/src/window/Window.hpp b/src/window/Window.hpp index 710044705..a5a3240b9 100644 --- a/src/window/Window.hpp +++ b/src/window/Window.hpp @@ -36,6 +36,7 @@ public: virtual void setMode(WindowMode mode) = 0; virtual WindowMode getMode() const = 0; + virtual void setTitle(const std::string& title) = 0; virtual void setIcon(const ImageData* image) = 0; virtual void pushScissor(glm::vec4 area) = 0; diff --git a/src/window/detail/GLFWWindow.cpp b/src/window/detail/GLFWWindow.cpp index a80c10e00..236ce16d2 100644 --- a/src/window/detail/GLFWWindow.cpp +++ b/src/window/detail/GLFWWindow.cpp @@ -468,6 +468,10 @@ public: return mode; } + void setTitle(const std::string& title) override { + glfwSetWindowTitle(window, title.c_str()); + } + void setIcon(const ImageData* image) override { if (image == nullptr) { glfwSetWindowIcon(window, 0, nullptr); From fc68d6cecab89829b1c1fde24a4f4c4e07e857ce Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 12 Nov 2025 01:16:33 +0300 Subject: [PATCH 03/95] update InlineFrame::act --- src/graphics/ui/elements/InlineFrame.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/graphics/ui/elements/InlineFrame.cpp b/src/graphics/ui/elements/InlineFrame.cpp index 13625058b..5df635b81 100644 --- a/src/graphics/ui/elements/InlineFrame.cpp +++ b/src/graphics/ui/elements/InlineFrame.cpp @@ -36,12 +36,11 @@ void InlineFrame::setDocument(const std::shared_ptr& document) { } void InlineFrame::act(float delta) { - Container::act(delta); - if (document || src.empty()) { - return; + if (document == nullptr && !src.empty()) { + const auto& assets = *gui.getEngine().getAssets(); + setDocument(assets.getShared(src)); } - const auto& assets = *gui.getEngine().getAssets(); - setDocument(assets.getShared(src)); + Container::act(delta); } void InlineFrame::setSize(glm::vec2 size) { From fb78e9f694a638a39f1a38be1a37cb7f35739ad6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 12 Nov 2025 01:17:10 +0300 Subject: [PATCH 04/95] replace glfwWaitEvents with glfwWaitEventsTimeout --- src/window/detail/GLFWWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window/detail/GLFWWindow.cpp b/src/window/detail/GLFWWindow.cpp index 236ce16d2..88df39408 100644 --- a/src/window/detail/GLFWWindow.cpp +++ b/src/window/detail/GLFWWindow.cpp @@ -188,7 +188,7 @@ public: codepoints.clear(); pressedKeys.clear(); if (waitForRefresh) { - glfwWaitEvents(); + glfwWaitEventsTimeout(0.5); } else { glfwPollEvents(); } From 72a71758463d2347e62583b841f1a451a3f68f6c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 12 Nov 2025 20:09:31 +0300 Subject: [PATCH 05/95] update doc/*/main-page.md --- doc/en/main-page.md | 5 +++-- doc/ru/main-page.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/en/main-page.md b/doc/en/main-page.md index 5eb767f94..30cb106c5 100644 --- a/doc/en/main-page.md +++ b/doc/en/main-page.md @@ -1,8 +1,9 @@ # Documentation -Documentation for 0.30 (in development). +Documentation for 0.30. -[Documentation for 0.29.](https://github.com/MihailRis/voxelcore/blob/release-0.29/doc/ru/main-page.md) +> [!WARNING] +> Version is in development. Proceed to [Documentation for 0.29.](https://github.com/MihailRis/voxelcore/blob/release-0.29/doc/ru/main-page.md) ## Sections diff --git a/doc/ru/main-page.md b/doc/ru/main-page.md index 60d0794d7..e74c29155 100644 --- a/doc/ru/main-page.md +++ b/doc/ru/main-page.md @@ -1,8 +1,9 @@ # Документация -Документация версии 0.30 (в разработке). +Документация версии 0.30. -[Документация 0.29.](https://github.com/MihailRis/voxelcore/blob/release-0.29/doc/ru/main-page.md) +> [!WARNING] +> Версия находится в разработке. Перейдите к [документации для 0.28](https://github.com/MihailRis/voxelcore/blob/release-0.29/doc/ru/main-page.md) ## Разделы From dec1ea7b155a749a0ebc4b5d5fc25f52aef635bd Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 12 Nov 2025 20:11:51 +0300 Subject: [PATCH 06/95] fix documentation links in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30925fefd..8503dd651 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Latest release - [Download](https://github.com/MihailRis/VoxelCore/releases/latest) | [Скачать](https://github.com/MihailRis/VoxelCore/releases/latest) -- [Documentation](https://github.com/MihailRis/VoxelCore/blob/release-0.28/doc/en/main-page.md) | [Документация](https://github.com/MihailRis/VoxelCore/blob/release-0.28/doc/ru/main-page.md) +- [Documentation](https://github.com/MihailRis/VoxelCore/blob/release-0.29/doc/en/main-page.md) | [Документация](https://github.com/MihailRis/VoxelCore/blob/release-0.29/doc/ru/main-page.md) --- From 0d4838facf61dbcacc256eda90ac7d57d2e19db1 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 13 Nov 2025 18:06:47 +0300 Subject: [PATCH 07/95] feat: autoresize (extend/shrink) canvas element --- src/graphics/core/ImageData.cpp | 26 +++++++++++++++++++++++++ src/graphics/core/ImageData.hpp | 1 + src/graphics/core/Texture.cpp | 4 ++-- src/graphics/core/Texture.hpp | 2 +- src/graphics/ui/elements/Canvas.cpp | 18 +++++++++++------ src/graphics/ui/elements/Canvas.hpp | 16 ++++++++------- src/logic/scripting/lua/libs/libgui.cpp | 2 +- 7 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/graphics/core/ImageData.cpp b/src/graphics/core/ImageData.cpp index bd2438323..218428e79 100644 --- a/src/graphics/core/ImageData.cpp +++ b/src/graphics/core/ImageData.cpp @@ -470,6 +470,32 @@ void ImageData::addColor(const ImageData& other, int multiplier) { } } +void ImageData::extend(int newWidth, int newHeight) { + size_t comps; + switch (format) { + case ImageFormat::rgb888: comps = 3; break; + case ImageFormat::rgba8888: comps = 4; break; + default: + throw std::runtime_error("only unsigned byte formats supported"); + } + auto newData = std::make_unique(newWidth * newHeight * comps); + for (uint y = 0; y < newHeight; y++) { + for (uint x = 0; x < newWidth; x++) { + for (size_t c = 0; c < comps; c++) { + if (x < width && y < height) { + newData[(y * newWidth + x) * comps + c] = + data[(y * width + x) * comps + c]; + } else { + newData[(y * newWidth + x) * comps + c] = 0; + } + } + } + } + data = std::move(newData); + width = newWidth; + height = newHeight; +} + void ImageData::addColor(const glm::ivec4& color, int multiplier) { uint comps; switch (format) { diff --git a/src/graphics/core/ImageData.hpp b/src/graphics/core/ImageData.hpp index a1597a986..94987886e 100644 --- a/src/graphics/core/ImageData.hpp +++ b/src/graphics/core/ImageData.hpp @@ -36,6 +36,7 @@ public: void mulColor(const ImageData& other); void addColor(const glm::ivec4& color, int multiplier); void addColor(const ImageData& other, int multiplier); + void extend(int newWidth, int newHeight); std::unique_ptr cropped(int x, int y, int width, int height) const; diff --git a/src/graphics/core/Texture.cpp b/src/graphics/core/Texture.cpp index 04285aa8b..dcd29e372 100644 --- a/src/graphics/core/Texture.cpp +++ b/src/graphics/core/Texture.cpp @@ -44,10 +44,10 @@ void Texture::unbind() const { void Texture::reload(const ImageData& image) { width = image.getWidth(); height = image.getHeight(); - reload(image.getData()); + reload(image.getData(), width, height); } -void Texture::reload(const ubyte* data) { +void Texture::reload(const ubyte* data, uint width, uint height) { glBindTexture(GL_TEXTURE_2D, id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast(data)); diff --git a/src/graphics/core/Texture.hpp b/src/graphics/core/Texture.hpp index 5e67890c7..3c8f1b4cb 100644 --- a/src/graphics/core/Texture.hpp +++ b/src/graphics/core/Texture.hpp @@ -18,7 +18,7 @@ public: virtual void bind() const; virtual void unbind() const; - void reload(const ubyte* data); + void reload(const ubyte* data, uint w, uint h); void reloadPartial(const ImageData& image, uint x, uint y, uint w, uint h); void setNearestFilter(); diff --git a/src/graphics/ui/elements/Canvas.cpp b/src/graphics/ui/elements/Canvas.cpp index 8d48f6a5d..6f43f9449 100644 --- a/src/graphics/ui/elements/Canvas.cpp +++ b/src/graphics/ui/elements/Canvas.cpp @@ -4,11 +4,11 @@ #include "graphics/core/DrawContext.hpp" #include "graphics/core/Texture.hpp" -gui::Canvas::Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize) - : UINode(gui, inSize) { - auto data = std::make_shared(inFormat, inSize.x, inSize.y); - mTexture = Texture::from(data.get()); - mData = std::move(data); +gui::Canvas::Canvas(GUI& gui, ImageFormat format, glm::uvec2 size) + : UINode(gui, size) { + auto data = std::make_shared(format, size.x, size.y); + texture = Texture::from(data.get()); + this->data = std::move(data); } void gui::Canvas::draw(const DrawContext& pctx, const Assets& assets) { @@ -16,6 +16,12 @@ void gui::Canvas::draw(const DrawContext& pctx, const Assets& assets) { auto col = calcColor(); auto batch = pctx.getBatch2D(); - batch->texture(mTexture.get()); + batch->texture(texture.get()); batch->rect(pos.x, pos.y, size.x, size.y, 0, 0, 0, {}, false, false, col); } + +void gui::Canvas::setSize(glm::vec2 size) { + UINode::setSize(size); + data->extend(size.x, size.y); + texture->reload(*data); +} diff --git a/src/graphics/ui/elements/Canvas.hpp b/src/graphics/ui/elements/Canvas.hpp index 0ed70cd1c..63430b8fc 100644 --- a/src/graphics/ui/elements/Canvas.hpp +++ b/src/graphics/ui/elements/Canvas.hpp @@ -9,21 +9,23 @@ class Texture; namespace gui { class Canvas final : public UINode { public: - explicit Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize); + explicit Canvas(GUI& gui, ImageFormat format, glm::uvec2 size); ~Canvas() override = default; void draw(const DrawContext& pctx, const Assets& assets) override; - [[nodiscard]] auto texture() const { - return mTexture; + void setSize(glm::vec2 size) override; + + [[nodiscard]] auto getTexture() const { + return texture; } - [[nodiscard]] auto data() const { - return mData; + [[nodiscard]] auto getData() const { + return data; } private: - std::shared_ptr<::Texture> mTexture; - std::shared_ptr mData; + std::shared_ptr<::Texture> texture; + std::shared_ptr data; }; } diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index cdf65898b..6e7031046 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -380,7 +380,7 @@ static int p_get_region(UINode* node, lua::State* L) { static int p_get_data(UINode* node, lua::State* L) { if (auto canvas = dynamic_cast(node)) { - return lua::newuserdata(L, canvas->texture(), canvas->data()); + return lua::newuserdata(L, canvas->getTexture(), canvas->getData()); } return 0; } From 1fd81da82e3e2cd6c4890050062952bf931820ee Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 14 Nov 2025 00:33:57 +0300 Subject: [PATCH 08/95] add 'onrightclick' uinode event --- src/graphics/ui/elements/Container.cpp | 1 + src/graphics/ui/elements/UINode.cpp | 11 +++++++++++ src/graphics/ui/elements/UINode.hpp | 5 ++++- src/graphics/ui/gui_xml.cpp | 4 ++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/graphics/ui/elements/Container.cpp b/src/graphics/ui/elements/Container.cpp index 8d45c2a1a..5d5375c13 100644 --- a/src/graphics/ui/elements/Container.cpp +++ b/src/graphics/ui/elements/Container.cpp @@ -177,6 +177,7 @@ void Container::add(const std::shared_ptr& node) { parent->setMustRefresh(); parent = parent->getParent(); } + gui.getWindow().setShouldRefresh(); } void Container::add(const std::shared_ptr& node, glm::vec2 pos) { diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 1e8f48d6e..8c3c07655 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -69,6 +69,11 @@ UINode* UINode::listenAction(const onaction& action) { return this; } +UINode* UINode::listenRightClick(const onaction& action) { + rightClickCallbacks.listen(action); + return this; +} + UINode* UINode::listenDoubleClick(const onaction& action) { doubleClickCallbacks.listen(action); return this; @@ -88,6 +93,12 @@ void UINode::click(int, int) { pressed = true; } +void UINode::clicked(Mousecode button) { + if (button == Mousecode::BUTTON_2) { + rightClickCallbacks.notify(gui); + } +} + void UINode::doubleClick(int x, int y) { pressed = true; if (isInside(glm::vec2(x, y))) { diff --git a/src/graphics/ui/elements/UINode.hpp b/src/graphics/ui/elements/UINode.hpp index fc64527fd..6024f841a 100644 --- a/src/graphics/ui/elements/UINode.hpp +++ b/src/graphics/ui/elements/UINode.hpp @@ -121,6 +121,8 @@ namespace gui { vec2supplier sizefunc = nullptr; /// @brief 'onclick' callbacks ActionsSet actions; + /// @brief 'onrightclick' callbacks + ActionsSet rightClickCallbacks; /// @brief 'ondoubleclick' callbacks ActionsSet doubleClickCallbacks; /// @brief 'onfocus' callbacks @@ -188,6 +190,7 @@ namespace gui { int getZIndex() const; virtual UINode* listenAction(const onaction& action); + virtual UINode* listenRightClick(const onaction& action); virtual UINode* listenDoubleClick(const onaction& action); virtual UINode* listenFocus(const onaction& action); virtual UINode* listenDefocus(const onaction& action); @@ -195,7 +198,7 @@ namespace gui { virtual void onFocus(); virtual void doubleClick(int x, int y); virtual void click(int x, int y); - virtual void clicked(Mousecode button) {} + virtual void clicked(Mousecode button); virtual void mouseMove(int x, int y) {}; virtual void mouseRelease(int x, int y); virtual void scrolled(int value); diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 18d0fa4b0..32e59b736 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -181,6 +181,10 @@ static void read_uinode( node.listenAction(onclick); } + if (auto onclick = create_action(reader, element, "onrightclick")) { + node.listenRightClick(onclick); + } + if (auto onfocus = create_action(reader, element, "onfocus")) { node.listenFocus(onfocus); } From 7abe552e3c83d1eb065cabc271dc7ed94afa9249 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 14 Nov 2025 12:33:30 +0300 Subject: [PATCH 09/95] fix UINode enums naming --- src/frontend/hud.cpp | 2 +- src/graphics/ui/elements/Button.cpp | 4 +-- src/graphics/ui/elements/Label.cpp | 12 ++++----- src/graphics/ui/elements/Label.hpp | 2 +- src/graphics/ui/elements/TextBox.cpp | 4 +-- src/graphics/ui/elements/UINode.cpp | 38 ++++++++++++++-------------- src/graphics/ui/elements/UINode.hpp | 26 +++++++++---------- src/graphics/ui/gui_util.cpp | 2 +- src/graphics/ui/gui_xml.cpp | 32 +++++++++++------------ 9 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 5cc161198..6ddc6744c 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -192,7 +192,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) gui.add(contentAccessPanel); auto dplotter = std::make_shared(gui, 350, 250, 2000, 16); - dplotter->setGravity(Gravity::bottom_right); + dplotter->setGravity(Gravity::BOTTOM_RIGHT); dplotter->setInteractive(false); add(HudElement(HudElementMode::PERMANENT, nullptr, dplotter, true)); diff --git a/src/graphics/ui/elements/Button.cpp b/src/graphics/ui/elements/Button.cpp index ef2142eab..bfa96757e 100644 --- a/src/graphics/ui/elements/Button.cpp +++ b/src/graphics/ui/elements/Button.cpp @@ -47,7 +47,7 @@ Button::Button( setScrollable(false); label = std::make_shared