Skip to content

Commit

Permalink
animation: fix crashes and cleanup of active vars (#42)
Browse files Browse the repository at this point in the history
Minor stuff

---------

Co-authored-by: Vaxry <[email protected]>
  • Loading branch information
PaideiaDilemma and vaxerski authored Jan 27, 2025
1 parent fb0c2d1 commit de58286
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 43 deletions.
31 changes: 21 additions & 10 deletions include/hyprutils/animation/AnimatedVariable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

#include "AnimationConfig.hpp"
#include "../memory/WeakPtr.hpp"
#include "hyprutils/memory/SharedPtr.hpp"
#include "../memory/SharedPtr.hpp"
#include "../signal/Signal.hpp"
#include "AnimationManager.hpp"

#include <functional>
#include <chrono>

namespace Hyprutils {
namespace Animation {
class CAnimationManager;

/* A base class for animated variables. */
class CBaseAnimatedVariable {
Expand All @@ -29,14 +30,15 @@ namespace Hyprutils {
disconnectFromActive();
};

virtual void warp(bool endCallback = true) = 0;
virtual void warp(bool endCallback = true, bool forceDisconnect = true) = 0;

CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete;

void setConfig(Memory::CSharedPointer<SAnimationPropertyConfig> pConfig) {
//
void setConfig(Memory::CSharedPointer<SAnimationPropertyConfig> pConfig) {
m_pConfig = pConfig;
}

Expand All @@ -51,7 +53,7 @@ namespace Hyprutils {
/* returns the spent (completion) % */
float getPercent() const;

/* returns the current curve value */
/* returns the current curve value. */
float getCurveValue() const;

/* checks if an animation is in progress */
Expand Down Expand Up @@ -83,15 +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<CBaseAnimatedVariable> m_pSelf;
Memory::CWeakPointer<CBaseAnimatedVariable> m_pSelf;

Memory::CWeakPointer<CAnimationManager::SAnimationManagerSignals> m_pSignals;

private:
Memory::CWeakPointer<SAnimationPropertyConfig> m_pConfig;
Expand All @@ -100,7 +109,6 @@ namespace Hyprutils {

bool m_bDummy = true;

CAnimationManager* m_pAnimationManager = nullptr;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;

Expand Down Expand Up @@ -142,7 +150,7 @@ namespace Hyprutils {
CGenericAnimatedVariable& operator=(const CGenericAnimatedVariable&) = delete;
CGenericAnimatedVariable& operator=(CGenericAnimatedVariable&&) = delete;

virtual void warp(bool endCallback = true) {
virtual void warp(bool endCallback = true, bool forceDisconnect = true) {
if (!m_bIsBeingAnimated)
return;

Expand All @@ -154,6 +162,9 @@ namespace Hyprutils {

if (endCallback)
onAnimationEnd();

if (forceDisconnect)
disconnectFromActive();
}

const VarType& value() const {
Expand Down
26 changes: 24 additions & 2 deletions include/hyprutils/animation/AnimationManager.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
#pragma once

#include "./BezierCurve.hpp"
#include "./AnimatedVariable.hpp"
#include "../math/Vector2D.hpp"
#include "../memory/WeakPtr.hpp"
#include "../signal/Signal.hpp"

#include <cstdint>
#include <unordered_map>
#include <vector>

namespace Hyprutils {
namespace Animation {
class CBaseAnimatedVariable;

/* A class for managing bezier curves and variables that are being animated. */
class CAnimationManager {
public:
CAnimationManager();
virtual ~CAnimationManager() = default;

void tickDone();
void rotateActive();
bool shouldTickForNext();

virtual void scheduleTick() = 0;
Expand All @@ -30,12 +34,30 @@ namespace Hyprutils {

const std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>>& getAllBeziers();

std::vector<Memory::CWeakPointer<CBaseAnimatedVariable>> m_vActiveAnimatedVariables;
struct SAnimationManagerSignals {
Signal::CSignal connect; // WP<CBaseAnimatedVariable>
Signal::CSignal disconnect; // WP<CBaseAnimatedVariable>
};

Memory::CWeakPointer<SAnimationManagerSignals> getSignals() const;

std::vector<Memory::CWeakPointer<CBaseAnimatedVariable>> m_vActiveAnimatedVariables;

private:
std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>> m_mBezierCurves;

bool m_bTickScheduled = false;

void onConnect(std::any data);
void onDisconnect(std::any data);

struct SAnimVarListeners {
Signal::CHyprSignalListener connect;
Signal::CHyprSignalListener disconnect;
};

Memory::CUniquePointer<SAnimVarListeners> m_listeners;
Memory::CUniquePointer<SAnimationManagerSignals> m_events;
};
}
}
29 changes: 16 additions & 13 deletions src/animation/AnimatedVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,28 @@ using namespace Hyprutils::Memory;
#define SP CSharedPointer
#define WP CWeakPointer

void CBaseAnimatedVariable::create(Hyprutils::Animation::CAnimationManager* pAnimationManager, int typeInfo, SP<CBaseAnimatedVariable> pSelf) {
m_pAnimationManager = pAnimationManager;
m_Type = typeInfo;
m_pSelf = pSelf;
void CBaseAnimatedVariable::create(CAnimationManager* pManager, int typeInfo, SP<CBaseAnimatedVariable> pSelf) {
m_Type = typeInfo;
m_pSelf = pSelf;

m_bDummy = false;
m_pAnimationManager = pManager;
m_pSignals = pManager->getSignals();
m_bDummy = false;
}

void CBaseAnimatedVariable::connectToActive() {
if (!m_pAnimationManager || m_bDummy)
if (m_bDummy || m_bIsConnectedToActive || isAnimationManagerDead())
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_pSignals->connect.emit(m_pSelf);
m_bIsConnectedToActive = true;
}

void CBaseAnimatedVariable::disconnectFromActive() {
if (!m_pAnimationManager)
if (isAnimationManagerDead())
return;

std::erase_if(m_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == m_pSelf; });
m_pSignals->disconnect.emit(m_pSelf);
m_bIsConnectedToActive = false;
}

Expand Down Expand Up @@ -77,7 +76,7 @@ float CBaseAnimatedVariable::getPercent() const {
}

float CBaseAnimatedVariable::getCurveValue() const {
if (!m_bIsBeingAnimated || !m_pAnimationManager)
if (!m_bIsBeingAnimated || isAnimationManagerDead())
return 1.f;

std::string bezierName = "";
Expand All @@ -99,7 +98,7 @@ float CBaseAnimatedVariable::getCurveValue() const {
}

bool CBaseAnimatedVariable::ok() const {
return m_pConfig && m_pAnimationManager;
return m_pConfig && !m_bDummy && !isAnimationManagerDead();
}

void CBaseAnimatedVariable::onUpdate() {
Expand Down Expand Up @@ -156,3 +155,7 @@ void CBaseAnimatedVariable::onAnimationBegin() {
m_fBeginCallback = nullptr; // reset
}
}

bool CBaseAnimatedVariable::isAnimationManagerDead() const {
return m_pSignals.expired();
}
40 changes: 40 additions & 0 deletions src/animation/AnimationManager.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
#include <hyprutils/animation/AnimationManager.hpp>
#include <hyprutils/animation/AnimatedVariable.hpp>

using namespace Hyprutils::Animation;
using namespace Hyprutils::Math;
using namespace Hyprutils::Memory;
using namespace Hyprutils::Signal;

#define SP CSharedPointer
#define WP CWeakPointer

const std::array<Vector2D, 2> DEFAULTBEZIERPOINTS = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)};

CAnimationManager::CAnimationManager() {
const auto BEZIER = makeShared<CBezierCurve>();
BEZIER->setup(DEFAULTBEZIERPOINTS);
m_mBezierCurves["default"] = BEZIER;

m_events = makeUnique<SAnimationManagerSignals>();
m_listeners = makeUnique<SAnimVarListeners>();

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::onConnect(std::any data) {
if (!m_bTickScheduled)
scheduleTick();

try {
const auto PAV = std::any_cast<WP<CBaseAnimatedVariable>>(data);
if (!PAV)
return;

m_vActiveAnimatedVariables.emplace_back(PAV);
} catch (const std::bad_any_cast&) { return; }
}

void CAnimationManager::onDisconnect(std::any data) {
try {
const auto PAV = std::any_cast<WP<CBaseAnimatedVariable>>(data);
if (!PAV)
return;

std::erase_if(m_vActiveAnimatedVariables, [&](const auto& other) { return !other || other == PAV; });
} catch (const std::bad_any_cast&) { return; }
}

void CAnimationManager::removeAllBeziers() {
Expand All @@ -37,6 +69,10 @@ bool CAnimationManager::shouldTickForNext() {
}

void CAnimationManager::tickDone() {
rotateActive();
}

void CAnimationManager::rotateActive() {
std::vector<CWeakPointer<CBaseAnimatedVariable>> active;
active.reserve(m_vActiveAnimatedVariables.size()); // avoid reallocations
for (auto const& av : m_vActiveAnimatedVariables) {
Expand Down Expand Up @@ -71,3 +107,7 @@ SP<CBezierCurve> CAnimationManager::getBezier(const std::string& name) {
const std::unordered_map<std::string, SP<CBezierCurve>>& CAnimationManager::getAllBeziers() {
return m_mBezierCurves;
}

CWeakPointer<CAnimationManager::SAnimationManagerSignals> CAnimationManager::getSignals() const {
return m_events;
}
Loading

0 comments on commit de58286

Please sign in to comment.