mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 01:24:18 +00:00
Extend CScrollRegion
to support scrolling when mouse at edge
Add `ScrollRelative` function to initiate relative scrolling programmatically, to realise scroll regions that scroll when the mouse is being dragged at the edge. Add `DoEdgeScrolling` to encapsulate all the necessary edge scrolling logic based on the position of the mouse. The edge scrolling starts at a fixed distance from the edges. The scrolling speed is dependent on the distance of the mouse from this border.
This commit is contained in:
parent
762f1a1262
commit
66ad9536fe
|
@ -13,11 +13,15 @@ CScrollRegion::CScrollRegion()
|
||||||
{
|
{
|
||||||
m_ScrollY = 0.0f;
|
m_ScrollY = 0.0f;
|
||||||
m_ContentH = 0.0f;
|
m_ContentH = 0.0f;
|
||||||
|
m_RequestScrollY = -1.0f;
|
||||||
|
m_ScrollDirection = SCROLLRELATIVE_NONE;
|
||||||
|
m_ScrollSpeedMultiplier = 1.0f;
|
||||||
|
|
||||||
m_AnimTimeMax = 0.0f;
|
m_AnimTimeMax = 0.0f;
|
||||||
m_AnimTime = 0.0f;
|
m_AnimTime = 0.0f;
|
||||||
m_AnimInitScrollY = 0.0f;
|
m_AnimInitScrollY = 0.0f;
|
||||||
m_AnimTargetScrollY = 0.0f;
|
m_AnimTargetScrollY = 0.0f;
|
||||||
m_RequestScrollY = -1.0f;
|
|
||||||
m_ContentScrollOff = vec2(0.0f, 0.0f);
|
m_ContentScrollOff = vec2(0.0f, 0.0f);
|
||||||
m_Params = CScrollRegionParams();
|
m_Params = CScrollRegionParams();
|
||||||
}
|
}
|
||||||
|
@ -69,23 +73,30 @@ void CScrollRegion::End()
|
||||||
CUIRect RegionRect = m_ClipRect;
|
CUIRect RegionRect = m_ClipRect;
|
||||||
RegionRect.w += m_Params.m_ScrollbarWidth;
|
RegionRect.w += m_Params.m_ScrollbarWidth;
|
||||||
|
|
||||||
if(UI()->Enabled() && UI()->MouseHovered(&RegionRect))
|
if(m_ScrollDirection != SCROLLRELATIVE_NONE || (UI()->Enabled() && UI()->MouseHovered(&RegionRect)))
|
||||||
{
|
{
|
||||||
float ScrollDirection = 0.0f;
|
bool ProgrammaticScroll = false;
|
||||||
if(UI()->ConsumeHotkey(CUI::HOTKEY_SCROLL_UP))
|
if(UI()->ConsumeHotkey(CUI::HOTKEY_SCROLL_UP))
|
||||||
ScrollDirection = -1.0f;
|
m_ScrollDirection = SCROLLRELATIVE_UP;
|
||||||
else if(UI()->ConsumeHotkey(CUI::HOTKEY_SCROLL_DOWN))
|
else if(UI()->ConsumeHotkey(CUI::HOTKEY_SCROLL_DOWN))
|
||||||
ScrollDirection = 1.0f;
|
m_ScrollDirection = SCROLLRELATIVE_DOWN;
|
||||||
|
else
|
||||||
|
ProgrammaticScroll = true;
|
||||||
|
|
||||||
if(ScrollDirection != 0.0f)
|
if(!ProgrammaticScroll)
|
||||||
|
m_ScrollSpeedMultiplier = 1.0f;
|
||||||
|
|
||||||
|
if(m_ScrollDirection != SCROLLRELATIVE_NONE)
|
||||||
{
|
{
|
||||||
const bool IsPageScroll = Input()->AltIsPressed();
|
const bool IsPageScroll = Input()->AltIsPressed();
|
||||||
const float ScrollUnit = IsPageScroll ? m_ClipRect.h : m_Params.m_ScrollUnit;
|
const float ScrollUnit = IsPageScroll && !ProgrammaticScroll ? m_ClipRect.h : m_Params.m_ScrollUnit;
|
||||||
|
|
||||||
m_AnimTimeMax = g_Config.m_UiSmoothScrollTime / 1000.0f;
|
m_AnimTimeMax = g_Config.m_UiSmoothScrollTime / 1000.0f;
|
||||||
m_AnimTime = m_AnimTimeMax;
|
m_AnimTime = m_AnimTimeMax;
|
||||||
m_AnimInitScrollY = m_ScrollY;
|
m_AnimInitScrollY = m_ScrollY;
|
||||||
m_AnimTargetScrollY += ScrollDirection * ScrollUnit;
|
m_AnimTargetScrollY = (ProgrammaticScroll ? m_ScrollY : m_AnimTargetScrollY) + (int)m_ScrollDirection * ScrollUnit * m_ScrollSpeedMultiplier;
|
||||||
|
m_ScrollDirection = SCROLLRELATIVE_NONE;
|
||||||
|
m_ScrollSpeedMultiplier = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +217,28 @@ void CScrollRegion::ScrollHere(EScrollOption Option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CScrollRegion::ScrollRelative(EScrollRelative Direction, float SpeedMultiplier)
|
||||||
|
{
|
||||||
|
m_ScrollDirection = Direction;
|
||||||
|
m_ScrollSpeedMultiplier = SpeedMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScrollRegion::DoEdgeScrolling()
|
||||||
|
{
|
||||||
|
if(!IsScrollbarShown())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const float ScrollBorderSize = 20.0f;
|
||||||
|
const float MaxScrollMultiplier = 2.0f;
|
||||||
|
const float ScrollSpeedFactor = MaxScrollMultiplier / ScrollBorderSize;
|
||||||
|
const float TopScrollPosition = m_ClipRect.y + ScrollBorderSize;
|
||||||
|
const float BottomScrollPosition = m_ClipRect.y + m_ClipRect.h - ScrollBorderSize;
|
||||||
|
if(UI()->MouseY() < TopScrollPosition)
|
||||||
|
ScrollRelative(SCROLLRELATIVE_UP, minimum(MaxScrollMultiplier, (TopScrollPosition - UI()->MouseY()) * ScrollSpeedFactor));
|
||||||
|
else if(UI()->MouseY() > BottomScrollPosition)
|
||||||
|
ScrollRelative(SCROLLRELATIVE_DOWN, minimum(MaxScrollMultiplier, (UI()->MouseY() - BottomScrollPosition) * ScrollSpeedFactor));
|
||||||
|
}
|
||||||
|
|
||||||
bool CScrollRegion::IsRectClipped(const CUIRect &Rect) const
|
bool CScrollRegion::IsRectClipped(const CUIRect &Rect) const
|
||||||
{
|
{
|
||||||
return (m_ClipRect.x > (Rect.x + Rect.w) || (m_ClipRect.x + m_ClipRect.w) < Rect.x || m_ClipRect.y > (Rect.y + Rect.h) || (m_ClipRect.y + m_ClipRect.h) < Rect.y);
|
return (m_ClipRect.x > (Rect.x + Rect.w) || (m_ClipRect.x + m_ClipRect.w) < Rect.x || m_ClipRect.y > (Rect.y + Rect.h) || (m_ClipRect.y + m_ClipRect.h) < Rect.y);
|
||||||
|
|
|
@ -86,10 +86,20 @@ Usage:
|
||||||
// Instances of CScrollRegion must be static, as member addresses are used as UI item IDs
|
// Instances of CScrollRegion must be static, as member addresses are used as UI item IDs
|
||||||
class CScrollRegion : private CUIElementBase
|
class CScrollRegion : private CUIElementBase
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum EScrollRelative
|
||||||
|
{
|
||||||
|
SCROLLRELATIVE_UP = -1,
|
||||||
|
SCROLLRELATIVE_NONE = 0,
|
||||||
|
SCROLLRELATIVE_DOWN = 1,
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_ScrollY;
|
float m_ScrollY;
|
||||||
float m_ContentH;
|
float m_ContentH;
|
||||||
float m_RequestScrollY; // [0, ContentHeight]
|
float m_RequestScrollY; // [0, ContentHeight]
|
||||||
|
EScrollRelative m_ScrollDirection;
|
||||||
|
float m_ScrollSpeedMultiplier;
|
||||||
|
|
||||||
float m_AnimTimeMax;
|
float m_AnimTimeMax;
|
||||||
float m_AnimTime;
|
float m_AnimTime;
|
||||||
|
@ -116,6 +126,9 @@ public:
|
||||||
void End();
|
void End();
|
||||||
bool AddRect(const CUIRect &Rect, bool ShouldScrollHere = false); // returns true if the added rect is visible (not clipped)
|
bool AddRect(const CUIRect &Rect, bool ShouldScrollHere = false); // returns true if the added rect is visible (not clipped)
|
||||||
void ScrollHere(EScrollOption Option = SCROLLHERE_KEEP_IN_VIEW);
|
void ScrollHere(EScrollOption Option = SCROLLHERE_KEEP_IN_VIEW);
|
||||||
|
void ScrollRelative(EScrollRelative Direction, float SpeedMultiplier = 1.0f);
|
||||||
|
const CUIRect *ClipRect() const { return &m_ClipRect; }
|
||||||
|
void DoEdgeScrolling();
|
||||||
bool IsRectClipped(const CUIRect &Rect) const;
|
bool IsRectClipped(const CUIRect &Rect) const;
|
||||||
bool IsScrollbarShown() const;
|
bool IsScrollbarShown() const;
|
||||||
bool IsAnimating() const;
|
bool IsAnimating() const;
|
||||||
|
|
Loading…
Reference in a new issue