mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge #6428
6428: Extend `CScrollRegion` to support scrolling when mouse at edge r=def- a=Robyt3 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. ## Checklist - [X] Tested the change ingame (in combination with #6426) - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
commit
5d1eab1fdb
|
@ -13,11 +13,15 @@ CScrollRegion::CScrollRegion()
|
|||
{
|
||||
m_ScrollY = 0.0f;
|
||||
m_ContentH = 0.0f;
|
||||
m_RequestScrollY = -1.0f;
|
||||
m_ScrollDirection = SCROLLRELATIVE_NONE;
|
||||
m_ScrollSpeedMultiplier = 1.0f;
|
||||
|
||||
m_AnimTimeMax = 0.0f;
|
||||
m_AnimTime = 0.0f;
|
||||
m_AnimInitScrollY = 0.0f;
|
||||
m_AnimTargetScrollY = 0.0f;
|
||||
m_RequestScrollY = -1.0f;
|
||||
|
||||
m_ContentScrollOff = vec2(0.0f, 0.0f);
|
||||
m_Params = CScrollRegionParams();
|
||||
}
|
||||
|
@ -69,23 +73,30 @@ void CScrollRegion::End()
|
|||
CUIRect RegionRect = m_ClipRect;
|
||||
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))
|
||||
ScrollDirection = -1.0f;
|
||||
m_ScrollDirection = SCROLLRELATIVE_UP;
|
||||
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 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_AnimTime = m_AnimTimeMax;
|
||||
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
|
||||
{
|
||||
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
|
||||
class CScrollRegion : private CUIElementBase
|
||||
{
|
||||
public:
|
||||
enum EScrollRelative
|
||||
{
|
||||
SCROLLRELATIVE_UP = -1,
|
||||
SCROLLRELATIVE_NONE = 0,
|
||||
SCROLLRELATIVE_DOWN = 1,
|
||||
};
|
||||
|
||||
private:
|
||||
float m_ScrollY;
|
||||
float m_ContentH;
|
||||
float m_RequestScrollY; // [0, ContentHeight]
|
||||
EScrollRelative m_ScrollDirection;
|
||||
float m_ScrollSpeedMultiplier;
|
||||
|
||||
float m_AnimTimeMax;
|
||||
float m_AnimTime;
|
||||
|
@ -116,6 +126,9 @@ public:
|
|||
void End();
|
||||
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 ScrollRelative(EScrollRelative Direction, float SpeedMultiplier = 1.0f);
|
||||
const CUIRect *ClipRect() const { return &m_ClipRect; }
|
||||
void DoEdgeScrolling();
|
||||
bool IsRectClipped(const CUIRect &Rect) const;
|
||||
bool IsScrollbarShown() const;
|
||||
bool IsAnimating() const;
|
||||
|
|
Loading…
Reference in a new issue