animation: use signals to connect and disconnect vars from the manager

This commit is contained in:
Maximilian Seidler 2025-01-26 07:23:34 +01:00
parent ad2ef653da
commit 77ddb222fc
4 changed files with 80 additions and 16 deletions

View file

@ -2,7 +2,8 @@
#include "AnimationConfig.hpp"
#include "../memory/WeakPtr.hpp"
#include "hyprutils/memory/SharedPtr.hpp"
#include "../memory/SharedPtr.hpp"
#include "../signal/Signal.hpp"
#include <functional>
#include <chrono>
@ -93,6 +94,11 @@ namespace Hyprutils {
Memory::CWeakPointer<CBaseAnimatedVariable> m_pSelf;
struct {
Memory::CWeakPointer<Signal::CSignal> connect;
Memory::CWeakPointer<Signal::CSignal> disconnect;
} m_sEvents;
private:
Memory::CWeakPointer<SAnimationPropertyConfig> m_pConfig;
@ -100,13 +106,16 @@ namespace Hyprutils {
bool m_bDummy = true;
CAnimationManager* m_pAnimationManager = nullptr;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
// TODO: remove this pointer. We still need it for getBezier in getCurveValue.
// getCurveValue is only used once in Hyprland. So either remove it or just pass pAnimationManager as a param.
CAnimationManager* m_pAnimationManager = nullptr;
CallbackFun m_fEndCallback;
CallbackFun m_fBeginCallback;
CallbackFun m_fUpdateCallback;
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 */

View file

@ -4,6 +4,7 @@
#include "./AnimatedVariable.hpp"
#include "../math/Vector2D.hpp"
#include "../memory/WeakPtr.hpp"
#include "../signal/Signal.hpp"
#include <unordered_map>
#include <vector>
@ -22,6 +23,9 @@ namespace Hyprutils {
virtual void scheduleTick() = 0;
virtual void onTicked() = 0;
void connectVarListener(std::any data);
void disconnectVarListener(std::any data);
void addBezierWithName(std::string, const Math::Vector2D&, const Math::Vector2D&);
void removeAllBeziers();
@ -36,6 +40,19 @@ namespace Hyprutils {
std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>> m_mBezierCurves;
bool m_bTickScheduled = false;
struct {
Signal::CHyprSignalListener connect;
Signal::CHyprSignalListener disconnect;
} m_sListeners;
struct {
// Those events are shared between animated vars
Memory::CSharedPointer<Signal::CSignal> connect;
Memory::CSharedPointer<Signal::CSignal> disconnect;
} m_sEvents;
friend class CBaseAnimatedVariable;
};
}
}

View file

@ -13,24 +13,26 @@ void CBaseAnimatedVariable::create(Hyprutils::Animation::CAnimationManager* pAni
m_Type = typeInfo;
m_pSelf = pSelf;
m_sEvents.connect = pAnimationManager->m_sEvents.connect;
m_sEvents.disconnect = pAnimationManager->m_sEvents.disconnect;
m_bDummy = false;
}
void CBaseAnimatedVariable::connectToActive() {
if (!m_pAnimationManager || m_bDummy)
if (m_bDummy || m_bIsConnectedToActive)
return;
m_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up
if (!m_bIsConnectedToActive)
m_pAnimationManager->m_vActiveAnimatedVariables.push_back(m_pSelf);
m_bIsConnectedToActive = true;
if (const auto CONNECT = m_sEvents.connect.lock()) {
CONNECT->emit(m_pSelf.lock());
m_bIsConnectedToActive = true;
}
}
void CBaseAnimatedVariable::disconnectFromActive() {
if (!m_pAnimationManager)
return;
if (const auto DISCONNECT = m_sEvents.disconnect.lock())
DISCONNECT->emit(static_cast<void*>(this));
std::erase_if(m_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == m_pSelf; });
m_bIsConnectedToActive = false;
}
@ -80,6 +82,12 @@ float CBaseAnimatedVariable::getCurveValue() const {
if (!m_bIsBeingAnimated || !m_pAnimationManager)
return 1.f;
// Guard against m_pAnimationManager being deleted
// TODO: Remove this and m_pAnimationManager
if (m_sEvents.connect.expired()) {
return 1.f;
}
std::string bezierName = "";
if (const auto PCONFIG = m_pConfig.lock()) {
const auto PVALUES = PCONFIG->pValues.lock();
@ -99,7 +107,7 @@ float CBaseAnimatedVariable::getCurveValue() const {
}
bool CBaseAnimatedVariable::ok() const {
return m_pConfig && m_pAnimationManager;
return m_pConfig && !m_bDummy;
}
void CBaseAnimatedVariable::onUpdate() {

View file

@ -3,6 +3,7 @@
using namespace Hyprutils::Animation;
using namespace Hyprutils::Math;
using namespace Hyprutils::Memory;
using namespace Hyprutils::Signal;
#define SP CSharedPointer
@ -12,6 +13,35 @@ CAnimationManager::CAnimationManager() {
const auto BEZIER = makeShared<CBezierCurve>();
BEZIER->setup(DEFAULTBEZIERPOINTS);
m_mBezierCurves["default"] = BEZIER;
m_sEvents.connect = makeShared<CSignal>();
m_sEvents.disconnect = makeShared<CSignal>();
m_sListeners.connect = m_sEvents.connect->registerListener([this](std::any data) { connectVarListener(data); });
m_sListeners.disconnect = m_sEvents.disconnect->registerListener([this](std::any data) { disconnectVarListener(data); });
}
void CAnimationManager::connectVarListener(std::any data) {
if (!m_bTickScheduled)
scheduleTick();
try {
const auto PAV = std::any_cast<SP<CBaseAnimatedVariable>>(data);
if (!PAV)
return;
m_vActiveAnimatedVariables.emplace_back(PAV);
} catch (const std::bad_any_cast&) { return; }
}
void CAnimationManager::disconnectVarListener(std::any data) {
try {
const auto PAV = std::any_cast<void*>(data);
if (!PAV)
return;
std::erase_if(m_vActiveAnimatedVariables, [&](const auto& other) { return other.get() == PAV; });
} catch (const std::bad_any_cast&) { return; }
}
void CAnimationManager::removeAllBeziers() {