From 196eb3ec38fbfc8ef705da31d46d2bda016a9bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Wed, 6 Jul 2022 10:50:24 +0200 Subject: [PATCH] gui: scrollbar improvements --- Editor/PaintToolWindow.cpp | 4 +-- Editor/WeatherWindow.cpp | 2 +- WickedEngine/wiGUI.cpp | 59 +++++++++++++++++++++++--------------- WickedEngine/wiGUI.h | 4 +-- WickedEngine/wiVersion.cpp | 2 +- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index 804500565..0ef772d1b 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -14,7 +14,7 @@ void PaintToolWindow::Create(EditorComponent* editor) this->editor = editor; wi::gui::Window::Create("Paint Tool Window"); - SetSize(XMFLOAT2(410, 610)); + SetSize(XMFLOAT2(360, 540)); float x = 105; float y = 0; @@ -80,7 +80,7 @@ void PaintToolWindow::Create(EditorComponent* editor) y += step + 5; infoLabel.Create("Paint Tool is disabled."); - infoLabel.SetSize(XMFLOAT2(400 - 20, 100)); + infoLabel.SetSize(XMFLOAT2(GetScale().x - 20, 100)); infoLabel.SetPos(XMFLOAT2(10, y)); infoLabel.SetColor(wi::Color::Transparent()); AddWidget(&infoLabel); diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index 905312343..667c1b37f 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -9,7 +9,7 @@ using namespace wi::graphics; void WeatherWindow::Create(EditorComponent* editor) { wi::gui::Window::Create("Weather Window"); - SetSize(XMFLOAT2(660, 680)); + SetSize(XMFLOAT2(660, 300)); float x = 180; float y = 0; diff --git a/WickedEngine/wiGUI.cpp b/WickedEngine/wiGUI.cpp index 05f8da426..2186445e0 100644 --- a/WickedEngine/wiGUI.cpp +++ b/WickedEngine/wiGUI.cpp @@ -50,6 +50,10 @@ namespace wi::gui return internal_state; } + // This is used so that elements that support scroll could disable other scrolling elements: + // As opposed to click and other interaction types, we don't want to disable scroll on every focused widget + // because that would block scrolling the parent if a child element is hovered + static bool scroll_allowed = true; void GUI::Update(const wi::Canvas& canvas, float dt) { @@ -60,6 +64,8 @@ namespace wi::gui auto range = wi::profiler::BeginRangeCPU("GUI Update"); + scroll_allowed = true; + XMFLOAT4 pointer = wi::input::GetPointer(); Hitbox2D pointerHitbox = Hitbox2D(XMFLOAT2(pointer.x, pointer.y), XMFLOAT2(1, 1)); @@ -792,7 +798,7 @@ namespace wi::gui scrollbar_begin = translation.y; scrollbar_end = scrollbar_begin + scale.y; scrollbar_size = scrollbar_end - scrollbar_begin; - scrollbar_granularity = std::min(1.0f, scrollbar_size / std::max(1.0f, list_length)); + scrollbar_granularity = std::min(1.0f, scrollbar_size / std::max(1.0f, list_length - scale.x)); scrollbar_length = std::max(scale.x * 2, scrollbar_size * scrollbar_granularity); } else @@ -800,7 +806,7 @@ namespace wi::gui scrollbar_begin = translation.x; scrollbar_end = scrollbar_begin + scale.x; scrollbar_size = scrollbar_end - scrollbar_begin; - scrollbar_granularity = std::min(1.0f, scrollbar_size / std::max(1.0f, list_length)); + scrollbar_granularity = std::min(1.0f, scrollbar_size / std::max(1.0f, list_length - scale.y)); scrollbar_length = std::max(scale.y * 2, scrollbar_size * scrollbar_granularity); } @@ -958,8 +964,9 @@ namespace wi::gui scrollbar.Update(canvas, dt); Hitbox2D pointerHitbox = GetPointerHitbox(); - if (pointerHitbox.intersects(hitBox) && !force_disable) + if (scroll_allowed && scrollbar.IsScrollbarRequired() && pointerHitbox.intersects(hitBox)) { + scroll_allowed = false; state = FOCUS; // This is outside scrollbar code, because it can also be scrolled if parent widget is only in focus scrollbar.Scroll(wi::input::GetPointer().z * 20); @@ -1643,8 +1650,9 @@ namespace wi::gui Deactivate(); combostate = COMBOSTATE_INACTIVE; } - else if (combostate == COMBOSTATE_HOVER) + else if (combostate == COMBOSTATE_HOVER && scroll_allowed) { + scroll_allowed = false; int scroll = (int)wi::input::GetPointer().z; firstItemVisible -= scroll; firstItemVisible = std::max(0, std::min((int)items.size() - maxVisibleItemCount, firstItemVisible)); @@ -2018,20 +2026,6 @@ namespace wi::gui }); minimizeButton.SetTooltip("Minimize window"); AddWidget(&minimizeButton); - - scrollbar_horizontal.SetColor(wi::Color(80, 80, 80, 100), wi::gui::IDLE); - scrollbar_horizontal.sprites_knob[ScrollBar::SCROLLBAR_INACTIVE].params.color = wi::Color(140, 140, 140, 140); - scrollbar_horizontal.sprites_knob[ScrollBar::SCROLLBAR_HOVER].params.color = wi::Color(180, 180, 180, 180); - scrollbar_horizontal.sprites_knob[ScrollBar::SCROLLBAR_GRABBED].params.color = wi::Color::White(); - scrollbar_horizontal.knob_inset_border = XMFLOAT2(2, 4); - AddWidget(&scrollbar_horizontal); - - scrollbar_vertical.SetColor(wi::Color(80, 80, 80, 100), wi::gui::IDLE); - scrollbar_vertical.sprites_knob[ScrollBar::SCROLLBAR_INACTIVE].params.color = wi::Color(140, 140, 140, 140); - scrollbar_vertical.sprites_knob[ScrollBar::SCROLLBAR_HOVER].params.color = wi::Color(180, 180, 180, 180); - scrollbar_vertical.sprites_knob[ScrollBar::SCROLLBAR_GRABBED].params.color = wi::Color::White(); - scrollbar_vertical.knob_inset_border = XMFLOAT2(4, 2); - AddWidget(&scrollbar_vertical); } else { @@ -2042,6 +2036,20 @@ namespace wi::gui AddWidget(&label); } + scrollbar_horizontal.SetColor(wi::Color(80, 80, 80, 100), wi::gui::IDLE); + scrollbar_horizontal.sprites_knob[ScrollBar::SCROLLBAR_INACTIVE].params.color = wi::Color(140, 140, 140, 140); + scrollbar_horizontal.sprites_knob[ScrollBar::SCROLLBAR_HOVER].params.color = wi::Color(180, 180, 180, 180); + scrollbar_horizontal.sprites_knob[ScrollBar::SCROLLBAR_GRABBED].params.color = wi::Color::White(); + scrollbar_horizontal.knob_inset_border = XMFLOAT2(2, 4); + AddWidget(&scrollbar_horizontal); + + scrollbar_vertical.SetColor(wi::Color(80, 80, 80, 100), wi::gui::IDLE); + scrollbar_vertical.sprites_knob[ScrollBar::SCROLLBAR_INACTIVE].params.color = wi::Color(140, 140, 140, 140); + scrollbar_vertical.sprites_knob[ScrollBar::SCROLLBAR_HOVER].params.color = wi::Color(180, 180, 180, 180); + scrollbar_vertical.sprites_knob[ScrollBar::SCROLLBAR_GRABBED].params.color = wi::Color::White(); + scrollbar_vertical.knob_inset_border = XMFLOAT2(4, 2); + AddWidget(&scrollbar_vertical); + SetEnabled(true); SetVisible(true); @@ -2173,6 +2181,8 @@ namespace wi::gui float scroll_length_vertical = 0; for (auto& widget : widgets) { + if (!widget->IsVisible()) + continue; if (widget->parent == &scrollable_area) { scroll_length_horizontal = std::max(scroll_length_horizontal, widget->translation_local.x + widget->scale_local.x); @@ -2233,10 +2243,12 @@ namespace wi::gui return a->priority < b->priority; }); - if (pointerHitbox.intersects(hitBox) && !force_disable && !focus) // when window is in focus, but other widgets aren't + float scroll = wi::input::GetPointer().z * 20; + if (scroll && scroll_allowed && scrollbar_vertical.IsScrollbarRequired() && pointerHitbox.intersects(hitBox)) // when window is in focus, but other widgets aren't { + scroll_allowed = false; // This is outside scrollbar code, because it can also be scrolled if parent widget is only in focus - scrollbar_vertical.Scroll(wi::input::GetPointer().z * 20); + scrollbar_vertical.Scroll(scroll); } if (IsMinimized()) @@ -3287,11 +3299,12 @@ namespace wi::gui } scrollbar.SetListLength(scroll_length); - - if (GetState() == FOCUS) + float scroll = wi::input::GetPointer().z * 10; + if (scroll && scroll_allowed && scrollbar.IsScrollbarRequired() && GetState() == FOCUS) { + scroll_allowed = false; // This is outside scrollbar code, because it can also be scrolled if parent widget is only in focus - scrollbar.Scroll(wi::input::GetPointer().z * 10); + scrollbar.Scroll(scroll); } const float scrollbar_width = 12; scrollbar.SetSize(XMFLOAT2(scrollbar_width - 1, scale.y - 1 - item_height())); diff --git a/WickedEngine/wiGUI.h b/WickedEngine/wiGUI.h index 01ccd3de7..5203d58ac 100644 --- a/WickedEngine/wiGUI.h +++ b/WickedEngine/wiGUI.h @@ -182,8 +182,8 @@ namespace wi::gui // 0: no extra offset // 1: full extra offset void SetOverScroll(float amount) { overscroll = amount; } - // Check whether the scrollbar is required (when the items don't and scrolling could be used) - bool IsScrollbarRequired() const { return scrollbar_granularity < 1; } + // Check whether the scrollbar is required (when the items don't fit and scrolling could be used) + bool IsScrollbarRequired() const { return scrollbar_granularity < 0.999f; } enum SCROLLBAR_STATE { diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 95659312a..39928e553 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 70; // minor bug fixes, alterations, refactors, updates - const int revision = 7; + const int revision = 8; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);