diff --git a/.clangd b/.clangd index c60968a..e6defe1 100644 --- a/.clangd +++ b/.clangd @@ -1,5 +1,4 @@ CompileFlags: CompilationDatabase: bin - Add: ["--target=x86_64-w64-mingw32"] Diagnostics: MissingIncludes: None \ No newline at end of file diff --git a/extra/DefaultTheme.oss b/extra/DefaultTheme.oss index 751a937..f7ebbaa 100644 --- a/extra/DefaultTheme.oss +++ b/extra/DefaultTheme.oss @@ -30,7 +30,8 @@ window.backgroundColor = rgba(160, 160, 160, 255) titlebarHeight = 18 titlebarFontSize = 18 titlebarTextAlign = text_left - scrollSpeed = 15.0 + scrollSpeed = 1.2 + scrollSmoothFactor = 0.7 padding = rect(15, 15, 15, 15) margin = rect(0, 0, 0, 0) } diff --git a/other/build.nr b/other/build.nr index a52986c..5208b65 100644 --- a/other/build.nr +++ b/other/build.nr @@ -1 +1 @@ -2067 +2069 diff --git a/src/ogfx/gui/widgets/Containers.cpp b/src/ogfx/gui/widgets/Containers.cpp index f4bfe21..a079196 100644 --- a/src/ogfx/gui/widgets/Containers.cpp +++ b/src/ogfx/gui/widgets/Containers.cpp @@ -39,15 +39,20 @@ namespace ogfx m_scrollbar.setMargin({ 0, getTitlebarHeight(), 0, 0 }); m_scrollbar.enableManualDraw(true); addWidget(m_scrollbar); - m_smoothScrollTimer.create(30.0f, [&](f64 dt) -> void { - f32 scrollStep = m_scrollTarget / 60.0f; - m_currentScroll += scrollStep; - addScrollOffset({ 0, scrollStep }); - if (m_currentScroll > m_scrollTarget) - m_currentScroll = m_scrollTarget; - }, [&](void) -> bool { - return m_currentScroll == m_scrollTarget; + m_smoothScrollTimer.create(60.0f, [&](f64 dt) -> void { + f32 stepX = m_scrollVelocity.x * (1.0f - m_scrollSmoothFactor); + f32 stepY = m_scrollVelocity.y * (1.0f - m_scrollSmoothFactor); + + addScrollOffset({ stepX, stepY }); + m_scrollVelocity -= { stepX, stepY }; + + 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); + + m_smoothScrollTimer.setStopCondition([&](void) -> bool { + return m_scrollVelocity.x == 0 && m_scrollVelocity.y == 0; + }); validate(); return *this; } @@ -63,6 +68,7 @@ namespace ogfx setPadding(getThemeValue(theme, "panel.padding", { 15, 15, 15, 15 })); setMargin(getThemeValue(theme, "panel.margin", { 0, 0, 0, 0 })); m_scrollSpeed = getThemeValue(theme, "panel.scrollSpeed", 0.8f); + m_scrollSmoothFactor = std::clamp(getThemeValue(theme, "panel.scrollSmoothFactor", 0.7f), 0.0f, 1.0f); m_basePadding = getPadding(); m_titleColor = getThemeValue(theme, "panel.titleColor", Colors::Black); m_titlebarColor = getThemeValue(theme, "panel.titlebarColor", Colors::Transparent); @@ -95,19 +101,15 @@ namespace ogfx { if (!isScrollAllowed()) 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()) 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(); } @@ -146,24 +148,30 @@ namespace ogfx { auto ext = getContentExtents(); auto cont = getContentBounds(); - f32 maxScroll = -(ext.h - cont.h); + f32 maxScrollY = -(ext.h - cont.h); + f32 maxScrollX = -(ext.w - cont.w); + m_scrollOffset = offset; - if (m_scrollOffset.y < maxScroll) - m_scrollOffset.y = maxScroll; - if (m_scrollOffset.y > 0) - m_scrollOffset.y = 0; + + if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY; + if (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) { auto ext = getContentExtents(); auto cont = getContentBounds(); - f32 maxScroll = -(ext.h - cont.h); + f32 maxScrollY = -(ext.h - cont.h); + f32 maxScrollX = -(ext.w - cont.w); + m_scrollOffset += offset; - if (m_scrollOffset.y < maxScroll) - m_scrollOffset.y = maxScroll; - if (m_scrollOffset.y > 0) - m_scrollOffset.y = 0; + + if (m_scrollOffset.y < maxScrollY) m_scrollOffset.y = maxScrollY; + if (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 diff --git a/src/ogfx/gui/widgets/Containers.hpp b/src/ogfx/gui/widgets/Containers.hpp index 6c59c3f..d3d92ab 100644 --- a/src/ogfx/gui/widgets/Containers.hpp +++ b/src/ogfx/gui/widgets/Containers.hpp @@ -83,8 +83,8 @@ namespace ogfx i32 m_titleTextAlign { 0 }; f32 m_scrollSpeed { 0.8f }; - f32 m_scrollTarget { 0.0f }; - f32 m_currentScroll { 0.0f }; + Vec2 m_scrollVelocity { 0.0f, 0.0f }; + f32 m_scrollSmoothFactor { 0.7f }; }; } } diff --git a/src/ostd/utils/Time.cpp b/src/ostd/utils/Time.cpp index 61781b8..e30fd7f 100644 --- a/src/ostd/utils/Time.cpp +++ b/src/ostd/utils/Time.cpp @@ -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_callback = std::move(callback); - m_stopCondition = std::move(stopCondition); m_prevTime = Clock::now(); m_accumulator = 0.0; m_stopped = stopped; @@ -615,6 +614,8 @@ namespace ostd if (m_stopCondition && m_stopCondition()) { m_stopped = true; + if (m_stopCallback) + m_stopCallback(); return; } diff --git a/src/ostd/utils/Time.hpp b/src/ostd/utils/Time.hpp index 1148260..c89e335 100644 --- a/src/ostd/utils/Time.hpp +++ b/src/ostd/utils/Time.hpp @@ -131,8 +131,8 @@ namespace ostd StepTimer& create(f64 updatesPerSecond, Callback callback, bool stopped = false); void update(void); void reset(void); - inline void setStopCondition(StopConditionCallback stopCondition) { m_stopCondition = stopCondition; } - inline void setStopCallback(StopCallback callback) { m_stopCallback = callback; } + inline void setStopCondition(StopConditionCallback stopCondition) { m_stopCondition = std::move(stopCondition); } + inline void setStopCallback(StopCallback callback) { m_stopCallback = std::move(callback); } inline void restart(void) { reset(); } 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; }