From 9a01b5ad2d2bd37a9fa8c7ce2ebc4bd76e00060c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 10 Mar 2025 23:09:07 +0300 Subject: [PATCH] add splitbox ui element --- src/graphics/ui/elements/SplitBox.cpp | 62 +++++++++++++++++++++++++++ src/graphics/ui/elements/SplitBox.hpp | 18 ++++++++ src/graphics/ui/gui_xml.cpp | 16 +++++++ 3 files changed, 96 insertions(+) create mode 100644 src/graphics/ui/elements/SplitBox.cpp create mode 100644 src/graphics/ui/elements/SplitBox.hpp diff --git a/src/graphics/ui/elements/SplitBox.cpp b/src/graphics/ui/elements/SplitBox.cpp new file mode 100644 index 00000000..1d73e0fd --- /dev/null +++ b/src/graphics/ui/elements/SplitBox.cpp @@ -0,0 +1,62 @@ +#include "SplitBox.hpp" + +using namespace gui; + +SplitBox::SplitBox(const glm::vec2& size, float splitPos, Orientation orientation) + : Container(size), splitPos(splitPos), orientation(orientation) { + setCursor( + orientation == Orientation::vertical ? CursorShape::NS_RESIZE + : CursorShape::EW_RESIZE + ); +} + +void SplitBox::mouseMove(GUI*, int x, int y) { + auto pos = calcPos(); + auto size = getSize(); + + glm::ivec2 cursor(x - pos.x, y - pos.y); + int axis = orientation == Orientation::vertical; + + int v = cursor[axis]; + v = std::max(std::min(static_cast(size[axis]) - 10, v), 10); + float t = v / size[axis]; + splitPos = t; + + refresh(); +} + +void SplitBox::refresh() { + Container::refresh(); + + if (nodes.empty()) { + return; + } + glm::vec2 size = getSize(); + if (nodes.size() == 1) { + auto node = nodes.at(0); + node->setPos(glm::vec2()); + node->setSize(size); + return; + } + auto nodeA = nodes.at(0); + auto nodeB = nodes.at(1); + + nodeA->setPos(glm::vec2()); + if (orientation == Orientation::vertical) { + float splitPos = this->splitPos * size.y; + nodeA->setSize(glm::vec2(size.x, splitPos - splitRadius)); + nodeB->setSize(glm::vec2(size.x, size.y - splitPos - splitRadius)); + nodeB->setPos(glm::vec2(0.0f, splitPos + splitRadius)); + } else { + float splitPos = this->splitPos * size.x; + nodeA->setSize(glm::vec2(splitPos - splitRadius, size.y)); + nodeB->setSize(glm::vec2(size.x - splitPos - splitRadius, size.y)); + nodeB->setPos(glm::vec2(splitPos + splitRadius, 0.0f)); + } +} + +void SplitBox::fullRefresh() { + refresh(); + reposition(); + Container::fullRefresh(); +} diff --git a/src/graphics/ui/elements/SplitBox.hpp b/src/graphics/ui/elements/SplitBox.hpp new file mode 100644 index 00000000..0e9092a8 --- /dev/null +++ b/src/graphics/ui/elements/SplitBox.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Container.hpp" + +namespace gui { + class SplitBox : public Container { + public: + SplitBox(const glm::vec2& size, float splitPos, Orientation orientation); + + virtual void mouseMove(GUI*, int x, int y) override; + virtual void refresh() override; + virtual void fullRefresh() override; + private: + float splitPos; + int splitRadius = 2; + Orientation orientation; + }; +} diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index ee0b7489..bb913f4d 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -7,6 +7,7 @@ #include "elements/Canvas.hpp" #include "elements/CheckBox.hpp" #include "elements/TextBox.hpp" +#include "elements/SplitBox.hpp" #include "elements/TrackBar.hpp" #include "elements/InputBindBox.hpp" #include "elements/InventoryView.hpp" @@ -313,6 +314,20 @@ static std::shared_ptr read_container( return container; } +static std::shared_ptr read_split_box( + UiXmlReader& reader, const xml::xmlelement& element +) { + float splitPos = element.attr("split-pos", "0.5").asFloat(); + Orientation orientation = + element.attr("orientation", "vertical").getText() == "horizontal" + ? Orientation::horizontal + : Orientation::vertical; + auto splitBox = + std::make_shared(glm::vec2(), splitPos, orientation); + read_container_impl(reader, element, *splitBox); + return splitBox; +} + static std::shared_ptr read_panel( UiXmlReader& reader, const xml::xmlelement& element ) { @@ -677,6 +692,7 @@ UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) { add("button", read_button); add("textbox", read_text_box); add("pagebox", read_page_box); + add("splitbox", read_split_box); add("checkbox", read_check_box); add("trackbar", read_track_bar); add("container", read_container);