From 85f7febd302a2ad3e0fa5b7e935e20c2fae178f1 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 20 Apr 2024 21:48:26 +0300 Subject: [PATCH] graphics/ui/elements/containers deleted --- src/frontend/InventoryView.cpp | 1 - src/frontend/InventoryView.h | 2 +- src/frontend/UiDocument.cpp | 1 - src/frontend/hud.cpp | 2 +- src/frontend/menu/menu.cpp | 2 +- src/frontend/screens.cpp | 2 +- src/graphics/ui/GUI.cpp | 2 +- src/graphics/ui/elements/Container.cpp | 152 +++++++++++ src/graphics/ui/elements/Container.hpp | 39 +++ src/graphics/ui/elements/Menu.cpp | 93 +++++++ src/graphics/ui/elements/Menu.hpp | 60 +++++ src/graphics/ui/elements/Panel.cpp | 99 +++++++ src/graphics/ui/elements/Panel.hpp | 40 +++ src/graphics/ui/elements/UINode.cpp | 2 +- src/graphics/ui/elements/commons.hpp | 20 ++ src/graphics/ui/elements/containers.cpp | 342 ------------------------ src/graphics/ui/elements/containers.h | 142 ---------- src/graphics/ui/elements/controls.h | 2 +- src/graphics/ui/gui_util.cpp | 2 +- src/graphics/ui/gui_xml.cpp | 2 +- src/logic/scripting/lua/libgui.cpp | 2 + 21 files changed, 514 insertions(+), 495 deletions(-) create mode 100644 src/graphics/ui/elements/Container.cpp create mode 100644 src/graphics/ui/elements/Container.hpp create mode 100644 src/graphics/ui/elements/Menu.cpp create mode 100644 src/graphics/ui/elements/Menu.hpp create mode 100644 src/graphics/ui/elements/Panel.cpp create mode 100644 src/graphics/ui/elements/Panel.hpp create mode 100644 src/graphics/ui/elements/commons.hpp delete mode 100644 src/graphics/ui/elements/containers.cpp delete mode 100644 src/graphics/ui/elements/containers.h diff --git a/src/frontend/InventoryView.cpp b/src/frontend/InventoryView.cpp index e45bf0a7..99d7722f 100644 --- a/src/frontend/InventoryView.cpp +++ b/src/frontend/InventoryView.cpp @@ -11,7 +11,6 @@ #include "../graphics/core/GfxContext.h" #include "../graphics/core/Shader.h" #include "../graphics/render/BlocksPreview.h" -#include "../graphics/ui/elements/containers.h" #include "../graphics/ui/elements/controls.h" #include "../items/Inventories.h" #include "../items/Inventory.h" diff --git a/src/frontend/InventoryView.h b/src/frontend/InventoryView.h index fd82d175..8cc76a03 100644 --- a/src/frontend/InventoryView.h +++ b/src/frontend/InventoryView.h @@ -6,7 +6,7 @@ #include #include "../graphics/ui/elements/UINode.h" -#include "../graphics/ui/elements/containers.h" +#include "../graphics/ui/elements/Container.hpp" #include "../graphics/ui/elements/controls.h" #include "../items/ItemStack.h" #include "../typedefs.h" diff --git a/src/frontend/UiDocument.cpp b/src/frontend/UiDocument.cpp index 4ebfcbd2..f31d1706 100644 --- a/src/frontend/UiDocument.cpp +++ b/src/frontend/UiDocument.cpp @@ -1,7 +1,6 @@ #include "UiDocument.h" #include "../files/files.h" -#include "../graphics/ui/elements/containers.h" #include "../graphics/ui/elements/UINode.h" #include "../graphics/ui/gui_xml.h" #include "../logic/scripting/scripting.h" diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 9f379df9..d5c14111 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -15,9 +15,9 @@ #include "../graphics/core/Texture.h" #include "../graphics/render/BlocksPreview.h" #include "../graphics/render/WorldRenderer.h" -#include "../graphics/ui/elements/containers.h" #include "../graphics/ui/elements/controls.h" #include "../graphics/ui/elements/UINode.h" +#include "../graphics/ui/elements/Menu.hpp" #include "../graphics/ui/elements/Plotter.hpp" #include "../graphics/ui/GUI.h" #include "../items/Inventories.h" diff --git a/src/frontend/menu/menu.cpp b/src/frontend/menu/menu.cpp index ab3912e0..5c11b629 100644 --- a/src/frontend/menu/menu.cpp +++ b/src/frontend/menu/menu.cpp @@ -11,7 +11,7 @@ #include "../../interfaces/Task.h" #include "../../graphics/ui/GUI.h" #include "../../graphics/ui/gui_util.h" -#include "../../graphics/ui/elements/containers.h" +#include "../../graphics/ui/elements/Menu.hpp" #include "../../graphics/ui/elements/controls.h" #include "../screens.h" #include "../UiDocument.h" diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 87dfa75c..5f3cbee3 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -10,7 +10,7 @@ #include "../graphics/core/Shader.h" #include "../graphics/core/TextureAnimation.h" #include "../graphics/render/WorldRenderer.h" -#include "../graphics/ui/elements/containers.h" +#include "../graphics/ui/elements/Menu.hpp" #include "../graphics/ui/GUI.h" #include "../logic/ChunksController.h" #include "../logic/LevelController.h" diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index b8529be5..4799d344 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -1,6 +1,6 @@ #include "GUI.h" #include "elements/UINode.h" -#include "elements/containers.h" +#include "elements/Menu.hpp" #include #include diff --git a/src/graphics/ui/elements/Container.cpp b/src/graphics/ui/elements/Container.cpp new file mode 100644 index 00000000..3eb5fd60 --- /dev/null +++ b/src/graphics/ui/elements/Container.cpp @@ -0,0 +1,152 @@ +#include "Container.hpp" + +#include "../../core/GfxContext.h" +#include "../../core/Batch2D.h" + +using namespace gui; + +Container::Container(glm::vec2 size) : UINode(size) { + actualLength = size.y; + setColor(glm::vec4()); +} + +std::shared_ptr Container::getAt(glm::vec2 pos, std::shared_ptr self) { + if (!interactive) { + return nullptr; + } + if (!isInside(pos)) return nullptr; + + for (int i = nodes.size()-1; i >= 0; i--) { + auto& node = nodes[i]; + if (!node->isVisible()) + continue; + auto hover = node->getAt(pos, node); + if (hover != nullptr) { + return hover; + } + } + return UINode::getAt(pos, self); +} + +void Container::act(float delta) { + for (auto node : nodes) { + if (node->isVisible()) { + node->act(delta); + } + } + for (IntervalEvent& event : intervalEvents) { + event.timer += delta; + if (event.timer > event.interval) { + event.callback(); + event.timer = fmod(event.timer, event.interval); + if (event.repeat > 0) { + event.repeat--; + } + } + } + intervalEvents.erase(std::remove_if( + intervalEvents.begin(), intervalEvents.end(), + [](const IntervalEvent& event) { + return event.repeat == 0; + } + ), intervalEvents.end()); +} + +void Container::scrolled(int value) { + int diff = (actualLength-getSize().y); + if (scroll < 0 && diff <= 0) { + scroll = 0; + } + if (diff > 0 && scrollable) { + scroll += value * scrollStep; + if (scroll > 0) + scroll = 0; + if (-scroll > diff) { + scroll = -diff; + } + } else if (parent) { + parent->scrolled(value); + } +} + +void Container::setScrollable(bool flag) { + scrollable = flag; +} + +void Container::draw(const GfxContext* pctx, Assets* assets) { + glm::vec2 pos = calcPos(); + glm::vec2 size = getSize(); + drawBackground(pctx, assets); + + auto batch = pctx->getBatch2D(); + batch->texture(nullptr); + batch->flush(); + { + GfxContext ctx = pctx->sub(); + ctx.setScissors(glm::vec4(pos.x, pos.y, size.x, size.y)); + for (auto node : nodes) { + if (node->isVisible()) + node->draw(pctx, assets); + } + } +} + +void Container::drawBackground(const GfxContext* pctx, Assets* assets) { + glm::vec4 color = isPressed() ? pressedColor : (hover ? hoverColor : this->color); + if (color.a <= 0.001f) + return; + glm::vec2 pos = calcPos(); + + auto batch = pctx->getBatch2D(); + batch->texture(nullptr); + batch->setColor(color); + batch->rect(pos.x, pos.y, size.x, size.y); +} + +void Container::add(std::shared_ptr node) { + nodes.push_back(node); + node->setParent(this); + node->reposition(); + refresh(); +} + +void Container::add(std::shared_ptr node, glm::vec2 pos) { + node->setPos(pos); + add(node); +} + +void Container::remove(std::shared_ptr selected) { + selected->setParent(nullptr); + nodes.erase(std::remove_if(nodes.begin(), nodes.end(), + [selected](const std::shared_ptr node) { + return node == selected; + } + ), nodes.end()); + refresh(); +} + +void Container::listenInterval(float interval, ontimeout callback, int repeat) { + intervalEvents.push_back({callback, interval, 0.0f, repeat}); +} + +void Container::setSize(glm::vec2 size) { + if (size == getSize()) { + refresh(); + return; + } + UINode::setSize(size); + refresh(); + for (auto& node : nodes) { + node->reposition(); + } +} + +void Container::refresh() { + std::stable_sort(nodes.begin(), nodes.end(), [](const auto& a, const auto& b) { + return a->getZIndex() < b->getZIndex(); + }); +} + +const std::vector>& Container::getNodes() const { + return nodes; +} diff --git a/src/graphics/ui/elements/Container.hpp b/src/graphics/ui/elements/Container.hpp new file mode 100644 index 00000000..f23c2e2e --- /dev/null +++ b/src/graphics/ui/elements/Container.hpp @@ -0,0 +1,39 @@ +#ifndef GRAPHICS_UI_ELEMENTS_CONTAINER_HPP_ +#define GRAPHICS_UI_ELEMENTS_CONTAINER_HPP_ + +#include "UINode.h" +#include "commons.hpp" + +#include + +namespace gui { + class Container : public UINode { + protected: + std::vector> nodes; + std::vector intervalEvents; + int scroll = 0; + int scrollStep = 40; + int actualLength = 0; + bool scrollable = true; + public: + Container(glm::vec2 size); + + virtual void act(float delta) override; + virtual void drawBackground(const GfxContext* pctx, Assets* assets); + virtual void draw(const GfxContext* pctx, Assets* assets) override; + virtual std::shared_ptr getAt(glm::vec2 pos, std::shared_ptr self) override; + virtual void add(std::shared_ptr node); + virtual void add(std::shared_ptr node, glm::vec2 pos); + virtual void remove(std::shared_ptr node); + virtual void scrolled(int value) override; + virtual void setScrollable(bool flag); + void listenInterval(float interval, ontimeout callback, int repeat=-1); + virtual glm::vec2 contentOffset() override {return glm::vec2(0.0f, scroll);}; + virtual void setSize(glm::vec2 size) override; + virtual void refresh() override; + + const std::vector>& getNodes() const; + }; +} + +#endif // GRAPHICS_UI_ELEMENTS_CONTAINER_HPP_ diff --git a/src/graphics/ui/elements/Menu.cpp b/src/graphics/ui/elements/Menu.cpp new file mode 100644 index 00000000..05fa1aaf --- /dev/null +++ b/src/graphics/ui/elements/Menu.cpp @@ -0,0 +1,93 @@ +#include "Menu.hpp" + +#include + +using namespace gui; + +Menu::Menu() : Container(glm::vec2(1)){ +} + +bool Menu::has(const std::string& name) { + return pages.find(name) != pages.end() || + pageSuppliers.find(name) != pageSuppliers.end(); +} + +void Menu::addPage(std::string name, std::shared_ptr panel) { + pages[name] = Page{name, panel}; +} + +void Menu::addSupplier(std::string name, supplier> pageSupplier) { + pageSuppliers[name] = pageSupplier; +} + +std::shared_ptr Menu::fetchPage(const std::string& name) { + auto found = pages.find(name); + if (found == pages.end()) { + auto supplier = pageSuppliers.find(name); + if (supplier == pageSuppliers.end()) { + if (pagesLoader) { + return pagesLoader(name); + } + return nullptr; + } else { + return supplier->second(); + // supplied pages caching is not implemented + } + } else { + return found->second.panel; + } +} + +void Menu::setPage(std::string name, bool history) { + Page page {name, fetchPage(name)}; + if (page.panel == nullptr) { + throw std::runtime_error("no page found"); + } + setPage(page, history); +} + +void Menu::setPage(Page page, bool history) { + if (current.panel) { + Container::remove(current.panel); + } + if (history) { + pageStack.push(current); + } + current = page; + Container::add(current.panel); + setSize(current.panel->getSize()); +} + +void Menu::back() { + if (pageStack.empty()) + return; + Page page = pageStack.top(); + pageStack.pop(); + + auto updated = fetchPage(page.name); + if (updated) { + page.panel = updated; + } + + setPage(page, false); +} + +void Menu::setPageLoader(page_loader_func loader) { + pagesLoader = loader; +} + +Page& Menu::getCurrent() { + return current; +} + +void Menu::clearHistory() { + pageStack = std::stack(); +} + +void Menu::reset() { + clearHistory(); + if (current.panel) { + Container::remove(current.panel); + current = Page{"", nullptr}; + } +} diff --git a/src/graphics/ui/elements/Menu.hpp b/src/graphics/ui/elements/Menu.hpp new file mode 100644 index 00000000..d0af54a8 --- /dev/null +++ b/src/graphics/ui/elements/Menu.hpp @@ -0,0 +1,60 @@ +#ifndef GRAPHICS_UI_ELEMENTS_MENU_HPP_ +#define GRAPHICS_UI_ELEMENTS_MENU_HPP_ + +#include "Container.hpp" + +#include + +namespace gui { + struct Page { + std::string name; + std::shared_ptr panel = nullptr; + }; + + using page_loader_func = std::function(const std::string& name)>; + + class Menu : public Container { + protected: + std::unordered_map pages; + std::stack pageStack; + Page current; + std::unordered_map>> pageSuppliers; + page_loader_func pagesLoader = nullptr; + public: + Menu(); + + /// @brief Check menu have page or page supplier + /// @param name page name + bool has(const std::string& name); + + /// @brief Set current page to specified one. + /// @param name page or page supplier name + /// @param history previous page will not be saved in history if false + void setPage(std::string name, bool history=true); + void setPage(Page page, bool history=true); + void addPage(std::string name, std::shared_ptr panel); + std::shared_ptr fetchPage(const std::string& name); + + /// @brief Add page supplier used if page is not found + /// @param name page name + /// @param pageSupplier page supplier function + void addSupplier(std::string name, supplier> pageSupplier); + + /// @brief Page loader is called if accessed page is not found + void setPageLoader(page_loader_func loader); + + /// @brief Set page to previous saved in history + void back(); + + /// @brief Clear pages history + void clearHistory(); + + /// @brief Clear history and remove and set page to null + void reset(); + + /// @brief Get current page + Page& getCurrent(); + }; +} + +#endif // GRAPHICS_UI_ELEMENTS_MENU_HPP_ diff --git a/src/graphics/ui/elements/Panel.cpp b/src/graphics/ui/elements/Panel.cpp new file mode 100644 index 00000000..2cf1c432 --- /dev/null +++ b/src/graphics/ui/elements/Panel.cpp @@ -0,0 +1,99 @@ +#include "Panel.hpp" + +using namespace gui; + +Panel::Panel(glm::vec2 size, glm::vec4 padding, float interval) + : Container(size), + padding(padding), + interval(interval) +{ + setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f)); +} + +Panel::~Panel() { +} + +void Panel::setMaxLength(int value) { + maxLength = value; +} + +int Panel::getMaxLength() const { + return maxLength; +} + +void Panel::setPadding(glm::vec4 padding) { + this->padding = padding; + refresh(); +} + +glm::vec4 Panel::getPadding() const { + return padding; +} + +void Panel::cropToContent() { + if (maxLength > 0.0f) { + setSize(glm::vec2(getSize().x, glm::min(maxLength, actualLength))); + } else { + setSize(glm::vec2(getSize().x, actualLength)); + } +} + +void Panel::fullRefresh() { + refresh(); + cropToContent(); + Container::fullRefresh(); +} + +void Panel::add(std::shared_ptr node) { + node->setResizing(true); + Container::add(node); + fullRefresh(); +} + +void Panel::refresh() { + UINode::refresh(); + float x = padding.x; + float y = padding.y; + glm::vec2 size = getSize(); + if (orientation == Orientation::vertical) { + float maxw = size.x; + for (auto& node : nodes) { + glm::vec2 nodesize = node->getSize(); + const glm::vec4 margin = node->getMargin(); + y += margin.y; + + float ex = x + margin.x; + node->setPos(glm::vec2(ex, y)); + y += nodesize.y + margin.w + interval; + + float width = size.x - padding.x - padding.z - margin.x - margin.z; + if (node->isResizing()) { + node->setSize(glm::vec2(width, nodesize.y)); + } + node->refresh(); + maxw = fmax(maxw, ex+node->getSize().x+margin.z+padding.z); + } + actualLength = y + padding.w; + } else { + float maxh = size.y; + for (auto& node : nodes) { + glm::vec2 nodesize = node->getSize(); + const glm::vec4 margin = node->getMargin(); + x += margin.x; + node->setPos(glm::vec2(x, y+margin.y)); + x += nodesize.x + margin.z + interval; + + node->refresh(); + maxh = fmax(maxh, y+margin.y+node->getSize().y+margin.w+padding.w); + } + actualLength = size.y; + } +} + +void Panel::setOrientation(Orientation orientation) { + this->orientation = orientation; +} + +Orientation Panel::getOrientation() const { + return orientation; +} diff --git a/src/graphics/ui/elements/Panel.hpp b/src/graphics/ui/elements/Panel.hpp new file mode 100644 index 00000000..cde3b12a --- /dev/null +++ b/src/graphics/ui/elements/Panel.hpp @@ -0,0 +1,40 @@ +#ifndef GRAPHICS_UI_ELEMENTS_PANEL_HPP_ +#define GRAPHICS_UI_ELEMENTS_PANEL_HPP_ + +#include "commons.hpp" +#include "Container.hpp" + +namespace gui { + class Panel : public Container { + protected: + Orientation orientation = Orientation::vertical; + glm::vec4 padding {2.0f}; + float interval = 2.0f; + int maxLength = 0; + public: + Panel( + glm::vec2 size, + glm::vec4 padding=glm::vec4(2.0f), + float interval=2.0f + ); + virtual ~Panel(); + + virtual void cropToContent(); + + virtual void setOrientation(Orientation orientation); + Orientation getOrientation() const; + + virtual void add(std::shared_ptr node) override; + + virtual void refresh() override; + virtual void fullRefresh() override; + + virtual void setMaxLength(int value); + int getMaxLength() const; + + virtual void setPadding(glm::vec4 padding); + glm::vec4 getPadding() const; + }; +} + +#endif // GRAPHICS_UI_ELEMENTS_PANEL_HPP_ diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 3ea8501b..c3a7501c 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -1,6 +1,6 @@ #include "UINode.h" -#include "containers.h" +#include "Container.hpp" #include "../../core/Batch2D.h" using gui::UINode; diff --git a/src/graphics/ui/elements/commons.hpp b/src/graphics/ui/elements/commons.hpp new file mode 100644 index 00000000..cdad6354 --- /dev/null +++ b/src/graphics/ui/elements/commons.hpp @@ -0,0 +1,20 @@ +#ifndef GRAPHICS_UI_ELEMENTS_COMMONS_HPP_ +#define GRAPHICS_UI_ELEMENTS_COMMONS_HPP_ + +#include + +namespace gui { + enum class Orientation { vertical, horizontal }; + + using ontimeout = std::function; + + struct IntervalEvent { + ontimeout callback; + float interval; + float timer; + // -1 - infinity, 1 - one time event + int repeat; + }; +} + +#endif // GRAPHICS_UI_ELEMENTS_COMMONS_HPP_ diff --git a/src/graphics/ui/elements/containers.cpp b/src/graphics/ui/elements/containers.cpp deleted file mode 100644 index edb4245d..00000000 --- a/src/graphics/ui/elements/containers.cpp +++ /dev/null @@ -1,342 +0,0 @@ -#include "containers.h" - -#include -#include - -#include "../../../window/Window.h" -#include "../../../assets/Assets.h" -#include "../../core/Batch2D.h" -#include "../../core/GfxContext.h" - -using namespace gui; - -Container::Container(glm::vec2 size) : UINode(size) { - actualLength = size.y; - setColor(glm::vec4()); -} - -std::shared_ptr Container::getAt(glm::vec2 pos, std::shared_ptr self) { - if (!interactive) { - return nullptr; - } - if (!isInside(pos)) return nullptr; - - for (int i = nodes.size()-1; i >= 0; i--) { - auto& node = nodes[i]; - if (!node->isVisible()) - continue; - auto hover = node->getAt(pos, node); - if (hover != nullptr) { - return hover; - } - } - return UINode::getAt(pos, self); -} - -void Container::act(float delta) { - for (auto node : nodes) { - if (node->isVisible()) { - node->act(delta); - } - } - for (IntervalEvent& event : intervalEvents) { - event.timer += delta; - if (event.timer > event.interval) { - event.callback(); - event.timer = fmod(event.timer, event.interval); - if (event.repeat > 0) { - event.repeat--; - } - } - } - intervalEvents.erase(std::remove_if( - intervalEvents.begin(), intervalEvents.end(), - [](const IntervalEvent& event) { - return event.repeat == 0; - } - ), intervalEvents.end()); -} - -void Container::scrolled(int value) { - int diff = (actualLength-getSize().y); - if (scroll < 0 && diff <= 0) { - scroll = 0; - } - if (diff > 0 && scrollable) { - scroll += value * scrollStep; - if (scroll > 0) - scroll = 0; - if (-scroll > diff) { - scroll = -diff; - } - } else if (parent) { - parent->scrolled(value); - } -} - -void Container::setScrollable(bool flag) { - scrollable = flag; -} - -void Container::draw(const GfxContext* pctx, Assets* assets) { - glm::vec2 pos = calcPos(); - glm::vec2 size = getSize(); - drawBackground(pctx, assets); - - auto batch = pctx->getBatch2D(); - batch->texture(nullptr); - batch->flush(); - { - GfxContext ctx = pctx->sub(); - ctx.setScissors(glm::vec4(pos.x, pos.y, size.x, size.y)); - for (auto node : nodes) { - if (node->isVisible()) - node->draw(pctx, assets); - } - } -} - -void Container::drawBackground(const GfxContext* pctx, Assets* assets) { - glm::vec4 color = isPressed() ? pressedColor : (hover ? hoverColor : this->color); - if (color.a <= 0.001f) - return; - glm::vec2 pos = calcPos(); - - auto batch = pctx->getBatch2D(); - batch->texture(nullptr); - batch->setColor(color); - batch->rect(pos.x, pos.y, size.x, size.y); -} - -void Container::add(std::shared_ptr node) { - nodes.push_back(node); - node->setParent(this); - node->reposition(); - refresh(); -} - -void Container::add(std::shared_ptr node, glm::vec2 pos) { - node->setPos(pos); - add(node); -} - -void Container::remove(std::shared_ptr selected) { - selected->setParent(nullptr); - nodes.erase(std::remove_if(nodes.begin(), nodes.end(), - [selected](const std::shared_ptr node) { - return node == selected; - } - ), nodes.end()); - refresh(); -} - -void Container::listenInterval(float interval, ontimeout callback, int repeat) { - intervalEvents.push_back({callback, interval, 0.0f, repeat}); -} - -void Container::setSize(glm::vec2 size) { - if (size == getSize()) { - refresh(); - return; - } - UINode::setSize(size); - refresh(); - for (auto& node : nodes) { - node->reposition(); - } -} - -void Container::refresh() { - std::stable_sort(nodes.begin(), nodes.end(), [](const auto& a, const auto& b) { - return a->getZIndex() < b->getZIndex(); - }); -} - -const std::vector>& Container::getNodes() const { - return nodes; -} - -Panel::Panel(glm::vec2 size, glm::vec4 padding, float interval) - : Container(size), - padding(padding), - interval(interval) -{ - setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f)); -} - -Panel::~Panel() { -} - -void Panel::setMaxLength(int value) { - maxLength = value; -} - -int Panel::getMaxLength() const { - return maxLength; -} - -void Panel::setPadding(glm::vec4 padding) { - this->padding = padding; - refresh(); -} - -glm::vec4 Panel::getPadding() const { - return padding; -} - -void Panel::cropToContent() { - if (maxLength > 0.0f) { - setSize(glm::vec2(getSize().x, glm::min(maxLength, actualLength))); - } else { - setSize(glm::vec2(getSize().x, actualLength)); - } -} - -void Panel::fullRefresh() { - refresh(); - cropToContent(); - Container::fullRefresh(); -} - -void Panel::add(std::shared_ptr node) { - node->setResizing(true); - Container::add(node); - fullRefresh(); -} - -void Panel::refresh() { - UINode::refresh(); - float x = padding.x; - float y = padding.y; - glm::vec2 size = getSize(); - if (orientation == Orientation::vertical) { - float maxw = size.x; - for (auto& node : nodes) { - glm::vec2 nodesize = node->getSize(); - const glm::vec4 margin = node->getMargin(); - y += margin.y; - - float ex = x + margin.x; - node->setPos(glm::vec2(ex, y)); - y += nodesize.y + margin.w + interval; - - float width = size.x - padding.x - padding.z - margin.x - margin.z; - if (node->isResizing()) { - node->setSize(glm::vec2(width, nodesize.y)); - } - node->refresh(); - maxw = fmax(maxw, ex+node->getSize().x+margin.z+padding.z); - } - actualLength = y + padding.w; - } else { - float maxh = size.y; - for (auto& node : nodes) { - glm::vec2 nodesize = node->getSize(); - const glm::vec4 margin = node->getMargin(); - x += margin.x; - node->setPos(glm::vec2(x, y+margin.y)); - x += nodesize.x + margin.z + interval; - - node->refresh(); - maxh = fmax(maxh, y+margin.y+node->getSize().y+margin.w+padding.w); - } - actualLength = size.y; - } -} - -void Panel::setOrientation(Orientation orientation) { - this->orientation = orientation; -} - -Orientation Panel::getOrientation() const { - return orientation; -} - -Menu::Menu() : Container(glm::vec2(1)){ -} - -bool Menu::has(const std::string& name) { - return pages.find(name) != pages.end() || - pageSuppliers.find(name) != pageSuppliers.end(); -} - -void Menu::addPage(std::string name, std::shared_ptr panel) { - pages[name] = Page{name, panel}; -} - -void Menu::addSupplier(std::string name, supplier> pageSupplier) { - pageSuppliers[name] = pageSupplier; -} - -std::shared_ptr Menu::fetchPage(const std::string& name) { - auto found = pages.find(name); - if (found == pages.end()) { - auto supplier = pageSuppliers.find(name); - if (supplier == pageSuppliers.end()) { - if (pagesLoader) { - return pagesLoader(name); - } - return nullptr; - } else { - return supplier->second(); - // supplied pages caching is not implemented - } - } else { - return found->second.panel; - } -} - - -void Menu::setPage(std::string name, bool history) { - Page page {name, fetchPage(name)}; - if (page.panel == nullptr) { - throw std::runtime_error("no page found"); - } - setPage(page, history); -} - -void Menu::setPage(Page page, bool history) { - if (current.panel) { - Container::remove(current.panel); - } - if (history) { - pageStack.push(current); - } - current = page; - Container::add(current.panel); - setSize(current.panel->getSize()); -} - -void Menu::back() { - if (pageStack.empty()) - return; - Page page = pageStack.top(); - pageStack.pop(); - - auto updated = fetchPage(page.name); - if (updated) { - page.panel = updated; - } - - setPage(page, false); -} - -void Menu::setPageLoader(page_loader_func loader) { - pagesLoader = loader; -} - -Page& Menu::getCurrent() { - return current; -} - -void Menu::clearHistory() { - pageStack = std::stack(); -} - -void Menu::reset() { - clearHistory(); - if (current.panel) { - Container::remove(current.panel); - current = Page{"", nullptr}; - } -} diff --git a/src/graphics/ui/elements/containers.h b/src/graphics/ui/elements/containers.h deleted file mode 100644 index 09496b0b..00000000 --- a/src/graphics/ui/elements/containers.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef GRAPHICS_UI_ELEMENTS_CONTAINERS_H_ -#define GRAPHICS_UI_ELEMENTS_CONTAINERS_H_ - -#include "UINode.h" -#include "../../../delegates.h" - -#include -#include -#include -#include -#include - -class Batch2D; -class Assets; - -namespace gui { - using ontimeout = std::function; - - struct IntervalEvent { - ontimeout callback; - float interval; - float timer; - // -1 - infinity, 1 - one time event - int repeat; - }; - - enum class Orientation { vertical, horizontal }; - - class Container : public UINode { - protected: - std::vector> nodes; - std::vector intervalEvents; - int scroll = 0; - int scrollStep = 40; - int actualLength = 0; - bool scrollable = true; - public: - Container(glm::vec2 size); - - virtual void act(float delta) override; - virtual void drawBackground(const GfxContext* pctx, Assets* assets); - virtual void draw(const GfxContext* pctx, Assets* assets) override; - virtual std::shared_ptr getAt(glm::vec2 pos, std::shared_ptr self) override; - virtual void add(std::shared_ptr node); - virtual void add(std::shared_ptr node, glm::vec2 pos); - virtual void remove(std::shared_ptr node); - virtual void scrolled(int value) override; - virtual void setScrollable(bool flag); - void listenInterval(float interval, ontimeout callback, int repeat=-1); - virtual glm::vec2 contentOffset() override {return glm::vec2(0.0f, scroll);}; - virtual void setSize(glm::vec2 size) override; - virtual void refresh() override; - - const std::vector>& getNodes() const; - }; - - class Panel : public Container { - protected: - Orientation orientation = Orientation::vertical; - glm::vec4 padding {2.0f}; - float interval = 2.0f; - int maxLength = 0; - public: - Panel( - glm::vec2 size, - glm::vec4 padding=glm::vec4(2.0f), - float interval=2.0f - ); - virtual ~Panel(); - - virtual void cropToContent(); - - virtual void setOrientation(Orientation orientation); - Orientation getOrientation() const; - - virtual void add(std::shared_ptr node) override; - - virtual void refresh() override; - virtual void fullRefresh() override; - - virtual void setMaxLength(int value); - int getMaxLength() const; - - virtual void setPadding(glm::vec4 padding); - glm::vec4 getPadding() const; - }; - - struct Page { - std::string name; - std::shared_ptr panel = nullptr; - - ~Page() { - panel = nullptr; - } - }; - - using page_loader_func = std::function(const std::string& name)>; - - class Menu : public Container { - protected: - std::unordered_map pages; - std::stack pageStack; - Page current; - std::unordered_map>> pageSuppliers; - page_loader_func pagesLoader = nullptr; - public: - Menu(); - - /// @brief Check menu have page or page supplier - /// @param name page name - bool has(const std::string& name); - - /// @brief Set current page to specified one. - /// @param name page or page supplier name - /// @param history previous page will not be saved in history if false - void setPage(std::string name, bool history=true); - void setPage(Page page, bool history=true); - void addPage(std::string name, std::shared_ptr panel); - std::shared_ptr fetchPage(const std::string& name); - - /// @brief Add page supplier used if page is not found - /// @param name page name - /// @param pageSupplier page supplier function - void addSupplier(std::string name, supplier> pageSupplier); - - /// @brief Page loader is called if accessed page is not found - void setPageLoader(page_loader_func loader); - - /// @brief Set page to previous saved in history - void back(); - - /// @brief Clear pages history - void clearHistory(); - - /// @brief Clear history and remove and set page to null - void reset(); - - /// @brief Get current page - Page& getCurrent(); - }; -} -#endif // GRAPHICS_UI_ELEMENTS_CONTAINERS_H_ diff --git a/src/graphics/ui/elements/controls.h b/src/graphics/ui/elements/controls.h index 1e46a786..a0c8b9ef 100644 --- a/src/graphics/ui/elements/controls.h +++ b/src/graphics/ui/elements/controls.h @@ -11,7 +11,7 @@ #include "../GUI.h" #include "UINode.h" -#include "containers.h" +#include "Panel.hpp" #include "../../../window/input.h" #include "../../../delegates.h" #include "../../../typedefs.h" diff --git a/src/graphics/ui/gui_util.cpp b/src/graphics/ui/gui_util.cpp index 25a41a37..cdbf4b2b 100644 --- a/src/graphics/ui/gui_util.cpp +++ b/src/graphics/ui/gui_util.cpp @@ -1,6 +1,6 @@ #include "gui_util.h" #include "elements/controls.h" -#include "elements/containers.h" +#include "elements/Menu.hpp" #include "gui_xml.h" #include diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index f0b0df9f..cd3c61e5 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -3,7 +3,7 @@ #include #include -#include "elements/containers.h" +#include "elements/Panel.hpp" #include "elements/controls.h" #include "../../frontend/locale/langs.h" diff --git a/src/logic/scripting/lua/libgui.cpp b/src/logic/scripting/lua/libgui.cpp index 6326db85..05950450 100644 --- a/src/logic/scripting/lua/libgui.cpp +++ b/src/logic/scripting/lua/libgui.cpp @@ -10,6 +10,8 @@ #include "../../../assets/Assets.h" #include "../../../graphics/ui/gui_util.h" #include "../../../graphics/ui/elements/UINode.h" +#include "../../../graphics/ui/elements/Panel.hpp" +#include "../../../graphics/ui/elements/Menu.hpp" #include "../../../graphics/ui/elements/controls.h" #include "../../../frontend/UiDocument.h" #include "../../../frontend/locale/langs.h"