Merge pull request #8096 from Robyt3/UI-ScrollRegion-Popup-Handling

Support overlapping scroll regions, always allow mouse scrolling
This commit is contained in:
Dennis Felsing 2024-03-12 21:55:02 +00:00 committed by GitHub
commit e92f5e85ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 37 additions and 19 deletions

View file

@ -15,7 +15,7 @@
enum class EInputPriority enum class EInputPriority
{ {
NONE = 0, NONE = 0,
Ui, UI,
CHAT, CHAT,
CONSOLE, CONSOLE,
}; };

View file

@ -113,11 +113,6 @@ CUi::CUi()
{ {
m_Enabled = true; m_Enabled = true;
m_pHotItem = nullptr;
m_pActiveItem = nullptr;
m_pLastActiveItem = nullptr;
m_pBecomingHotItem = nullptr;
m_MouseX = 0; m_MouseX = 0;
m_MouseY = 0; m_MouseY = 0;
m_MouseWorldX = 0; m_MouseWorldX = 0;
@ -220,6 +215,8 @@ void CUi::Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDelta
if(m_pActiveItem) if(m_pActiveItem)
m_pHotItem = m_pActiveItem; m_pHotItem = m_pActiveItem;
m_pBecomingHotItem = nullptr; m_pBecomingHotItem = nullptr;
m_pHotScrollRegion = m_pBecomingHotScrollRegion;
m_pBecomingHotScrollRegion = nullptr;
if(Enabled()) if(Enabled())
{ {
@ -231,6 +228,7 @@ void CUi::Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDelta
{ {
m_pHotItem = nullptr; m_pHotItem = nullptr;
m_pActiveItem = nullptr; m_pActiveItem = nullptr;
m_pHotScrollRegion = nullptr;
} }
} }
@ -804,7 +802,7 @@ bool CUi::DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize
SetHotItem(pLineInput); SetHotItem(pLineInput);
if(Enabled() && Active && !JustGotActive) if(Enabled() && Active && !JustGotActive)
pLineInput->Activate(EInputPriority::Ui); pLineInput->Activate(EInputPriority::UI);
else else
pLineInput->Deactivate(); pLineInput->Deactivate();
@ -1416,7 +1414,10 @@ void CUi::RenderPopupMenus()
const bool Active = i == m_vPopupMenus.size() - 1; const bool Active = i == m_vPopupMenus.size() - 1;
if(Active) if(Active)
{
// Prevent UI elements below the popup menu from being activated.
SetHotItem(pId); SetHotItem(pId);
}
if(CheckActiveItem(pId)) if(CheckActiveItem(pId))
{ {
@ -1437,6 +1438,12 @@ void CUi::RenderPopupMenus()
SetActiveItem(pId); SetActiveItem(pId);
} }
if(Inside)
{
// Prevent scroll regions directly behind popup menus from using the mouse scroll events.
SetHotScrollRegion(nullptr);
}
CUIRect PopupRect = PopupMenu.m_Rect; CUIRect PopupRect = PopupMenu.m_Rect;
PopupRect.Draw(PopupMenu.m_Props.m_BorderColor, PopupMenu.m_Props.m_Corners, 3.0f); PopupRect.Draw(PopupMenu.m_Props.m_BorderColor, PopupMenu.m_Props.m_Corners, 3.0f);
PopupRect.Margin(SPopupMenu::POPUP_BORDER, &PopupRect); PopupRect.Margin(SPopupMenu::POPUP_BORDER, &PopupRect);

View file

@ -14,6 +14,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
class CScrollRegion;
class IClient; class IClient;
class IGraphics; class IGraphics;
class IKernel; class IKernel;
@ -322,10 +323,12 @@ public:
private: private:
bool m_Enabled; bool m_Enabled;
const void *m_pHotItem; const void *m_pHotItem = nullptr;
const void *m_pActiveItem; const void *m_pActiveItem = nullptr;
const void *m_pLastActiveItem; // only used internally to track active CLineInput const void *m_pLastActiveItem = nullptr; // only used internally to track active CLineInput
const void *m_pBecomingHotItem; const void *m_pBecomingHotItem = nullptr;
const CScrollRegion *m_pHotScrollRegion = nullptr;
const CScrollRegion *m_pBecomingHotScrollRegion = nullptr;
bool m_ActiveItemValid = false; bool m_ActiveItemValid = false;
vec2 m_UpdatedMousePos = vec2(0.0f, 0.0f); vec2 m_UpdatedMousePos = vec2(0.0f, 0.0f);
@ -464,9 +467,11 @@ public:
} }
return false; return false;
} }
void SetHotScrollRegion(const CScrollRegion *pId) { m_pBecomingHotScrollRegion = pId; }
const void *HotItem() const { return m_pHotItem; } const void *HotItem() const { return m_pHotItem; }
const void *NextHotItem() const { return m_pBecomingHotItem; } const void *NextHotItem() const { return m_pBecomingHotItem; }
const void *ActiveItem() const { return m_pActiveItem; } const void *ActiveItem() const { return m_pActiveItem; }
const CScrollRegion *HotScrollRegion() const { return m_pHotScrollRegion; }
void StartCheck() { m_ActiveItemValid = false; } void StartCheck() { m_ActiveItemValid = false; }
void FinishCheck() void FinishCheck()
@ -629,7 +634,7 @@ public:
struct SSelectionPopupContext : public SPopupMenuId struct SSelectionPopupContext : public SPopupMenuId
{ {
CUi *m_pUI; // set by CUi when popup is shown CUi *m_pUI; // set by CUi when popup is shown
class CScrollRegion *m_pScrollRegion; CScrollRegion *m_pScrollRegion;
SPopupMenuProperties m_Props; SPopupMenuProperties m_Props;
char m_aMessage[256]; char m_aMessage[256];
std::vector<std::string> m_vEntries; std::vector<std::string> m_vEntries;

View file

@ -117,7 +117,6 @@ void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsP
// setup the scrollbar // setup the scrollbar
m_ScrollOffset = vec2(0.0f, 0.0f); m_ScrollOffset = vec2(0.0f, 0.0f);
CScrollRegionParams ScrollParams; CScrollRegionParams ScrollParams;
ScrollParams.m_Active = m_Active;
ScrollParams.m_ScrollbarWidth = ScrollbarWidthMax(); ScrollParams.m_ScrollbarWidth = ScrollbarWidthMax();
ScrollParams.m_ScrollbarMargin = ScrollbarMargin(); ScrollParams.m_ScrollbarMargin = ScrollbarMargin();
ScrollParams.m_ScrollUnit = (m_ListBoxRowHeight + m_AutoSpacing) * RowsPerScroll; ScrollParams.m_ScrollUnit = (m_ListBoxRowHeight + m_AutoSpacing) * RowsPerScroll;
@ -208,7 +207,7 @@ CListboxItem CListBox::DoSubheader()
int CListBox::DoEnd() int CListBox::DoEnd()
{ {
m_ScrollRegion.End(); m_ScrollRegion.End();
m_Active |= m_ScrollRegion.Params().m_Active; m_Active |= m_ScrollRegion.Active();
m_ScrollbarShown = m_ScrollRegion.ScrollbarShown(); m_ScrollbarShown = m_ScrollRegion.ScrollbarShown();
if(m_ListBoxNewSelOffset != 0 && m_ListBoxNumItems > 0 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) if(m_ListBoxNewSelOffset != 0 && m_ListBoxNumItems > 0 && m_ListBoxSelectedIndex == m_ListBoxNewSelected)

View file

@ -79,7 +79,7 @@ void CScrollRegion::End()
CUIRect RegionRect = m_ClipRect; CUIRect RegionRect = m_ClipRect;
RegionRect.w += m_Params.m_ScrollbarWidth; 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; bool ProgrammaticScroll = false;
if(Ui()->ConsumeHotkey(CUi::HOTKEY_SCROLL_UP)) 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); const float SliderHeight = maximum(m_Params.m_SliderMinHeight, m_ClipRect.h / m_ContentH * m_RailRect.h);
CUIRect Slider = m_RailRect; CUIRect Slider = m_RailRect;
@ -163,7 +168,6 @@ void CScrollRegion::End()
m_SliderGrabPos = Ui()->MouseY() - Slider.y; m_SliderGrabPos = Ui()->MouseY() - Slider.y;
m_AnimTargetScrollY = m_ScrollY; m_AnimTargetScrollY = m_ScrollY;
m_AnimTime = 0.0f; m_AnimTime = 0.0f;
m_Params.m_Active = true;
} }
} }
else if(InsideRail && Ui()->MouseButtonClicked(0)) else if(InsideRail && Ui()->MouseButtonClicked(0))
@ -174,7 +178,6 @@ void CScrollRegion::End()
m_SliderGrabPos = Slider.h / 2.0f; m_SliderGrabPos = Slider.h / 2.0f;
m_AnimTargetScrollY = m_ScrollY; m_AnimTargetScrollY = m_ScrollY;
m_AnimTime = 0.0f; m_AnimTime = 0.0f;
m_Params.m_Active = true;
} }
else if(Ui()->CheckActiveItem(pId) && !Ui()->MouseButton(0)) else if(Ui()->CheckActiveItem(pId) && !Ui()->MouseButton(0))
{ {
@ -259,3 +262,8 @@ bool CScrollRegion::Animating() const
{ {
return m_AnimTime > 0.0f; return m_AnimTime > 0.0f;
} }
bool CScrollRegion::Active() const
{
return Ui()->ActiveItem() == &m_ScrollY;
}

View file

@ -7,7 +7,6 @@
struct CScrollRegionParams struct CScrollRegionParams
{ {
bool m_Active;
float m_ScrollbarWidth; float m_ScrollbarWidth;
float m_ScrollbarMargin; float m_ScrollbarMargin;
bool m_ScrollbarNoMarginRight; bool m_ScrollbarNoMarginRight;
@ -28,7 +27,6 @@ struct CScrollRegionParams
CScrollRegionParams() CScrollRegionParams()
{ {
m_Active = true;
m_ScrollbarWidth = 20.0f; m_ScrollbarWidth = 20.0f;
m_ScrollbarMargin = 5.0f; m_ScrollbarMargin = 5.0f;
m_ScrollbarNoMarginRight = false; m_ScrollbarNoMarginRight = false;
@ -140,6 +138,7 @@ public:
bool RectClipped(const CUIRect &Rect) const; bool RectClipped(const CUIRect &Rect) const;
bool ScrollbarShown() const; bool ScrollbarShown() const;
bool Animating() const; bool Animating() const;
bool Active() const;
const CScrollRegionParams &Params() const { return m_Params; } const CScrollRegionParams &Params() const { return m_Params; }
}; };