From 4e17d6e40cc1dc69cc75de2e75e55ebb4ef9a8bd Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Fri, 24 Apr 2026 10:06:45 +0300 Subject: [PATCH] Attempt to add GUI animations --- include/Helpers/BezierEasing.cpp | 2 + include/Helpers/BezierEasing.hpp | 2 + src/GUIStuff/Elements/LayoutElement.cpp | 54 +++++++++++++++++++++++++ src/GUIStuff/Elements/LayoutElement.hpp | 21 ++++++++++ 4 files changed, 79 insertions(+) diff --git a/include/Helpers/BezierEasing.cpp b/include/Helpers/BezierEasing.cpp index e453afd..f7c2e3b 100644 --- a/include/Helpers/BezierEasing.cpp +++ b/include/Helpers/BezierEasing.cpp @@ -9,6 +9,8 @@ BezierEasing BezierEasing::linear{0.0, 1.0, 0.0, 1.0}; +BezierEasing::BezierEasing() {} + BezierEasing::BezierEasing(Eigen::Vector4f c): BezierEasing(c.x(), c.y(), c.z(), c.w()) {} diff --git a/include/Helpers/BezierEasing.hpp b/include/Helpers/BezierEasing.hpp index 9d7e08c..292e8d8 100644 --- a/include/Helpers/BezierEasing.hpp +++ b/include/Helpers/BezierEasing.hpp @@ -11,8 +11,10 @@ class BezierEasing { public: + BezierEasing(); BezierEasing(Eigen::Vector4f c); BezierEasing(float x1, float y1, float x2, float y2); + BezierEasing& operator=(const BezierEasing& b) = default; float operator() (float x) const; static BezierEasing linear; private: diff --git a/src/GUIStuff/Elements/LayoutElement.cpp b/src/GUIStuff/Elements/LayoutElement.cpp index e8d3fcf..a546fa7 100644 --- a/src/GUIStuff/Elements/LayoutElement.cpp +++ b/src/GUIStuff/Elements/LayoutElement.cpp @@ -1,5 +1,6 @@ #include "LayoutElement.hpp" #include "Helpers/ConvertVec.hpp" +#include "../GUIManager.hpp" namespace GUIStuff { @@ -10,6 +11,59 @@ void LayoutElement::layout(const Clay_ElementId& id, const std::function= animation.anim.duration) { + animation.currentTime = animation.anim.duration; + animation.state = InternalFloatAnimation::State::DONE; + } + gui.set_to_layout(); + break; + } + case InternalFloatAnimation::State::RUN_REVERSE: { + animation.currentTime -= gui.io.deltaTime; + if(animation.currentTime <= 0.0f) { + animation.currentTime = 0.0f; + animation.state = InternalFloatAnimation::State::DONE; + } + gui.set_to_layout(); + break; + } + case InternalFloatAnimation::State::DONE: + break; + } + } +} + +float LayoutElement::get_float_animation(const char* animationID, const FloatAnimation& animation) { + InternalFloatAnimation internalAnim; + internalAnim.anim = animation; + auto [it, placed] = animations.emplace(animationID, internalAnim); + const InternalFloatAnimation& actualInternalAnim = it->second; + return std::lerp(actualInternalAnim.anim.startVal, actualInternalAnim.anim.endVal, actualInternalAnim.anim.easing(it->second.currentTime / actualInternalAnim.anim.duration)); +} + +void LayoutElement::animation_trigger(const char* animationID) { + auto it = animations.find(animationID); + if(it != animations.end()) { + InternalFloatAnimation& animation = it->second; + if(animation.currentTime < animation.anim.duration) + animation.state = InternalFloatAnimation::State::RUN; + } +} + +void LayoutElement::animation_trigger_reverse(const char* animationID) { + auto it = animations.find(animationID); + if(it != animations.end()) { + InternalFloatAnimation& animation = it->second; + if(animation.currentTime > 0.0f) + animation.state = InternalFloatAnimation::State::RUN_REVERSE; + } +} + void LayoutElement::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { if(c.mouseButton) c.mouseButton(this, button); } diff --git a/src/GUIStuff/Elements/LayoutElement.hpp b/src/GUIStuff/Elements/LayoutElement.hpp index beba2e5..a9fe97a 100644 --- a/src/GUIStuff/Elements/LayoutElement.hpp +++ b/src/GUIStuff/Elements/LayoutElement.hpp @@ -1,5 +1,6 @@ #pragma once #include "Element.hpp" +#include "Helpers/BezierEasing.hpp" namespace GUIStuff { @@ -12,12 +13,32 @@ class LayoutElement : public Element { std::function mouseWheel; std::function key; }; + struct FloatAnimation { + float startVal = 0.0f; + float endVal = 1.0f; + float duration = 1.0f; + BezierEasing easing = BezierEasing::linear; + }; void layout(const Clay_ElementId& id, const std::function& layout, const Callbacks& c = {}); + virtual void update() override; + float get_float_animation(const char* animationID, const FloatAnimation& animation); + void animation_trigger(const char* animationID); + void animation_trigger_reverse(const char* animationID); virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override; virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override; virtual void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) override; virtual void input_key_callback(const InputManager::KeyCallbackArgs& key) override; private: + struct InternalFloatAnimation { + enum class State { + RUN, + RUN_REVERSE, + DONE + } state = State::DONE; + float currentTime = 0.0f; + FloatAnimation anim; + }; + std::unordered_map animations; Callbacks c; };