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; } };