Sync push

This commit is contained in:
OmniaX-Dev 2026-04-18 07:27:46 +02:00
parent e2287c06f0
commit d618de0981
7 changed files with 108 additions and 42 deletions

View file

@ -30,7 +30,7 @@ window.backgroundColor = rgba(160, 160, 160, 255)
titlebarHeight = 18 titlebarHeight = 18
titlebarFontSize = 18 titlebarFontSize = 18
titlebarTextAlign = text_left titlebarTextAlign = text_left
scrollSpeed = vec2(0.8, 0.8) scrollSpeed = 15.0
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

@ -21,6 +21,7 @@
#pragma once #pragma once
#include <ostd/data/BaseObject.hpp> #include <ostd/data/BaseObject.hpp>
#include <ostd/math/Geometry.hpp>
namespace ogfx namespace ogfx
{ {
@ -48,7 +49,7 @@ namespace ogfx
class MouseEventData : public ostd::BaseObject class MouseEventData : public ostd::BaseObject
{ {
public: enum class eButton { None = 0, Left, Middle, Right }; public: enum class eButton { None = 0, Left, Middle, Right };
public: enum class eScrollDirection { None = 0, Up, Down }; public: enum class eScrollDirection { None = 0, Up, Down, Left, Right };
public: public:
inline MouseEventData(WindowCore& parent, f32 mousex, f32 mousey, eButton btn) : parentWindow(parent), position_x(mousex), position_y(mousey), button(btn) inline MouseEventData(WindowCore& parent, f32 mousex, f32 mousey, eButton btn) : parentWindow(parent), position_x(mousex), position_y(mousey), button(btn)
{ {
@ -61,7 +62,7 @@ namespace ogfx
f32 position_y; f32 position_y;
eButton button; eButton button;
eScrollDirection scroll { eScrollDirection::None }; eScrollDirection scroll { eScrollDirection::None };
f32 scrollAmount { 0 }; Vec2 scrollAmount { 0 };
gui::Widget* mousePressedOnWidget { nullptr }; gui::Widget* mousePressedOnWidget { nullptr };
WindowCore& parentWindow; WindowCore& parentWindow;
}; };

View file

@ -462,16 +462,36 @@ namespace ogfx
else if (event.type == SDL_EVENT_MOUSE_WHEEL) else if (event.type == SDL_EVENT_MOUSE_WHEEL)
{ {
MouseEventData mmd = get_mouse_state(event); MouseEventData mmd = get_mouse_state(event);
f32 delta = event.wheel.y; f32 deltaY = event.wheel.y;
f32 deltaX = event.wheel.x;
if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
delta = -delta; deltaY = -deltaY;
if (delta < 0) if (deltaY < 0)
{
mmd.scroll = MouseEventData::eScrollDirection::Down; mmd.scroll = MouseEventData::eScrollDirection::Down;
else if (delta > 0) mmd.scrollAmount = { 0.0f, deltaY };
}
else if (deltaY > 0)
{
mmd.scroll = MouseEventData::eScrollDirection::Up; mmd.scroll = MouseEventData::eScrollDirection::Up;
mmd.scrollAmount = { 0.0f, deltaY };
}
else if (deltaX < 0)
{
mmd.scroll = MouseEventData::eScrollDirection::Right;
mmd.scrollAmount = { deltaX, 0.0f };
}
else if (deltaX > 0)
{
mmd.scroll = MouseEventData::eScrollDirection::Left;
mmd.scrollAmount = { deltaX, 0.0f };
}
else else
{
mmd.scroll = MouseEventData::eScrollDirection::None; mmd.scroll = MouseEventData::eScrollDirection::None;
mmd.scrollAmount = delta; mmd.scrollAmount = { 0.0f, 0.0f };
}
ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::MouseScrolled, ostd::Signal::Priority::RealTime, mmd); ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::MouseScrolled, ostd::Signal::Priority::RealTime, mmd);
} }
else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN)

View file

@ -39,6 +39,15 @@ 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 {
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;
}, true);
validate(); validate();
return *this; return *this;
} }
@ -53,7 +62,7 @@ namespace ogfx
setBorderColor(getThemeValue<Color>(theme, "panel.borderColor", Colors::Black)); setBorderColor(getThemeValue<Color>(theme, "panel.borderColor", Colors::Black));
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<Vec2>(theme, "panel.scrollSpeed", { 0.0f, 0.8f }); m_scrollSpeed = getThemeValue<f32>(theme, "panel.scrollSpeed", 0.8f);
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);
@ -71,6 +80,11 @@ namespace ogfx
// gfx.fillRect(getContentExtents() + Rectangle { getGlobalPosition(), 0, 0 }, { 80, 0, 0, 30 }); // gfx.fillRect(getContentExtents() + Rectangle { getGlobalPosition(), 0, 0 }, { 80, 0, 0, 30 });
} }
void Panel::onUpdate(void)
{
m_smoothScrollTimer.update();
}
void Panel::afterDraw(ogfx::BasicRenderer2D& gfx) void Panel::afterDraw(ogfx::BasicRenderer2D& gfx)
{ {
draw_titlebar(gfx); draw_titlebar(gfx);
@ -81,12 +95,19 @@ namespace ogfx
{ {
if (!isScrollAllowed()) if (!isScrollAllowed())
return; return;
if (m_smoothScrollTimer.isStopped())
m_smoothScrollTimer.restart();
f32 offset_y = 0; f32 offset_y = 0;
if (event.mouse->scroll == MouseEventData::eScrollDirection::Down) if (event.mouse->scroll == MouseEventData::eScrollDirection::Down)
offset_y = (m_scrollSpeed.y * event.mouse->scrollAmount * 15.0f); {
m_scrollTarget += (m_scrollSpeed * event.mouse->scrollAmount.y);
}
else if (event.mouse->scroll == MouseEventData::eScrollDirection::Up) else if (event.mouse->scroll == MouseEventData::eScrollDirection::Up)
offset_y = (m_scrollSpeed.y * event.mouse->scrollAmount * 15.0f); {
addScrollOffset({ 0, offset_y });
m_scrollTarget += (m_scrollSpeed * event.mouse->scrollAmount.y);
}
event.handle(); event.handle();
} }

View file

@ -22,6 +22,7 @@
#include <ogfx/gui/widgets/Widget.hpp> #include <ogfx/gui/widgets/Widget.hpp>
#include <ogfx/gui/widgets/Scrollbar.hpp> #include <ogfx/gui/widgets/Scrollbar.hpp>
#include <ostd/utils/Time.hpp>
namespace ogfx namespace ogfx
{ {
@ -46,6 +47,7 @@ namespace ogfx
Panel& create(void); Panel& create(void);
void applyTheme(const ostd::Stylesheet& theme) override; void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override; void onDraw(ogfx::BasicRenderer2D& gfx) override;
void onUpdate(void) override;
void afterDraw(ogfx::BasicRenderer2D& gfx) override; void afterDraw(ogfx::BasicRenderer2D& gfx) override;
void onMouseScrolled(const Event& event) override; void onMouseScrolled(const Event& event) override;
void setTitlebarType(const String& type); void setTitlebarType(const String& type);
@ -68,6 +70,7 @@ namespace ogfx
String m_title { "Panel" }; String m_title { "Panel" };
Vec2 m_scrollOffset { 0, 0 }; Vec2 m_scrollOffset { 0, 0 };
VerticalScrollBar m_scrollbar { getWindow() }; VerticalScrollBar m_scrollbar { getWindow() };
ostd::StepTimer m_smoothScrollTimer;
Color m_titleColor { Colors::Black }; Color m_titleColor { Colors::Black };
i32 m_titlebarType = TitleBarTypes::NoneValue; i32 m_titlebarType = TitleBarTypes::NoneValue;
@ -78,7 +81,10 @@ namespace ogfx
Color m_titlebarBorderColor { Colors::Black }; Color m_titlebarBorderColor { Colors::Black };
Rectangle m_basePadding { 0, 0, 0, 0 }; Rectangle m_basePadding { 0, 0, 0, 0 };
i32 m_titleTextAlign { 0 }; i32 m_titleTextAlign { 0 };
Vec2 m_scrollSpeed { 0.8f, 0.8f }; f32 m_scrollSpeed { 0.8f };
f32 m_scrollTarget { 0.0f };
f32 m_currentScroll { 0.0f };
}; };
} }
} }

View file

@ -597,19 +597,26 @@ namespace ostd
StepTimer& StepTimer::create(f64 updatesPerSecond, StepTimer::Callback callback) StepTimer& StepTimer::create(f64 updatesPerSecond, StepTimer::Callback callback, StopConditionCallback stopCondition, 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_valid = true; m_valid = true;
return *this; return *this;
} }
void StepTimer::update(void) void StepTimer::update(void)
{ {
if (!m_valid) return; if (!m_valid || m_stopped || !m_callback) return;
if (m_stopCondition && m_stopCondition())
{
m_stopped = true;
return;
}
TimePoint currentTime = Clock::now(); TimePoint currentTime = Clock::now();
Duration frameDuration = currentTime - m_prevTime; Duration frameDuration = currentTime - m_prevTime;
@ -638,6 +645,7 @@ namespace ostd
{ {
m_accumulator = 0.0; m_accumulator = 0.0;
m_prevTime = Clock::now(); m_prevTime = Clock::now();
m_stopped = false;
} }
} }

View file

@ -1,21 +1,21 @@
/* /*
OmniaFramework - A collection of useful functionality OmniaFramework - A collection of useful functionality
Copyright (C) 2025 OmniaX-Dev Copyright (C) 2025 OmniaX-Dev
This file is part of OmniaFramework. This file is part of OmniaFramework.
OmniaFramework is free software: you can redistribute it and/or modify OmniaFramework is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
OmniaFramework is distributed in the hope that it will be useful, OmniaFramework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>. along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
@ -118,27 +118,37 @@ namespace ostd
class StepTimer class StepTimer
{ {
public: public:
using Callback = std::function<void(f64 dt)>; using Callback = std::function<void(f64 dt)>;
using StopConditionCallback = std::function<bool(void)>;
using StopCallback = std::function<void(void)>;
using Clock = std::chrono::high_resolution_clock; using Clock = std::chrono::high_resolution_clock;
using TimePoint = Clock::time_point; using TimePoint = Clock::time_point;
using Duration = Clock::duration; using Duration = Clock::duration;
public: public:
StepTimer() = default; StepTimer() = default;
inline StepTimer(f64 updatesPerSecond, Callback callback) { create(updatesPerSecond, callback); } inline StepTimer(f64 updatesPerSecond, Callback callback, bool stopped = false) { create(updatesPerSecond, callback, stopped); }
StepTimer& create(f64 updatesPerSecond, Callback callback); 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 setStopCallback(StopCallback callback) { m_stopCallback = 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; } inline f64 getInterpolationAlpha(void) const { return m_valid && m_targetDt > 0.0 ? m_accumulator / m_targetDt : 0.0; }
inline void invalidate(void) { m_valid = false; } inline void invalidate(void) { m_valid = false; }
inline bool isValid(void) const { return m_valid; } inline bool isValid(void) const { return m_valid; }
inline bool isStopped(void) const { return m_stopped; }
private: private:
TimePoint m_prevTime; TimePoint m_prevTime;
f64 m_targetDt { 0.0 }; f64 m_targetDt { 0.0 };
Callback m_callback { nullptr }; Callback m_callback { nullptr };
f64 m_accumulator { 0.0 }; StopConditionCallback m_stopCondition { nullptr };
bool m_valid { false }; StopCallback m_stopCallback { nullptr };
f64 m_accumulator { 0.0 };
bool m_valid { false };
bool m_stopped { false };
}; };
struct GameClock struct GameClock