diff --git a/include/hyprutils/animation/AnimatedVariable.hpp b/include/hyprutils/animation/AnimatedVariable.hpp index 5abe4c7..cc56434 100644 --- a/include/hyprutils/animation/AnimatedVariable.hpp +++ b/include/hyprutils/animation/AnimatedVariable.hpp @@ -4,18 +4,13 @@ #include "../memory/WeakPtr.hpp" #include "../memory/SharedPtr.hpp" #include "../signal/Signal.hpp" +#include "AnimationManager.hpp" #include #include namespace Hyprutils { namespace Animation { - class CAnimationManager; - - struct SAnimVarEvents { - Signal::CSignal connect; - Signal::CSignal disconnect; - }; /* A base class for animated variables. */ class CBaseAnimatedVariable { @@ -26,7 +21,7 @@ namespace Hyprutils { ; // m_bDummy = true; }; - void create(int, Memory::CSharedPointer, Memory::CSharedPointer events); + void create(CAnimationManager*, int, Memory::CSharedPointer); void connectToActive(); void disconnectFromActive(); @@ -42,7 +37,8 @@ namespace Hyprutils { CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete; CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete; - void setConfig(Memory::CSharedPointer pConfig) { + // + void setConfig(Memory::CSharedPointer pConfig) { m_pConfig = pConfig; } @@ -57,9 +53,8 @@ namespace Hyprutils { /* returns the spent (completion) % */ float getPercent() const; - /* returns the current curve value. - needs a reference to the animationmgr to get the bezier curve with the configured name from it */ - float getCurveValue(CAnimationManager*) const; + /* returns the current curve value. */ + float getCurveValue() const; /* checks if an animation is in progress */ bool isBeingAnimated() const { @@ -90,17 +85,22 @@ namespace Hyprutils { void onAnimationEnd(); void onAnimationBegin(); + /* returns whether the parent CAnimationManager is dead */ + bool isAnimationManagerDead() const; + int m_Type = -1; protected: friend class CAnimationManager; - bool m_bIsConnectedToActive = false; - bool m_bIsBeingAnimated = false; + CAnimationManager* m_pAnimationManager = nullptr; + + bool m_bIsConnectedToActive = false; + bool m_bIsBeingAnimated = false; - Memory::CWeakPointer m_pSelf; + Memory::CWeakPointer m_pSelf; - Memory::CWeakPointer m_events; + Memory::CWeakPointer m_pSignals; private: Memory::CWeakPointer m_pConfig; @@ -136,13 +136,13 @@ namespace Hyprutils { public: CGenericAnimatedVariable() = default; - void create(const int typeInfo, Memory::CSharedPointer> pSelf, Memory::CSharedPointer events, + void create(const int typeInfo, CAnimationManager* pAnimationManager, Memory::CSharedPointer> pSelf, const VarType& initialValue) { m_Begun = initialValue; m_Value = initialValue; m_Goal = initialValue; - CBaseAnimatedVariable::create(typeInfo, pSelf, events); + CBaseAnimatedVariable::create(pAnimationManager, typeInfo, pSelf); } CGenericAnimatedVariable(const CGenericAnimatedVariable&) = delete; diff --git a/include/hyprutils/animation/AnimationManager.hpp b/include/hyprutils/animation/AnimationManager.hpp index b3d35d4..1266e2d 100644 --- a/include/hyprutils/animation/AnimationManager.hpp +++ b/include/hyprutils/animation/AnimationManager.hpp @@ -1,7 +1,6 @@ #pragma once #include "./BezierCurve.hpp" -#include "./AnimatedVariable.hpp" #include "../math/Vector2D.hpp" #include "../memory/WeakPtr.hpp" #include "../signal/Signal.hpp" @@ -12,6 +11,8 @@ namespace Hyprutils { namespace Animation { + class CBaseAnimatedVariable; + /* A class for managing bezier curves and variables that are being animated. */ class CAnimationManager { public: @@ -33,25 +34,30 @@ namespace Hyprutils { const std::unordered_map>& getAllBeziers(); - Memory::CSharedPointer getEvents() const; + struct SAnimationManagerSignals { + Signal::CSignal connect; // WP + Signal::CSignal disconnect; // WP + }; + + Memory::CWeakPointer getSignals() const; - std::vector> m_vActiveAnimatedVariables; - Memory::CSharedPointer m_events; + std::vector> m_vActiveAnimatedVariables; private: std::unordered_map> m_mBezierCurves; bool m_bTickScheduled = false; - void connectListener(std::any data); - void disconnectListener(std::any data); + void onConnect(std::any data); + void onDisconnect(std::any data); - struct { + struct SAnimVarListeners { Signal::CHyprSignalListener connect; Signal::CHyprSignalListener disconnect; - } m_sListeners; + }; - friend class CBaseAnimatedVariable; + Memory::CUniquePointer m_listeners; + Memory::CUniquePointer m_events; }; } } diff --git a/src/animation/AnimatedVariable.cpp b/src/animation/AnimatedVariable.cpp index f18a187..69c66af 100644 --- a/src/animation/AnimatedVariable.cpp +++ b/src/animation/AnimatedVariable.cpp @@ -8,28 +8,28 @@ using namespace Hyprutils::Memory; #define SP CSharedPointer #define WP CWeakPointer -void CBaseAnimatedVariable::create(int typeInfo, SP pSelf, SP events) { +void CBaseAnimatedVariable::create(CAnimationManager* pManager, int typeInfo, SP pSelf) { m_Type = typeInfo; m_pSelf = pSelf; - m_events = events; - m_bDummy = false; + m_pAnimationManager = pManager; + m_pSignals = pManager->getSignals(); + m_bDummy = false; } void CBaseAnimatedVariable::connectToActive() { - if (m_bDummy || m_bIsConnectedToActive) + if (m_bDummy || m_bIsConnectedToActive || isAnimationManagerDead()) return; - if (const auto PEVENTS = m_events.lock()) { - PEVENTS->connect.emit(m_pSelf.lock()); - m_bIsConnectedToActive = true; - } + m_pSignals->connect.emit(m_pSelf); + m_bIsConnectedToActive = true; } void CBaseAnimatedVariable::disconnectFromActive() { - if (const auto PEVENTS = m_events.lock()) - PEVENTS->disconnect.emit(static_cast(this)); + if (isAnimationManagerDead()) + return; + m_pSignals->disconnect.emit(m_pSelf); m_bIsConnectedToActive = false; } @@ -75,8 +75,8 @@ float CBaseAnimatedVariable::getPercent() const { return 1.f; } -float CBaseAnimatedVariable::getCurveValue(CAnimationManager* pAnimationManager) const { - if (!m_bIsBeingAnimated || !pAnimationManager) +float CBaseAnimatedVariable::getCurveValue() const { + if (!m_bIsBeingAnimated || isAnimationManagerDead()) return 1.f; std::string bezierName = ""; @@ -86,7 +86,7 @@ float CBaseAnimatedVariable::getCurveValue(CAnimationManager* pAnimationManager) bezierName = PVALUES->internalBezier; } - const auto BEZIER = pAnimationManager->getBezier(bezierName); + const auto BEZIER = m_pAnimationManager->getBezier(bezierName); if (!BEZIER) return 1.f; @@ -98,7 +98,7 @@ float CBaseAnimatedVariable::getCurveValue(CAnimationManager* pAnimationManager) } bool CBaseAnimatedVariable::ok() const { - return m_pConfig && !m_bDummy && !m_events.expired(); + return m_pConfig && !m_bDummy && !isAnimationManagerDead(); } void CBaseAnimatedVariable::onUpdate() { @@ -155,3 +155,7 @@ void CBaseAnimatedVariable::onAnimationBegin() { m_fBeginCallback = nullptr; // reset } } + +bool CBaseAnimatedVariable::isAnimationManagerDead() const { + return m_pSignals.expired(); +} diff --git a/src/animation/AnimationManager.cpp b/src/animation/AnimationManager.cpp index 0eb93bb..0089e35 100644 --- a/src/animation/AnimationManager.cpp +++ b/src/animation/AnimationManager.cpp @@ -1,4 +1,5 @@ #include +#include using namespace Hyprutils::Animation; using namespace Hyprutils::Math; @@ -6,6 +7,7 @@ using namespace Hyprutils::Memory; using namespace Hyprutils::Signal; #define SP CSharedPointer +#define WP CWeakPointer const std::array DEFAULTBEZIERPOINTS = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)}; @@ -14,18 +16,19 @@ CAnimationManager::CAnimationManager() { BEZIER->setup(DEFAULTBEZIERPOINTS); m_mBezierCurves["default"] = BEZIER; - m_events = makeShared(); + m_events = makeUnique(); + m_listeners = makeUnique(); - m_sListeners.connect = m_events->connect.registerListener([this](std::any data) { connectListener(data); }); - m_sListeners.disconnect = m_events->disconnect.registerListener([this](std::any data) { disconnectListener(data); }); + m_listeners->connect = m_events->connect.registerListener([this](std::any data) { onConnect(data); }); + m_listeners->disconnect = m_events->disconnect.registerListener([this](std::any data) { onDisconnect(data); }); } -void CAnimationManager::connectListener(std::any data) { +void CAnimationManager::onConnect(std::any data) { if (!m_bTickScheduled) scheduleTick(); try { - const auto PAV = std::any_cast>(data); + const auto PAV = std::any_cast>(data); if (!PAV) return; @@ -33,13 +36,13 @@ void CAnimationManager::connectListener(std::any data) { } catch (const std::bad_any_cast&) { return; } } -void CAnimationManager::disconnectListener(std::any data) { +void CAnimationManager::onDisconnect(std::any data) { try { - const auto PAV = std::any_cast(data); + const auto PAV = std::any_cast>(data); if (!PAV) return; - std::erase_if(m_vActiveAnimatedVariables, [&](const auto& other) { return other.get() == PAV; }); + std::erase_if(m_vActiveAnimatedVariables, [&](const auto& other) { return !other || other == PAV; }); } catch (const std::bad_any_cast&) { return; } } @@ -104,3 +107,7 @@ SP CAnimationManager::getBezier(const std::string& name) { const std::unordered_map>& CAnimationManager::getAllBeziers() { return m_mBezierCurves; } + +CWeakPointer CAnimationManager::getSignals() const { + return m_events; +} diff --git a/tests/animation.cpp b/tests/animation.cpp index bec7c47..971afac 100644 --- a/tests/animation.cpp +++ b/tests/animation.cpp @@ -93,7 +93,7 @@ class CMyAnimationManager : public CAnimationManager { constexpr const eAVTypes EAVTYPE = std::is_same_v ? eAVTypes::INT : eAVTypes::TEST; const auto PAV = makeShared>(); - PAV->create(EAVTYPE, PAV, m_events, v); + PAV->create(EAVTYPE, static_cast(this), PAV, v); PAV->setConfig(animationTree.getConfig(animationConfigName)); av = std::move(PAV); } @@ -339,9 +339,9 @@ int main(int argc, char** argv, char** envp) { // test getCurveValue *s.m_iA = 0; - EXPECT(s.m_iA->getCurveValue(pAnimationManager.get()), 0.f); + EXPECT(s.m_iA->getCurveValue(), 0.f); s.m_iA->warp(); - EXPECT(s.m_iA->getCurveValue(pAnimationManager.get()), 1.f); + EXPECT(s.m_iA->getCurveValue(), 1.f); EXPECT(endCallbackRan, 6); // Test duplicate active anim vars are not allowed @@ -365,6 +365,7 @@ int main(int argc, char** argv, char** envp) { pAnimationManager->createAnimation(1, a, "default"); *a = 10; pAnimationManager.reset(); + EXPECT(a->isAnimationManagerDead(), true); a->setValueAndWarp(11); EXPECT(a->value(), 11); *a = 12;