-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
animation: add BezierCurve, AnimationManager and AnimatedVariable (#27)
- Loading branch information
1 parent
8f15d45
commit 8af7e4b
Showing
8 changed files
with
841 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
#pragma once | ||
|
||
#include "../memory/WeakPtr.hpp" | ||
#include "hyprutils/memory/SharedPtr.hpp" | ||
|
||
#include <functional> | ||
#include <chrono> | ||
|
||
namespace Hyprutils { | ||
namespace Animation { | ||
class CAnimationManager; | ||
|
||
/* | ||
Structure for animation properties. | ||
Config properties need to have a static lifetime to allow for config reload. | ||
*/ | ||
struct SAnimationPropertyConfig { | ||
bool overridden = true; | ||
|
||
std::string internalBezier = ""; | ||
std::string internalStyle = ""; | ||
float internalSpeed = 0.f; | ||
int internalEnabled = -1; | ||
|
||
Memory::CWeakPointer<SAnimationPropertyConfig> pValues; | ||
Memory::CWeakPointer<SAnimationPropertyConfig> pParentAnimation; | ||
}; | ||
|
||
/* A base class for animated variables. */ | ||
class CBaseAnimatedVariable { | ||
public: | ||
using CallbackFun = std::function<void(Memory::CWeakPointer<CBaseAnimatedVariable> thisptr)>; | ||
|
||
CBaseAnimatedVariable() { | ||
; // m_bDummy = true; | ||
}; | ||
|
||
void create(CAnimationManager*, int, Memory::CSharedPointer<CBaseAnimatedVariable>); | ||
void connectToActive(); | ||
void disconnectFromActive(); | ||
|
||
/* Needs to call disconnectFromActive to remove `m_pSelf` from the active animation list */ | ||
virtual ~CBaseAnimatedVariable() { | ||
disconnectFromActive(); | ||
}; | ||
|
||
virtual void warp(bool endCallback = true) = 0; | ||
|
||
CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete; | ||
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete; | ||
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete; | ||
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete; | ||
|
||
void setConfig(Memory::CSharedPointer<SAnimationPropertyConfig> pConfig) { | ||
m_pConfig = pConfig; | ||
} | ||
|
||
Memory::CWeakPointer<SAnimationPropertyConfig> getConfig() const { | ||
return m_pConfig; | ||
} | ||
|
||
bool enabled() const; | ||
const std::string& getBezierName() const; | ||
const std::string& getStyle() const; | ||
|
||
/* returns the spent (completion) % */ | ||
float getPercent() const; | ||
|
||
/* returns the current curve value */ | ||
float getCurveValue() const; | ||
|
||
/* checks if an animation is in progress */ | ||
bool isBeingAnimated() const { | ||
return m_bIsBeingAnimated; | ||
} | ||
|
||
/* checks m_bDummy and m_pAnimationManager */ | ||
bool ok() const; | ||
|
||
/* calls the update callback */ | ||
void onUpdate(); | ||
|
||
/* sets a function to be ran when an animation ended. | ||
if "remove" is set to true, it will remove the callback when ran. */ | ||
void setCallbackOnEnd(CallbackFun func, bool remove = true); | ||
|
||
/* sets a function to be ran when an animation is started. | ||
if "remove" is set to true, it will remove the callback when ran. */ | ||
void setCallbackOnBegin(CallbackFun func, bool remove = true); | ||
|
||
/* sets the update callback, called every time the value is animated and a step is done | ||
Warning: calling unregisterVar/registerVar in this handler will cause UB */ | ||
void setUpdateCallback(CallbackFun func); | ||
|
||
/* resets all callbacks. Does not call any. */ | ||
void resetAllCallbacks(); | ||
|
||
void onAnimationEnd(); | ||
void onAnimationBegin(); | ||
|
||
int m_Type = -1; | ||
|
||
protected: | ||
friend class CAnimationManager; | ||
|
||
bool m_bIsConnectedToActive = false; | ||
bool m_bIsBeingAnimated = false; | ||
|
||
Memory::CWeakPointer<CBaseAnimatedVariable> m_pSelf; | ||
|
||
private: | ||
Memory::CWeakPointer<SAnimationPropertyConfig> m_pConfig; | ||
|
||
std::chrono::steady_clock::time_point animationBegin; | ||
|
||
bool m_bDummy = true; | ||
|
||
CAnimationManager* m_pAnimationManager = nullptr; | ||
bool m_bRemoveEndAfterRan = true; | ||
bool m_bRemoveBeginAfterRan = true; | ||
|
||
CallbackFun m_fEndCallback; | ||
CallbackFun m_fBeginCallback; | ||
CallbackFun m_fUpdateCallback; | ||
}; | ||
|
||
/* This concept represents the minimum requirement for a type to be used with CGenericAnimatedVariable */ | ||
template <class ValueImpl> | ||
concept AnimatedType = requires(ValueImpl val) { | ||
requires std::is_copy_constructible_v<ValueImpl>; | ||
{ val == val } -> std::same_as<bool>; // requires operator== | ||
{ val = val }; // requires operator= | ||
}; | ||
|
||
/* | ||
A generic class for variables. | ||
VarType is the type of the variable to be animated. | ||
AnimationContext is there to attach additional data to the animation. | ||
In Hyprland that struct would contain a reference to window, workspace or layer for example. | ||
*/ | ||
template <AnimatedType VarType, class AnimationContext> | ||
class CGenericAnimatedVariable : public CBaseAnimatedVariable { | ||
public: | ||
CGenericAnimatedVariable() = default; | ||
|
||
void create(const int typeInfo, CAnimationManager* pAnimationManager, Memory::CSharedPointer<CGenericAnimatedVariable<VarType, AnimationContext>> pSelf, | ||
const VarType& initialValue) { | ||
m_Begun = initialValue; | ||
m_Value = initialValue; | ||
m_Goal = initialValue; | ||
|
||
CBaseAnimatedVariable::create(pAnimationManager, typeInfo, pSelf); | ||
} | ||
|
||
CGenericAnimatedVariable(const CGenericAnimatedVariable&) = delete; | ||
CGenericAnimatedVariable(CGenericAnimatedVariable&&) = delete; | ||
CGenericAnimatedVariable& operator=(const CGenericAnimatedVariable&) = delete; | ||
CGenericAnimatedVariable& operator=(CGenericAnimatedVariable&&) = delete; | ||
|
||
virtual void warp(bool endCallback = true) { | ||
if (!m_bIsBeingAnimated) | ||
return; | ||
|
||
m_Value = m_Goal; | ||
|
||
m_bIsBeingAnimated = false; | ||
|
||
onUpdate(); | ||
|
||
if (endCallback) | ||
onAnimationEnd(); | ||
} | ||
|
||
const VarType& value() const { | ||
return m_Value; | ||
} | ||
|
||
/* used to update the value each tick via the AnimationManager */ | ||
VarType& value() { | ||
return m_Value; | ||
} | ||
|
||
const VarType& goal() const { | ||
return m_Goal; | ||
} | ||
|
||
const VarType& begun() const { | ||
return m_Begun; | ||
} | ||
|
||
CGenericAnimatedVariable& operator=(const VarType& v) { | ||
if (v == m_Goal) | ||
return *this; | ||
|
||
m_Goal = v; | ||
m_Begun = m_Value; | ||
|
||
onAnimationBegin(); | ||
|
||
return *this; | ||
} | ||
|
||
/* Sets the actual stored value, without affecting the goal, but resets the timer*/ | ||
void setValue(const VarType& v) { | ||
if (v == m_Value) | ||
return; | ||
|
||
m_Value = v; | ||
m_Begun = m_Value; | ||
|
||
onAnimationBegin(); | ||
} | ||
|
||
/* Sets the actual value and goal*/ | ||
void setValueAndWarp(const VarType& v) { | ||
m_Goal = v; | ||
m_bIsBeingAnimated = true; | ||
|
||
warp(); | ||
} | ||
|
||
AnimationContext m_Context; | ||
|
||
private: | ||
VarType m_Value{}; | ||
VarType m_Goal{}; | ||
VarType m_Begun{}; | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#pragma once | ||
|
||
#include "./BezierCurve.hpp" | ||
#include "./AnimatedVariable.hpp" | ||
#include "../math/Vector2D.hpp" | ||
#include "../memory/WeakPtr.hpp" | ||
|
||
#include <unordered_map> | ||
#include <vector> | ||
|
||
namespace Hyprutils { | ||
namespace Animation { | ||
/* A class for managing bezier curves and variables that are being animated. */ | ||
class CAnimationManager { | ||
public: | ||
CAnimationManager(); | ||
|
||
void tickDone(); | ||
bool shouldTickForNext(); | ||
|
||
virtual void scheduleTick() = 0; | ||
virtual void onTicked() = 0; | ||
|
||
void addBezierWithName(std::string, const Math::Vector2D&, const Math::Vector2D&); | ||
void removeAllBeziers(); | ||
|
||
bool bezierExists(const std::string&); | ||
Memory::CSharedPointer<CBezierCurve> getBezier(const std::string&); | ||
|
||
const std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>>& getAllBeziers(); | ||
|
||
std::vector<Memory::CWeakPointer<CBaseAnimatedVariable>> m_vActiveAnimatedVariables; | ||
|
||
private: | ||
std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>> m_mBezierCurves; | ||
|
||
bool m_bTickScheduled = false; | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#pragma once | ||
|
||
#include <array> | ||
#include <vector> | ||
|
||
#include "../math/Vector2D.hpp" | ||
|
||
namespace Hyprutils { | ||
namespace Animation { | ||
constexpr int BAKEDPOINTS = 255; | ||
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS; | ||
|
||
/* An implementation of a cubic bezier curve. */ | ||
class CBezierCurve { | ||
public: | ||
/* Calculates a cubic bezier curve based on 2 control points (EXCLUDES the 0,0 and 1,1 points). */ | ||
void setup(const std::array<Hyprutils::Math::Vector2D, 2>& points); | ||
|
||
float getYForT(float const& t) const; | ||
float getXForT(float const& t) const; | ||
float getYForPoint(float const& x) const; | ||
|
||
private: | ||
/* this INCLUDES the 0,0 and 1,1 points. */ | ||
std::vector<Hyprutils::Math::Vector2D> m_vPoints; | ||
|
||
std::array<Hyprutils::Math::Vector2D, BAKEDPOINTS> m_aPointsBaked; | ||
}; | ||
} | ||
} |
Oops, something went wrong.