From 463098aa1e22259385a8a7957851af7cd7c4da37 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 4 Feb 2026 13:10:49 +0300 Subject: [PATCH] add gui.create_frame --- res/scripts/hud.lua | 7 +++++- src/engine/Engine.cpp | 1 + src/graphics/ui/GUI.cpp | 20 +++++++++++++++ src/graphics/ui/GUI.hpp | 6 +++++ src/graphics/ui/elements/Frame.cpp | 33 +++++++++++++++++-------- src/graphics/ui/elements/Frame.hpp | 9 +++++-- src/graphics/ui/gui_xml.cpp | 11 --------- src/logic/scripting/lua/libs/libgui.cpp | 21 ++++++++++++++++ 8 files changed, 84 insertions(+), 24 deletions(-) diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua index a0e363b99..d10d00e1e 100644 --- a/res/scripts/hud.lua +++ b/res/scripts/hud.lua @@ -127,7 +127,12 @@ function on_hud_open() hud.default_hand_controller = update_hand - gui.root.root:add("") + local name = "gui/no_icon" + gui.create_frame(name, {16, 16}) + + local document = Document.new(name) + document.root:add("") + document.root.color = {255, 0, 0, 255} end function on_hud_render() diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 9afe0824a..70bb5dae9 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -305,6 +305,7 @@ void Engine::renderFrame() { screen->draw(time.getDelta()); DrawContext ctx(nullptr, *window, nullptr); + gui->renderFrames(ctx, *assets->getStorage()); gui->draw(ctx, *assets->getStorage()); } diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index d2702bb19..7677ca9f8 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -8,6 +8,7 @@ #include "elements/Label.hpp" #include "elements/Menu.hpp" #include "elements/Panel.hpp" +#include "elements/Frame.hpp" #include "elements/UINode.hpp" #include "engine/Engine.hpp" #include "frontend/UiDocument.hpp" @@ -262,6 +263,21 @@ void GUI::postAct() { } } +void GUI::renderFrames(const DrawContext& pctx, Assets& assets) { + auto ctx = pctx.sub(batch2D.get()); + + auto uishader = assets.get("ui"); + uishader->use(); + uishader->uniformMatrix("u_projview", uicamera->getProjView()); + + batch2D->begin(); + for (auto& [outputTexture, frame] : frames) { + frame->updateOutput(assets); + frame->draw(ctx, assets); + } + batch2D->flush(); +} + void GUI::draw(const DrawContext& pctx, const Assets& assets) { auto ctx = pctx.sub(batch2D.get()); @@ -337,6 +353,10 @@ void GUI::add(std::shared_ptr node) { container->add(std::move(node)); } +void GUI::addFrame(std::shared_ptr frame) { + frames[frame->getOutputTexture()] = std::move(frame); +} + void GUI::remove(UINode* node) noexcept { container->remove(node); } diff --git a/src/graphics/ui/GUI.hpp b/src/graphics/ui/GUI.hpp index a27872d76..b990d93ab 100644 --- a/src/graphics/ui/GUI.hpp +++ b/src/graphics/ui/GUI.hpp @@ -61,6 +61,7 @@ namespace gui { class UINode; class Container; class Menu; + class Frame; /// @brief The main UI controller class GUI { @@ -80,6 +81,7 @@ namespace gui { std::shared_ptr menu; std::queue postRunnables; std::vector> mouseOver; + std::unordered_map> frames; float tooltipTimer = 0.0f; float doubleClickTimer = 0.0f; @@ -112,6 +114,8 @@ namespace gui { /// @param viewport window size void act(float delta, const glm::uvec2& viewport); + void renderFrames(const DrawContext& pctx, Assets& assets); + /// @brief Draw all visible elements on main container /// @param pctx parent graphics context /// @param assets active assets storage @@ -123,6 +127,8 @@ namespace gui { /// @param node UI element void add(std::shared_ptr node); + void addFrame(std::shared_ptr frame); + /// @brief Remove node from the main container void remove(UINode* node) noexcept; diff --git a/src/graphics/ui/elements/Frame.cpp b/src/graphics/ui/elements/Frame.cpp index 2a7af926b..8f6840c9c 100644 --- a/src/graphics/ui/elements/Frame.cpp +++ b/src/graphics/ui/elements/Frame.cpp @@ -5,6 +5,7 @@ #include "graphics/core/Framebuffer.hpp" #include "graphics/core/DrawContext.hpp" #include "graphics/core/Texture.hpp" +#include "frontend/UiDocument.hpp" #include "window/Window.hpp" #include "../GUI.hpp" @@ -12,25 +13,23 @@ using namespace gui; static inline constexpr int MAX_TEXTURE_SIZE = 2048; -gui::Frame::Frame(GUI& gui) : Container(gui, {}), fbo(nullptr) {} +gui::Frame::Frame(GUI& gui, std::string outputTexture) + : Container(gui, {}), + fbo(nullptr), + outputTexture(std::move(outputTexture)) { +} gui::Frame::~Frame() = default; void gui::Frame::draw(const DrawContext& pctx, const Assets& assets) { + if (fbo == nullptr) { + return; + } glm::ivec2 size = getSize(); if (size.x <= 0 || size.y <= 0 || size.x > MAX_TEXTURE_SIZE || size.y > MAX_TEXTURE_SIZE) { return; } - auto& nonConstASsets = const_cast(assets); - if (fbo && (fbo->getWidth() != size.x || fbo->getHeight() != size.y)) { - fbo->resize(size.x, size.y); - nonConstASsets.store(fbo->getSharedTexture(), texture); - } else if (fbo == nullptr) { - fbo = std::make_unique(size.x, size.y, true); - nonConstASsets.store(fbo->getSharedTexture(), texture); - } - // ui uses flipped camera with matrix based on main viewport setPos({0, pctx.getViewport().y - size.y}); @@ -40,3 +39,17 @@ void gui::Frame::draw(const DrawContext& pctx, const Assets& assets) { Container::draw(ctx, assets); ctx.getBatch2D()->flush(); } + +void gui::Frame::updateOutput(Assets& assets) { + if (fbo && (fbo->getWidth() != size.x || fbo->getHeight() != size.y)) { + fbo->resize(size.x, size.y); + assets.store(fbo->getSharedTexture(), outputTexture); + } else if (fbo == nullptr) { + fbo = std::make_unique(size.x, size.y, true); + assets.store(fbo->getSharedTexture(), outputTexture); + } +} + +const std::string& gui::Frame::getOutputTexture() const { + return outputTexture; +} diff --git a/src/graphics/ui/elements/Frame.hpp b/src/graphics/ui/elements/Frame.hpp index 1f4a10c86..fc61b37a2 100644 --- a/src/graphics/ui/elements/Frame.hpp +++ b/src/graphics/ui/elements/Frame.hpp @@ -3,16 +3,21 @@ #include "Container.hpp" class Framebuffer; +class UiDocument; namespace gui { class Frame final : public Container { public: - explicit Frame(GUI& gui); + Frame(GUI& gui, std::string outputTexture); virtual ~Frame(); void draw(const DrawContext& pctx, const Assets& assets) override; + + void updateOutput(Assets& assets); + + const std::string& getOutputTexture() const; private: std::unique_ptr fbo; - std::string texture = "gui/no_icon"; + std::string outputTexture; }; } diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index f34bd9247..0020c28d1 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -8,7 +8,6 @@ #include "elements/Button.hpp" #include "elements/Canvas.hpp" #include "elements/CheckBox.hpp" -#include "elements/Frame.hpp" #include "elements/Image.hpp" #include "elements/InlineFrame.hpp" #include "elements/InputBindBox.hpp" @@ -851,15 +850,6 @@ static std::shared_ptr read_page_box( return menu; } -static std::shared_ptr read_frame( - UiXmlReader& reader, const xml::xmlelement& element -) { - auto& gui = reader.getGUI(); - auto frame = std::make_shared(gui); - read_container_impl(reader, element, *frame, true); - return frame; -} - static std::shared_ptr read_iframe( UiXmlReader& reader, const xml::xmlelement& element ) { @@ -877,7 +867,6 @@ UiXmlReader::UiXmlReader(gui::GUI& gui, scriptenv&& env) contextStack.emplace(""); add("image", read_image); add("canvas", read_canvas); - add("frame", read_frame); add("iframe", read_iframe); add("label", read_label); add("panel", read_panel); diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index fe4cabada..c71eb7e80 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -16,6 +16,7 @@ #include "graphics/ui/elements/TrackBar.hpp" #include "graphics/ui/elements/InlineFrame.hpp" #include "graphics/ui/elements/ModelViewer.hpp" +#include "graphics/ui/elements/Frame.hpp" #include "graphics/ui/gui_util.hpp" #include "graphics/ui/markdown.hpp" #include "graphics/core/Font.hpp" @@ -1149,6 +1150,25 @@ static int l_set_syntax_styles(lua::State* L) { return 0; } +static int l_create_frame(lua::State* L) { + if (engine->isHeadless()) { + return 0; + } + std::string outputTexture = lua::require_string(L, 1); + auto size = lua::tovec2(L, 2); + + auto& gui = engine->getGUI(); + auto frame = std::make_shared(gui, outputTexture); + frame->setSize(std::move(size)); + auto& assets = *engine->getAssets(); + auto document = std::make_shared( + outputTexture, UiDocScript {}, frame, nullptr + ); + assets.store(document, document->getId()); + gui.addFrame(std::move(frame)); + return 0; +} + const luaL_Reg guilib[] = { {"get_viewport", lua::wrap}, {"getattr", lua::wrap}, @@ -1162,6 +1182,7 @@ const luaL_Reg guilib[] = { {"alert", lua::wrap}, {"load_document", lua::wrap}, {"set_syntax_styles", lua::wrap}, + {"create_frame", lua::wrap}, {"__reindex", lua::wrap}, {nullptr, nullptr} };