From be807535f5aa1447c203462e77792a599f10f90c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 23 Nov 2023 13:36:24 +0300 Subject: [PATCH] Panels scrolling, scissors test fix --- src/frontend/gui/GUI.cpp | 6 ++++- src/frontend/gui/UINode.cpp | 13 +++++----- src/frontend/gui/UINode.h | 2 ++ src/frontend/gui/controls.cpp | 4 ++++ src/frontend/gui/panels.cpp | 45 +++++++++++++++++++++++++++++++---- src/frontend/gui/panels.h | 10 ++++++++ src/frontend/menu.cpp | 9 +++++-- src/window/Events.cpp | 2 ++ src/window/Events.h | 1 + src/window/Window.cpp | 20 ++++++++++++++-- 10 files changed, 97 insertions(+), 15 deletions(-) diff --git a/src/frontend/gui/GUI.cpp b/src/frontend/gui/GUI.cpp index b0831077..c1b67b77 100644 --- a/src/frontend/gui/GUI.cpp +++ b/src/frontend/gui/GUI.cpp @@ -49,6 +49,9 @@ void GUI::act(float delta) { } if (hover) { hover->hover(true); + if (Events::scroll) { + hover->scrolled(Events::scroll); + } } this->hover = hover; @@ -87,12 +90,13 @@ void GUI::act(float delta) { if (Events::clicked(mousecode::BUTTON_1)) { focus->mouseMove(this, mx, my); } - if (prevfocus == focus) + if (prevfocus == focus){ for (int i = mousecode::BUTTON_1; i < mousecode::BUTTON_1+12; i++) { if (Events::jclicked(i)) { focus->clicked(this, i); } } + } } } if (focus && !focus->isfocused()) { diff --git a/src/frontend/gui/UINode.cpp b/src/frontend/gui/UINode.cpp index 751c341a..3a77b146 100644 --- a/src/frontend/gui/UINode.cpp +++ b/src/frontend/gui/UINode.cpp @@ -83,11 +83,17 @@ shared_ptr UINode::getAt(vec2 pos, shared_ptr self) { vec2 UINode::calcCoord() const { if (parent) { - return coord + parent->calcCoord(); + return coord + parent->calcCoord() + parent->contentOffset(); } return coord; } +void UINode::scrolled(int value) { + if (parent) { + parent->scrolled(value); + } +} + void UINode::setCoord(vec2 coord) { this->coord = coord; } @@ -100,11 +106,6 @@ void UINode::size(vec2 size) { if (sizelock) return; this->size_ = size; - if (parent) { - sizelock = true; - //parent->refresh(); - sizelock = false; - } } void UINode::_size(vec2 size) { diff --git a/src/frontend/gui/UINode.h b/src/frontend/gui/UINode.h index 1620fc5a..25ba270f 100644 --- a/src/frontend/gui/UINode.h +++ b/src/frontend/gui/UINode.h @@ -61,6 +61,7 @@ namespace gui { virtual void clicked(GUI*, int button) {} virtual void mouseMove(GUI*, int x, int y) {}; virtual void mouseRelease(GUI*, int x, int y); + virtual void scrolled(int value); bool ispressed() const; void defocus(); @@ -73,6 +74,7 @@ namespace gui { virtual bool isInside(glm::vec2 pos); virtual std::shared_ptr getAt(glm::vec2 pos, std::shared_ptr self); + virtual glm::vec2 contentOffset() {return glm::vec2(0.0f);}; glm::vec2 calcCoord() const; void setCoord(glm::vec2 coord); glm::vec2 size() const; diff --git a/src/frontend/gui/controls.cpp b/src/frontend/gui/controls.cpp index c7a2f278..4f09573a 100644 --- a/src/frontend/gui/controls.cpp +++ b/src/frontend/gui/controls.cpp @@ -59,12 +59,14 @@ void Label::size(vec2 sizenew) { // ================================= Button =================================== Button::Button(shared_ptr content, glm::vec4 padding) : Panel(vec2(32,32), padding, 0) { add(content); + scrollable(false); } Button::Button(wstring text, glm::vec4 padding) : Panel(vec2(32,32), padding, 0) { Label* label = new Label(text); label->align(Align::center); add(shared_ptr(label)); + scrollable(false); } void Button::drawBackground(Batch2D* batch, Assets* assets) { @@ -117,6 +119,7 @@ void TextBox::drawBackground(Batch2D* batch, Assets* assets) { label->color(vec4(1.0f)); label->text(input); } + scrollable(false); } void TextBox::typed(unsigned int codepoint) { @@ -163,6 +166,7 @@ InputBindBox::InputBindBox(Binding& binding, vec4 padding) binding(binding) { label = new Label(L""); add(label); + scrollable(false); } shared_ptr InputBindBox::getAt(vec2 pos, shared_ptr self) { diff --git a/src/frontend/gui/panels.cpp b/src/frontend/gui/panels.cpp index 8959b492..8bca8572 100644 --- a/src/frontend/gui/panels.cpp +++ b/src/frontend/gui/panels.cpp @@ -14,6 +14,7 @@ using glm::vec2; using glm::vec4; Container::Container(vec2 coord, vec2 size) : UINode(coord, size) { + actualLength = size.y; } shared_ptr Container::getAt(vec2 pos, shared_ptr self) { @@ -53,6 +54,24 @@ void Container::act(float delta) { } } +void Container::scrolled(int value) { + int diff = (actualLength-size().y); + if (diff > 0 && scrollable_) { + scroll += value * 20; + if (scroll > 0) + scroll = 0; + if (-scroll > diff) { + scroll = -diff; + } + } else if (parent) { + parent->scrolled(value); + } +} + +void Container::scrollable(bool flag) { + scrollable_ = flag; +} + void Container::draw(Batch2D* batch, Assets* assets) { vec2 coord = calcCoord(); vec2 size = this->size(); @@ -110,6 +129,14 @@ void Panel::drawBackground(Batch2D* batch, Assets* assets) { batch->rect(coord.x, coord.y, size_.x, size_.y); } +void Panel::maxLength(int value) { + maxLength_ = value; +} + +int Panel::maxLength() const { + return maxLength_; +} + void Panel::refresh() { float x = padding.x; float y = padding.y; @@ -141,8 +168,13 @@ void Panel::refresh() { node->refresh(); maxw = fmax(maxw, ex+node->size().x+margin.z+padding.z); } - if (resizing_) - this->size(vec2(size.x, y+padding.w)); + if (resizing_) { + if (maxLength_) + this->size(vec2(size.x, min(maxLength_, (int)(y+padding.w)))); + else + this->size(vec2(size.x, y+padding.w)); + } + actualLength = y + padding.w; } else { float maxh = size.y; for (auto& node : nodes) { @@ -158,10 +190,15 @@ void Panel::refresh() { maxh = fmax(maxh, y+margin.y+node->size().y+margin.w+padding.w); } bool increased = maxh > size.y; - if (resizing_) - this->size(vec2(x+padding.z, size.y)); + if (resizing_) { + if (maxLength_) + this->size(vec2(min(maxLength_, (int)(x+padding.z)), size.y)); + else + this->size(vec2(x+padding.z, size.y)); + } if (increased) refresh(); + actualLength = size.y; } } diff --git a/src/frontend/gui/panels.h b/src/frontend/gui/panels.h index a44c605b..3524576f 100644 --- a/src/frontend/gui/panels.h +++ b/src/frontend/gui/panels.h @@ -27,6 +27,9 @@ namespace gui { protected: std::vector> nodes; std::vector intervalEvents; + int scroll = 0; + int actualLength = 0; + bool scrollable_ = true; public: Container(glm::vec2 coord, glm::vec2 size); @@ -37,7 +40,10 @@ namespace gui { virtual void add(std::shared_ptr node); virtual void add(UINode* node); virtual void remove(std::shared_ptr node); + virtual void scrolled(int value) override; + virtual void scrollable(bool flag); void listenInterval(float interval, ontimeout callback, int repeat=-1); + virtual glm::vec2 contentOffset() override {return glm::vec2(0.0f, scroll);}; }; class Panel : public Container { @@ -46,6 +52,7 @@ namespace gui { glm::vec4 padding {2.0f}; float interval = 2.0f; bool resizing_; + int maxLength_ = 0; public: Panel(glm::vec2 size, glm::vec4 padding=glm::vec4(2.0f), float interval=2.0f, bool resizing=true); virtual ~Panel(); @@ -57,6 +64,9 @@ namespace gui { virtual void refresh() override; virtual void lock() override; + + virtual void maxLength(int value); + int maxLength() const; }; struct Page { diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index 78305b34..fa0ef1bf 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -48,6 +48,7 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) { Panel* worldsPanel = new Panel(vec2(390, 200), vec4(5.0f)); worldsPanel->color(vec4(0.1f)); + worldsPanel->maxLength(400); path worldsFolder = enginefs::get_worlds_folder(); if (std::filesystem::is_directory(worldsFolder)) { for (auto const& entry : directory_iterator(worldsFolder)) { @@ -164,9 +165,12 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) { } Panel* create_controls_panel(Engine* engine, PagesControl* menu) { - Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); + Panel* panel = new Panel(vec2(400, 200), vec4(2.0f), 1.0f); panel->color(vec4(0.0f)); + Panel* scrollPanel = new Panel(vec2(400, 200), vec4(2.0f), 1.0f); + scrollPanel->color(vec4(0.0f, 0.0f, 0.0f, 0.3f)); + scrollPanel->maxLength(500); for (auto& entry : Events::bindings){ string bindname = entry.first; @@ -179,8 +183,9 @@ Panel* create_controls_panel(Engine* engine, PagesControl* menu) { Label* label = new Label(util::str2wstr_utf8(bindname)); label->margin(vec4(6.0f)); subpanel->add(label); - panel->add(subpanel); + scrollPanel->add(subpanel); } + panel->add(scrollPanel); panel->add(backButton(menu)); panel->refresh(); diff --git a/src/window/Events.cpp b/src/window/Events.cpp index 6bbc7f63..0b779e7b 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -10,6 +10,7 @@ float Events::deltaX = 0.0f; float Events::deltaY = 0.0f; float Events::x = 0.0f; float Events::y = 0.0f; +int Events::scroll = 0; bool Events::_cursor_locked = false; bool Events::_cursor_started = false; std::vector Events::codepoints; @@ -62,6 +63,7 @@ void Events::pullEvents(){ _current++; deltaX = 0.0f; deltaY = 0.0f; + scroll = 0; codepoints.clear(); pressedKeys.clear(); glfwPollEvents(); diff --git a/src/window/Events.h b/src/window/Events.h index c4d4813f..226a5096 100644 --- a/src/window/Events.h +++ b/src/window/Events.h @@ -19,6 +19,7 @@ public: static float deltaY; static float x; static float y; + static int scroll; static bool _cursor_locked; static bool _cursor_started; static std::vector codepoints; diff --git a/src/window/Window.cpp b/src/window/Window.cpp index 562e6f67..58d54a5e 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -53,6 +53,10 @@ void key_callback(GLFWwindow*, int key, int scancode, int action, int /*mode*/) } } +void scroll_callback(GLFWwindow*, double xoffset, double yoffset) { + Events::scroll += yoffset; +} + void window_size_callback(GLFWwindow*, int width, int height) { glViewport(0, 0, width, height); Window::width = width; @@ -105,6 +109,7 @@ int Window::initialize(DisplaySettings& settings){ glfwSetCursorPosCallback(window, cursor_position_callback); glfwSetWindowSizeCallback(window, window_size_callback); glfwSetCharCallback(window, character_callback); + glfwSetScrollCallback(window, scroll_callback); glfwSwapInterval(settings.swapInterval); return 0; @@ -139,13 +144,20 @@ void Window::pushScissor(vec4 area) { } scissorStack.push(scissorArea); + area.z += area.x; + area.w += area.y; + area.x = fmax(area.x, scissorArea.x); area.y = fmax(area.y, scissorArea.y); area.z = fmin(area.z, scissorArea.z); area.w = fmin(area.w, scissorArea.w); - glScissor(area.x, Window::height-area.y-area.w, area.z, area.w); + if (area.z < 0.0f || area.w < 0.0f) { + glScissor(0, 0, 0, 0); + } else { + glScissor(area.x, Window::height-area.w, area.z-area.x, area.w-area.y); + } scissorArea = area; } @@ -156,7 +168,11 @@ void Window::popScissor() { } vec4 area = scissorStack.top(); scissorStack.pop(); - glScissor(area.x, Window::height-area.y-area.w, area.z, area.w); + if (area.z < 0.0f || area.w < 0.0f) { + glScissor(0, 0, 0, 0); + } else { + glScissor(area.x, Window::height-area.w, area.z-area.x, area.w-area.y); + } if (scissorStack.empty()) { glDisable(GL_SCISSOR_TEST); }