From f291362d8828a583d82223d49d247ece555ef87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 12 Mar 2024 18:10:54 +0100 Subject: [PATCH 1/2] Revert name of `enum` literal `Ui` back to `UI` This `enum` literal was accidentally included in the renaming of the `UI` function to `Ui`. --- src/game/client/lineinput.h | 2 +- src/game/client/ui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/lineinput.h b/src/game/client/lineinput.h index 8d47008c1..cbf4e42e9 100644 --- a/src/game/client/lineinput.h +++ b/src/game/client/lineinput.h @@ -15,7 +15,7 @@ enum class EInputPriority { NONE = 0, - Ui, + UI, CHAT, CONSOLE, }; diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 96d6360f8..60a1ef973 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -804,7 +804,7 @@ bool CUi::DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize SetHotItem(pLineInput); if(Enabled() && Active && !JustGotActive) - pLineInput->Activate(EInputPriority::Ui); + pLineInput->Activate(EInputPriority::UI); else pLineInput->Deactivate(); From ae9a8fe3d42c49da934aea50bff4e99d303a3fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 12 Mar 2024 18:14:55 +0100 Subject: [PATCH 2/2] Support overlapping scroll regions, always allow mouse scrolling Support scrolling all scroll regions with the mouse wheel also while popup menus are open. Support overlapping scroll regions by always scrolling the top-most hovered scroll region on mouse wheel events. The hot scroll region is now tracked separated by `CUi`, as tracking the IDs of all UI elements which are contained in scroll regions is not feasible. The separate active state for scroll regions is therefore unnecessary. It's still necessary to disable `CListBox`es when popup menus are open, to ensure that only one list box consumes the key events. Closes #8087. Supersedes #8090. --- src/game/client/ui.cpp | 17 ++++++++++++----- src/game/client/ui.h | 15 ++++++++++----- src/game/client/ui_listbox.cpp | 3 +-- src/game/client/ui_scrollregion.cpp | 14 +++++++++++--- src/game/client/ui_scrollregion.h | 3 +-- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 60a1ef973..a5331a0a3 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -113,11 +113,6 @@ CUi::CUi() { m_Enabled = true; - m_pHotItem = nullptr; - m_pActiveItem = nullptr; - m_pLastActiveItem = nullptr; - m_pBecomingHotItem = nullptr; - m_MouseX = 0; m_MouseY = 0; m_MouseWorldX = 0; @@ -220,6 +215,8 @@ void CUi::Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDelta if(m_pActiveItem) m_pHotItem = m_pActiveItem; m_pBecomingHotItem = nullptr; + m_pHotScrollRegion = m_pBecomingHotScrollRegion; + m_pBecomingHotScrollRegion = nullptr; if(Enabled()) { @@ -231,6 +228,7 @@ void CUi::Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDelta { m_pHotItem = nullptr; m_pActiveItem = nullptr; + m_pHotScrollRegion = nullptr; } } @@ -1416,7 +1414,10 @@ void CUi::RenderPopupMenus() const bool Active = i == m_vPopupMenus.size() - 1; if(Active) + { + // Prevent UI elements below the popup menu from being activated. SetHotItem(pId); + } if(CheckActiveItem(pId)) { @@ -1437,6 +1438,12 @@ void CUi::RenderPopupMenus() SetActiveItem(pId); } + if(Inside) + { + // Prevent scroll regions directly behind popup menus from using the mouse scroll events. + SetHotScrollRegion(nullptr); + } + CUIRect PopupRect = PopupMenu.m_Rect; PopupRect.Draw(PopupMenu.m_Props.m_BorderColor, PopupMenu.m_Props.m_Corners, 3.0f); PopupRect.Margin(SPopupMenu::POPUP_BORDER, &PopupRect); diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 5c1a70673..f8455972d 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -14,6 +14,7 @@ #include #include +class CScrollRegion; class IClient; class IGraphics; class IKernel; @@ -322,10 +323,12 @@ public: private: bool m_Enabled; - const void *m_pHotItem; - const void *m_pActiveItem; - const void *m_pLastActiveItem; // only used internally to track active CLineInput - const void *m_pBecomingHotItem; + const void *m_pHotItem = nullptr; + const void *m_pActiveItem = nullptr; + const void *m_pLastActiveItem = nullptr; // only used internally to track active CLineInput + const void *m_pBecomingHotItem = nullptr; + const CScrollRegion *m_pHotScrollRegion = nullptr; + const CScrollRegion *m_pBecomingHotScrollRegion = nullptr; bool m_ActiveItemValid = false; vec2 m_UpdatedMousePos = vec2(0.0f, 0.0f); @@ -464,9 +467,11 @@ public: } return false; } + void SetHotScrollRegion(const CScrollRegion *pId) { m_pBecomingHotScrollRegion = pId; } const void *HotItem() const { return m_pHotItem; } const void *NextHotItem() const { return m_pBecomingHotItem; } const void *ActiveItem() const { return m_pActiveItem; } + const CScrollRegion *HotScrollRegion() const { return m_pHotScrollRegion; } void StartCheck() { m_ActiveItemValid = false; } void FinishCheck() @@ -629,7 +634,7 @@ public: struct SSelectionPopupContext : public SPopupMenuId { CUi *m_pUI; // set by CUi when popup is shown - class CScrollRegion *m_pScrollRegion; + CScrollRegion *m_pScrollRegion; SPopupMenuProperties m_Props; char m_aMessage[256]; std::vector m_vEntries; diff --git a/src/game/client/ui_listbox.cpp b/src/game/client/ui_listbox.cpp index 4414f0662..086b37bb3 100644 --- a/src/game/client/ui_listbox.cpp +++ b/src/game/client/ui_listbox.cpp @@ -117,7 +117,6 @@ void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsP // setup the scrollbar m_ScrollOffset = vec2(0.0f, 0.0f); CScrollRegionParams ScrollParams; - ScrollParams.m_Active = m_Active; ScrollParams.m_ScrollbarWidth = ScrollbarWidthMax(); ScrollParams.m_ScrollbarMargin = ScrollbarMargin(); ScrollParams.m_ScrollUnit = (m_ListBoxRowHeight + m_AutoSpacing) * RowsPerScroll; @@ -208,7 +207,7 @@ CListboxItem CListBox::DoSubheader() int CListBox::DoEnd() { m_ScrollRegion.End(); - m_Active |= m_ScrollRegion.Params().m_Active; + m_Active |= m_ScrollRegion.Active(); m_ScrollbarShown = m_ScrollRegion.ScrollbarShown(); if(m_ListBoxNewSelOffset != 0 && m_ListBoxNumItems > 0 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) diff --git a/src/game/client/ui_scrollregion.cpp b/src/game/client/ui_scrollregion.cpp index 7da294361..1f549a7cf 100644 --- a/src/game/client/ui_scrollregion.cpp +++ b/src/game/client/ui_scrollregion.cpp @@ -79,7 +79,7 @@ void CScrollRegion::End() CUIRect RegionRect = m_ClipRect; RegionRect.w += m_Params.m_ScrollbarWidth; - if(m_ScrollDirection != SCROLLRELATIVE_NONE || (Ui()->Enabled() && m_Params.m_Active && Ui()->MouseHovered(&RegionRect))) + if(m_ScrollDirection != SCROLLRELATIVE_NONE || Ui()->HotScrollRegion() == this) { bool ProgrammaticScroll = false; if(Ui()->ConsumeHotkey(CUi::HOTKEY_SCROLL_UP)) @@ -106,6 +106,11 @@ void CScrollRegion::End() } } + if(Ui()->Enabled() && Ui()->MouseHovered(&RegionRect)) + { + Ui()->SetHotScrollRegion(this); + } + const float SliderHeight = maximum(m_Params.m_SliderMinHeight, m_ClipRect.h / m_ContentH * m_RailRect.h); CUIRect Slider = m_RailRect; @@ -163,7 +168,6 @@ void CScrollRegion::End() m_SliderGrabPos = Ui()->MouseY() - Slider.y; m_AnimTargetScrollY = m_ScrollY; m_AnimTime = 0.0f; - m_Params.m_Active = true; } } else if(InsideRail && Ui()->MouseButtonClicked(0)) @@ -174,7 +178,6 @@ void CScrollRegion::End() m_SliderGrabPos = Slider.h / 2.0f; m_AnimTargetScrollY = m_ScrollY; m_AnimTime = 0.0f; - m_Params.m_Active = true; } else if(Ui()->CheckActiveItem(pId) && !Ui()->MouseButton(0)) { @@ -259,3 +262,8 @@ bool CScrollRegion::Animating() const { return m_AnimTime > 0.0f; } + +bool CScrollRegion::Active() const +{ + return Ui()->ActiveItem() == &m_ScrollY; +} diff --git a/src/game/client/ui_scrollregion.h b/src/game/client/ui_scrollregion.h index 2a601be53..203356c4c 100644 --- a/src/game/client/ui_scrollregion.h +++ b/src/game/client/ui_scrollregion.h @@ -7,7 +7,6 @@ struct CScrollRegionParams { - bool m_Active; float m_ScrollbarWidth; float m_ScrollbarMargin; bool m_ScrollbarNoMarginRight; @@ -28,7 +27,6 @@ struct CScrollRegionParams CScrollRegionParams() { - m_Active = true; m_ScrollbarWidth = 20.0f; m_ScrollbarMargin = 5.0f; m_ScrollbarNoMarginRight = false; @@ -140,6 +138,7 @@ public: bool RectClipped(const CUIRect &Rect) const; bool ScrollbarShown() const; bool Animating() const; + bool Active() const; const CScrollRegionParams &Params() const { return m_Params; } };