Added smooth scrolling + horizontal scrolling support

This commit is contained in:
OmniaX-Dev 2026-04-18 08:26:45 +02:00
parent d618de0981
commit d8475ecb48
7 changed files with 46 additions and 37 deletions

View file

@ -1,5 +1,4 @@
CompileFlags: CompileFlags:
CompilationDatabase: bin CompilationDatabase: bin
Add: ["--target=x86_64-w64-mingw32"]
Diagnostics: Diagnostics:
MissingIncludes: None MissingIncludes: None

View file

@ -30,7 +30,8 @@ window.backgroundColor = rgba(160, 160, 160, 255)
titlebarHeight = 18 titlebarHeight = 18
titlebarFontSize = 18 titlebarFontSize = 18
titlebarTextAlign = text_left titlebarTextAlign = text_left
scrollSpeed = 15.0 scrollSpeed = 1.2
scrollSmoothFactor = 0.7
padding = rect(15, 15, 15, 15) padding = rect(15, 15, 15, 15)
margin = rect(0, 0, 0, 0) margin = rect(0, 0, 0, 0)
} }

View file

@ -1 +1 @@
2067 2069

View file

@ -39,15 +39,20 @@ namespace ogfx
m_scrollbar.setMargin({ 0, getTitlebarHeight(), 0, 0 }); m_scrollbar.setMargin({ 0, getTitlebarHeight(), 0, 0 });
m_scrollbar.enableManualDraw(true); m_scrollbar.enableManualDraw(true);
addWidget(m_scrollbar); addWidget(m_scrollbar);
m_smoothScrollTimer.create(30.0f, [&](f64 dt) -> void { m_smoothScrollTimer.create(60.0f, [&](f64 dt) -> void {
f32 scrollStep = m_scrollTarget / 60.0f; f32 stepX = m_scrollVelocity.x * (1.0f - m_scrollSmoothFactor);
m_currentScroll += scrollStep; f32 stepY = m_scrollVelocity.y * (1.0f - m_scrollSmoothFactor);
addScrollOffset({ 0, scrollStep });
if (m_currentScroll > m_scrollTarget) addScrollOffset({ stepX, stepY });
m_currentScroll = m_scrollTarget; m_scrollVelocity -= { stepX, stepY };
}, [&](void) -> bool {
return m_currentScroll == m_scrollTarget; if (std::abs(m_scrollVelocity.x) < 0.5f) m_scrollVelocity.x = 0;
if (std::abs(m_scrollVelocity.y) < 0.5f) m_scrollVelocity.y = 0;
}, true); }, true);
m_smoothScrollTimer.setStopCondition([&](void) -> bool {
return m_scrollVelocity.x == 0 && m_scrollVelocity.y == 0;
});
validate(); validate();
return *this; return *this;
} }
@ -63,6 +68,7 @@ namespace ogfx
setPadding(getThemeValue<Rectangle>(theme, "panel.padding", { 15, 15, 15, 15 })); setPadding(getThemeValue<Rectangle>(theme, "panel.padding", { 15, 15, 15, 15 }));
setMargin(getThemeValue<Rectangle>(theme, "panel.margin", { 0, 0, 0, 0 })); setMargin(getThemeValue<Rectangle>(theme, "panel.margin", { 0, 0, 0, 0 }));
m_scrollSpeed = getThemeValue<f32>(theme, "panel.scrollSpeed", 0.8f); m_scrollSpeed = getThemeValue<f32>(theme, "panel.scrollSpeed", 0.8f);
m_scrollSmoothFactor = std::clamp(getThemeValue<f32>(theme, "panel.scrollSmoothFactor", 0.7f), 0.0f, 1.0f);
m_basePadding = getPadding(); m_basePadding = getPadding();
m_titleColor = getThemeValue<Color>(theme, "panel.titleColor", Colors::Black); m_titleColor = getThemeValue<Color>(theme, "panel.titleColor", Colors::Black);
m_titlebarColor = getThemeValue<Color>(theme, "panel.titlebarColor", Colors::Transparent); m_titlebarColor = getThemeValue<Color>(theme, "panel.titlebarColor", Colors::Transparent);
@ -95,19 +101,15 @@ namespace ogfx
{ {
if (!isScrollAllowed()) if (!isScrollAllowed())
return; return;
if (std::abs(event.mouse->scrollAmount.y) > 0)
m_scrollVelocity.y += m_scrollSpeed * event.mouse->scrollAmount.y * 15.0f;
if (std::abs(event.mouse->scrollAmount.x) > 0)
m_scrollVelocity.x += m_scrollSpeed * event.mouse->scrollAmount.x * 15.0f;
if (m_smoothScrollTimer.isStopped()) if (m_smoothScrollTimer.isStopped())
m_smoothScrollTimer.restart(); m_smoothScrollTimer.restart();
f32 offset_y = 0;
if (event.mouse->scroll == MouseEventData::eScrollDirection::Down)
{
m_scrollTarget += (m_scrollSpeed * event.mouse->scrollAmount.y);
}
else if (event.mouse->scroll == MouseEventData::eScrollDirection::Up)
{
m_scrollTarget += (m_scrollSpeed * event.mouse->scrollAmount.y);
}
event.handle(); event.handle();
} }
@ -146,24 +148,30 @@ namespace ogfx
{ {
auto ext = getContentExtents(); auto ext = getContentExtents();
auto cont = getContentBounds(); auto cont = getContentBounds();
f32 maxScroll = -(ext.h - cont.h); f32 maxScrollY = -(ext.h - cont.h);
f32 maxScrollX = -(ext.w - cont.w);
m_scrollOffset = offset; m_scrollOffset = offset;
if (m_scrollOffset.y < maxScroll)
m_scrollOffset.y = maxScroll; if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY;
if (m_scrollOffset.y > 0) if (m_scrollOffset.y > 0) m_scrollOffset.y = 0;
m_scrollOffset.y = 0; if (m_scrollOffset.x < maxScrollX) m_scrollOffset.x = maxScrollX;
if (m_scrollOffset.x > 0) m_scrollOffset.x = 0;
} }
void Panel::addScrollOffset(const Vec2& offset) void Panel::addScrollOffset(const Vec2& offset)
{ {
auto ext = getContentExtents(); auto ext = getContentExtents();
auto cont = getContentBounds(); auto cont = getContentBounds();
f32 maxScroll = -(ext.h - cont.h); f32 maxScrollY = -(ext.h - cont.h);
f32 maxScrollX = -(ext.w - cont.w);
m_scrollOffset += offset; m_scrollOffset += offset;
if (m_scrollOffset.y < maxScroll)
m_scrollOffset.y = maxScroll; if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY;
if (m_scrollOffset.y > 0) if (m_scrollOffset.y > 0) m_scrollOffset.y = 0;
m_scrollOffset.y = 0; if (m_scrollOffset.x < maxScrollX) m_scrollOffset.x = maxScrollX;
if (m_scrollOffset.x > 0) m_scrollOffset.x = 0;
} }
bool Panel::needsScroll(void) const bool Panel::needsScroll(void) const

View file

@ -83,8 +83,8 @@ namespace ogfx
i32 m_titleTextAlign { 0 }; i32 m_titleTextAlign { 0 };
f32 m_scrollSpeed { 0.8f }; f32 m_scrollSpeed { 0.8f };
f32 m_scrollTarget { 0.0f }; Vec2 m_scrollVelocity { 0.0f, 0.0f };
f32 m_currentScroll { 0.0f }; f32 m_scrollSmoothFactor { 0.7f };
}; };
} }
} }

View file

@ -597,11 +597,10 @@ namespace ostd
StepTimer& StepTimer::create(f64 updatesPerSecond, StepTimer::Callback callback, StopConditionCallback stopCondition, bool stopped) StepTimer& StepTimer::create(f64 updatesPerSecond, StepTimer::Callback callback, bool stopped)
{ {
m_targetDt = 1.0 / updatesPerSecond; m_targetDt = 1.0 / updatesPerSecond;
m_callback = std::move(callback); m_callback = std::move(callback);
m_stopCondition = std::move(stopCondition);
m_prevTime = Clock::now(); m_prevTime = Clock::now();
m_accumulator = 0.0; m_accumulator = 0.0;
m_stopped = stopped; m_stopped = stopped;
@ -615,6 +614,8 @@ namespace ostd
if (m_stopCondition && m_stopCondition()) if (m_stopCondition && m_stopCondition())
{ {
m_stopped = true; m_stopped = true;
if (m_stopCallback)
m_stopCallback();
return; return;
} }

View file

@ -131,8 +131,8 @@ namespace ostd
StepTimer& create(f64 updatesPerSecond, Callback callback, bool stopped = false); StepTimer& create(f64 updatesPerSecond, Callback callback, bool stopped = false);
void update(void); void update(void);
void reset(void); void reset(void);
inline void setStopCondition(StopConditionCallback stopCondition) { m_stopCondition = stopCondition; } inline void setStopCondition(StopConditionCallback stopCondition) { m_stopCondition = std::move(stopCondition); }
inline void setStopCallback(StopCallback callback) { m_stopCallback = callback; } inline void setStopCallback(StopCallback callback) { m_stopCallback = std::move(callback); }
inline void restart(void) { reset(); } inline void restart(void) { reset(); }
inline void stop(void) { m_stopped = true; } inline void stop(void) { m_stopped = true; }
inline f64 getInterpolationAlpha(void) const { return m_valid && m_targetDt > 0.0 ? m_accumulator / m_targetDt : 0.0; } inline f64 getInterpolationAlpha(void) const { return m_valid && m_targetDt > 0.0 ? m_accumulator / m_targetDt : 0.0; }