mirror of
https://github.com/hyprwm/hyprutils.git
synced 2025-05-12 21:30:36 +01:00
animation: let callbacks have SP's to the self variable and dispatch them internally
To be absolutely sure that adding/removing callbacks can't cause problems, dispatch them in tickDone outside of the loop. I think looping over all the vars twice is still better than having disconnectFromActive handle the removal, because that needs to search for each variable in the active vector.
This commit is contained in:
parent
72dfbf5296
commit
71844cbde1
5 changed files with 49 additions and 20 deletions
|
@ -14,7 +14,7 @@ namespace Hyprutils {
|
|||
/* A base class for animated variables. */
|
||||
class CBaseAnimatedVariable {
|
||||
public:
|
||||
using CallbackFun = std::function<void(Memory::CWeakPointer<CBaseAnimatedVariable> thisptr)>;
|
||||
using CallbackFun = std::function<void(Memory::CSharedPointer<CBaseAnimatedVariable> thisptr)>;
|
||||
|
||||
CBaseAnimatedVariable() {
|
||||
; // m_bDummy = true;
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Hyprutils {
|
|||
class CAnimationManager {
|
||||
public:
|
||||
CAnimationManager();
|
||||
virtual ~CAnimationManager() = default;
|
||||
|
||||
void tickDone();
|
||||
bool shouldTickForNext();
|
||||
|
|
|
@ -103,8 +103,11 @@ bool CBaseAnimatedVariable::ok() const {
|
|||
}
|
||||
|
||||
void CBaseAnimatedVariable::onUpdate() {
|
||||
if (m_bIsBeingAnimated && m_fUpdateCallback)
|
||||
m_fUpdateCallback(m_pSelf);
|
||||
if (!m_bIsBeingAnimated || !m_fUpdateCallback)
|
||||
return;
|
||||
|
||||
if (const auto SELF = m_pSelf.lock(); SELF)
|
||||
m_fUpdateCallback(SELF);
|
||||
}
|
||||
|
||||
void CBaseAnimatedVariable::setCallbackOnEnd(CallbackFun func, bool remove) {
|
||||
|
@ -133,14 +136,15 @@ void CBaseAnimatedVariable::resetAllCallbacks() {
|
|||
}
|
||||
|
||||
void CBaseAnimatedVariable::onAnimationEnd() {
|
||||
m_bIsBeingAnimated = false;
|
||||
/* We do not call disconnectFromActive here. The animation manager will remove it on a call to tickDone. */
|
||||
m_bIsBeingAnimated = false;
|
||||
|
||||
if (m_fEndCallback) {
|
||||
/* loading m_bRemoveEndAfterRan before calling the callback allows the callback to delete this animation safely if it is false. */
|
||||
auto removeEndCallback = m_bRemoveEndAfterRan;
|
||||
m_fEndCallback(m_pSelf);
|
||||
if (removeEndCallback)
|
||||
if (m_bIsConnectedToActive) // callback will we handled by tickDone
|
||||
return;
|
||||
|
||||
if (const auto SELF = m_pSelf.lock(); SELF && m_fEndCallback) {
|
||||
m_fEndCallback(SELF);
|
||||
if (m_bRemoveEndAfterRan)
|
||||
m_fEndCallback = nullptr; // reset
|
||||
}
|
||||
}
|
||||
|
@ -150,8 +154,8 @@ void CBaseAnimatedVariable::onAnimationBegin() {
|
|||
animationBegin = std::chrono::steady_clock::now();
|
||||
connectToActive();
|
||||
|
||||
if (m_fBeginCallback) {
|
||||
m_fBeginCallback(m_pSelf);
|
||||
if (const auto SELF = m_pSelf.lock(); SELF && m_fBeginCallback) {
|
||||
m_fBeginCallback(SELF);
|
||||
if (m_bRemoveBeginAfterRan)
|
||||
m_fBeginCallback = nullptr; // reset
|
||||
}
|
||||
|
|
|
@ -37,6 +37,27 @@ bool CAnimationManager::shouldTickForNext() {
|
|||
}
|
||||
|
||||
void CAnimationManager::tickDone() {
|
||||
std::vector<std::function<void(void)>> callbacks;
|
||||
callbacks.reserve(m_vActiveAnimatedVariables.size());
|
||||
for (auto const& av : m_vActiveAnimatedVariables) {
|
||||
const auto PAV = av.lock();
|
||||
if (!PAV)
|
||||
continue;
|
||||
|
||||
if (PAV->ok() && PAV->isBeingAnimated()) {
|
||||
if (PAV->m_fUpdateCallback)
|
||||
callbacks.emplace_back(std::bind(PAV->m_fUpdateCallback, PAV));
|
||||
} else {
|
||||
if (PAV->m_fEndCallback)
|
||||
callbacks.emplace_back(std::bind(PAV->m_fEndCallback, PAV));
|
||||
if (PAV->m_bRemoveEndAfterRan)
|
||||
PAV->m_fEndCallback = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& cb : callbacks)
|
||||
cb();
|
||||
|
||||
std::vector<CWeakPointer<CBaseAnimatedVariable>> active;
|
||||
active.reserve(m_vActiveAnimatedVariables.size()); // avoid reallocations
|
||||
for (auto const& av : m_vActiveAnimatedVariables) {
|
||||
|
|
|
@ -43,8 +43,8 @@ CAnimationConfigTree animationTree;
|
|||
class CMyAnimationManager : public CAnimationManager {
|
||||
public:
|
||||
void tick() {
|
||||
for (size_t i = 0; i < m_vActiveAnimatedVariables.size(); i++) {
|
||||
const auto PAV = m_vActiveAnimatedVariables[i].lock();
|
||||
for (const auto& av : m_vActiveAnimatedVariables) {
|
||||
const auto PAV = av.lock();
|
||||
if (!PAV || !PAV->ok())
|
||||
continue;
|
||||
|
||||
|
@ -79,8 +79,6 @@ class CMyAnimationManager : public CAnimationManager {
|
|||
std::cout << Colors::RED << "What are we even doing?" << Colors::RESET;
|
||||
} break;
|
||||
}
|
||||
|
||||
PAV->onUpdate();
|
||||
}
|
||||
|
||||
tickDone();
|
||||
|
@ -263,12 +261,16 @@ int main(int argc, char** argv, char** envp) {
|
|||
int beginCallbackRan = 0;
|
||||
int updateCallbackRan = 0;
|
||||
int endCallbackRan = 0;
|
||||
s.m_iA->setCallbackOnBegin([&beginCallbackRan](WP<CBaseAnimatedVariable> pav) { beginCallbackRan++; });
|
||||
s.m_iA->setUpdateCallback([&updateCallbackRan](WP<CBaseAnimatedVariable> pav) { updateCallbackRan++; });
|
||||
s.m_iA->setCallbackOnEnd([&endCallbackRan](WP<CBaseAnimatedVariable> pav) { endCallbackRan++; }, false);
|
||||
s.m_iA->setCallbackOnBegin([&beginCallbackRan](SP<CBaseAnimatedVariable> pav) { beginCallbackRan++; }, false);
|
||||
s.m_iA->setUpdateCallback([&updateCallbackRan](SP<CBaseAnimatedVariable> pav) { updateCallbackRan++; });
|
||||
s.m_iA->setCallbackOnEnd([&endCallbackRan](SP<CBaseAnimatedVariable> pav) { endCallbackRan++; }, false);
|
||||
|
||||
EXPECT(gAnimationManager.shouldTickForNext(), false);
|
||||
|
||||
s.m_iA->setValueAndWarp(42);
|
||||
|
||||
EXPECT(gAnimationManager.shouldTickForNext(), false);
|
||||
|
||||
EXPECT(beginCallbackRan, 0);
|
||||
EXPECT(updateCallbackRan, 1);
|
||||
EXPECT(endCallbackRan, 2); // first called when setting the callback, then when warping.
|
||||
|
@ -291,8 +293,8 @@ int main(int argc, char** argv, char** envp) {
|
|||
|
||||
// test adding / removing vars during a tick
|
||||
s.m_iA->resetAllCallbacks();
|
||||
s.m_iA->setUpdateCallback([&vars](WP<CBaseAnimatedVariable> v) {
|
||||
if (v.lock() != vars.back())
|
||||
s.m_iA->setUpdateCallback([&vars](SP<CBaseAnimatedVariable> v) {
|
||||
if (v != vars.back())
|
||||
vars.back()->warp();
|
||||
});
|
||||
s.m_iA->setCallbackOnEnd([&s, &vars](auto) {
|
||||
|
@ -310,6 +312,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
EXPECT(s.m_iA->value(), 1000000);
|
||||
// all vars should be set to 1337
|
||||
EXPECT(std::find_if(vars.begin(), vars.end(), [](const auto& v) { return v->value() != 1337; }) == vars.end(), true);
|
||||
EXPECT(endCallbackRan, 3);
|
||||
|
||||
// test one-time callbacks
|
||||
s.m_iA->resetAllCallbacks();
|
||||
|
|
Loading…
Reference in a new issue