animation: forceDisconnect outside of tick() and remove the pointer to the animation manager

This commit is contained in:
Maximilian Seidler 2025-01-26 13:29:42 +01:00
parent 60dbdc46cc
commit 1e0392e711
5 changed files with 58 additions and 56 deletions

View file

@ -27,7 +27,7 @@ namespace Hyprutils {
; // m_bDummy = true;
};
void create(CAnimationManager*, int, Memory::CSharedPointer<CBaseAnimatedVariable>);
void create(int, Memory::CSharedPointer<CBaseAnimatedVariable>, Memory::CSharedPointer<SAnimVarEvents> events);
void connectToActive();
void disconnectFromActive();
@ -36,7 +36,7 @@ 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;
@ -58,8 +58,9 @@ namespace Hyprutils {
/* returns the spent (completion) % */
float getPercent() const;
/* returns the current curve value */
float getCurveValue() 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;
/* checks if an animation is in progress */
bool isBeingAnimated() const {
@ -100,6 +101,8 @@ namespace Hyprutils {
Memory::CWeakPointer<CBaseAnimatedVariable> m_pSelf;
Memory::CWeakPointer<SAnimVarEvents> m_events;
private:
Memory::CWeakPointer<SAnimationPropertyConfig> m_pConfig;
@ -107,18 +110,12 @@ namespace Hyprutils {
bool m_bDummy = 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;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
Memory::CWeakPointer<SAnimVarEvents> m_events;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
CallbackFun m_fEndCallback;
CallbackFun m_fBeginCallback;
CallbackFun m_fUpdateCallback;
CallbackFun m_fEndCallback;
CallbackFun m_fBeginCallback;
CallbackFun m_fUpdateCallback;
};
/* This concept represents the minimum requirement for a type to be used with CGenericAnimatedVariable */
@ -140,13 +137,13 @@ namespace Hyprutils {
public:
CGenericAnimatedVariable() = default;
void create(const int typeInfo, CAnimationManager* pAnimationManager, Memory::CSharedPointer<CGenericAnimatedVariable<VarType, AnimationContext>> pSelf,
void create(const int typeInfo, Memory::CSharedPointer<CGenericAnimatedVariable<VarType, AnimationContext>> pSelf, Memory::CSharedPointer<SAnimVarEvents> events,
const VarType& initialValue) {
m_Begun = initialValue;
m_Value = initialValue;
m_Goal = initialValue;
CBaseAnimatedVariable::create(pAnimationManager, typeInfo, pSelf);
CBaseAnimatedVariable::create(typeInfo, pSelf, events);
}
CGenericAnimatedVariable(const CGenericAnimatedVariable&) = delete;
@ -154,7 +151,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;
@ -166,6 +163,11 @@ namespace Hyprutils {
if (endCallback)
onAnimationEnd();
if (forceDisconnect) {
if (const auto PEVENTS = m_events.lock())
PEVENTS->forceDisconnect.emit(static_cast<void*>(this));
}
}
const VarType& value() const {

View file

@ -33,26 +33,24 @@ namespace Hyprutils {
const std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>>& getAllBeziers();
Memory::CSharedPointer<SAnimVarEvents> getEvents() const;
std::vector<Memory::CWeakPointer<CBaseAnimatedVariable>> m_vActiveAnimatedVariables;
Memory::CSharedPointer<SAnimVarEvents> m_events;
private:
std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>> m_mBezierCurves;
bool m_bTickScheduled = false;
uint32_t m_pendingDisconnects = 0;
bool m_bTickScheduled = false;
void connectListener(std::any data);
void lazyDisconnectListener(std::any data);
void forceDisconnectListener(std::any data);
struct {
Signal::CHyprSignalListener connect;
Signal::CHyprSignalListener forceDisconnect;
Signal::CHyprSignalListener lazyDisconnect;
} m_sListeners;
Memory::CSharedPointer<SAnimVarEvents> m_events;
friend class CBaseAnimatedVariable;
};
}

View file

@ -8,13 +8,11 @@ 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;
m_events = pAnimationManager->m_events;
void CBaseAnimatedVariable::create(int typeInfo, SP<CBaseAnimatedVariable> pSelf, SP<SAnimVarEvents> events) {
m_Type = typeInfo;
m_pSelf = pSelf;
m_events = events;
m_bDummy = false;
}
@ -77,16 +75,10 @@ float CBaseAnimatedVariable::getPercent() const {
return 1.f;
}
float CBaseAnimatedVariable::getCurveValue() const {
if (!m_bIsBeingAnimated || !m_pAnimationManager)
float CBaseAnimatedVariable::getCurveValue(CAnimationManager* pAnimationManager) const {
if (!m_bIsBeingAnimated || !pAnimationManager)
return 1.f;
// Guard against m_pAnimationManager being deleted
// TODO: Remove this and m_pAnimationManager
if (m_events.expired()) {
return 1.f;
}
std::string bezierName = "";
if (const auto PCONFIG = m_pConfig.lock()) {
const auto PVALUES = PCONFIG->pValues.lock();
@ -94,7 +86,7 @@ float CBaseAnimatedVariable::getCurveValue() const {
bezierName = PVALUES->internalBezier;
}
const auto BEZIER = m_pAnimationManager->getBezier(bezierName);
const auto BEZIER = pAnimationManager->getBezier(bezierName);
if (!BEZIER)
return 1.f;

View file

@ -18,7 +18,6 @@ CAnimationManager::CAnimationManager() {
m_sListeners.connect = m_events->connect.registerListener([this](std::any data) { connectListener(data); });
m_sListeners.forceDisconnect = m_events->forceDisconnect.registerListener([this](std::any data) { forceDisconnectListener(data); });
m_sListeners.lazyDisconnect = m_events->lazyDisconnect.registerListener([this](std::any data) { lazyDisconnectListener(data); });
}
void CAnimationManager::connectListener(std::any data) {
@ -32,12 +31,6 @@ void CAnimationManager::connectListener(std::any data) {
m_vActiveAnimatedVariables.emplace_back(PAV);
} catch (const std::bad_any_cast&) { return; }
// When the animation manager ticks, it will cleanup the active list.
// If for some reason we don't tick for a while, but vars get warped a lot, we could end up with a lot of pending disconnects.
// So we rorate here, since we don't want the vector to grow too big for no reason.
if (m_pendingDisconnects > 100)
rotateActive();
}
void CAnimationManager::forceDisconnectListener(std::any data) {
@ -50,10 +43,6 @@ void CAnimationManager::forceDisconnectListener(std::any data) {
} catch (const std::bad_any_cast&) { return; }
}
void CAnimationManager::lazyDisconnectListener(std::any data) {
m_pendingDisconnects++;
}
void CAnimationManager::removeAllBeziers() {
m_mBezierCurves.clear();
@ -95,7 +84,6 @@ void CAnimationManager::rotateActive() {
}
m_vActiveAnimatedVariables = std::move(active);
m_pendingDisconnects = 0;
}
bool CAnimationManager::bezierExists(const std::string& bezier) {

View file

@ -54,7 +54,7 @@ class CMyAnimationManager : public CAnimationManager {
const auto PBEZIER = getBezier(PAV->getBezierName());
if (SPENT >= 1.f || !PAV->enabled()) {
PAV->warp();
PAV->warp(true, false);
continue;
}
@ -93,7 +93,7 @@ class CMyAnimationManager : public CAnimationManager {
constexpr const eAVTypes EAVTYPE = std::is_same_v<VarType, int> ? eAVTypes::INT : eAVTypes::TEST;
const auto PAV = makeShared<CGenericAnimatedVariable<VarType, EmtpyContext>>();
PAV->create(EAVTYPE, static_cast<CAnimationManager*>(this), PAV, v);
PAV->create(EAVTYPE, PAV, m_events, v);
PAV->setConfig(animationTree.getConfig(animationConfigName));
av = std::move(PAV);
}
@ -326,6 +326,24 @@ int main(int argc, char** argv, char** envp) {
EXPECT(endCallbackRan, 4);
EXPECT(s.m_iA->value(), 10);
// test warp
*s.m_iA = 3;
s.m_iA->setCallbackOnEnd([&endCallbackRan](auto) { endCallbackRan++; }, false);
s.m_iA->warp(false);
EXPECT(endCallbackRan, 4);
*s.m_iA = 4;
s.m_iA->warp(true);
EXPECT(endCallbackRan, 5);
// test getCurveValue
*s.m_iA = 0;
EXPECT(s.m_iA->getCurveValue(pAnimationManager.get()), 0.f);
s.m_iA->warp();
EXPECT(s.m_iA->getCurveValue(pAnimationManager.get()), 1.f);
EXPECT(endCallbackRan, 6);
// Test duplicate active anim vars are not allowed
{
EXPECT(pAnimationManager->m_vActiveAnimatedVariables.size(), 0);
@ -337,7 +355,6 @@ int main(int argc, char** argv, char** envp) {
*a = 20;
EXPECT(pAnimationManager->m_vActiveAnimatedVariables.size(), 1);
a->warp();
pAnimationManager->tick(); // trigger cleanup
EXPECT(pAnimationManager->m_vActiveAnimatedVariables.size(), 0);
EXPECT(a->value(), 20);
}
@ -348,10 +365,15 @@ int main(int argc, char** argv, char** envp) {
pAnimationManager->createAnimation(1, a, "default");
*a = 10;
pAnimationManager.reset();
}
a->setValueAndWarp(11);
EXPECT(a->value(), 11);
*a = 12;
a->warp();
EXPECT(a->value(), 12);
*a = 13;
} // a gets destroyed
EXPECT(pAnimationManager.get(), nullptr);
*s.m_iA = 10;
return ret;
}