mirror of
https://github.com/hyprwm/hyprutils.git
synced 2025-01-29 05:49:49 +01:00
animation: add CAnimationConfigTree (#29)
Co-authored-by: Maximilian Seidler <paideia_dilemma@losfuzzys.net>
This commit is contained in:
parent
c42ce87eb3
commit
6a26d08bac
4 changed files with 205 additions and 32 deletions
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "AnimationConfig.hpp"
|
||||||
#include "../memory/WeakPtr.hpp"
|
#include "../memory/WeakPtr.hpp"
|
||||||
#include "hyprutils/memory/SharedPtr.hpp"
|
#include "hyprutils/memory/SharedPtr.hpp"
|
||||||
|
|
||||||
|
@ -10,22 +11,6 @@ namespace Hyprutils {
|
||||||
namespace Animation {
|
namespace Animation {
|
||||||
class CAnimationManager;
|
class CAnimationManager;
|
||||||
|
|
||||||
/*
|
|
||||||
Structure for animation properties.
|
|
||||||
Config properties need to have a static lifetime to allow for config reload.
|
|
||||||
*/
|
|
||||||
struct SAnimationPropertyConfig {
|
|
||||||
bool overridden = true;
|
|
||||||
|
|
||||||
std::string internalBezier = "";
|
|
||||||
std::string internalStyle = "";
|
|
||||||
float internalSpeed = 0.f;
|
|
||||||
int internalEnabled = -1;
|
|
||||||
|
|
||||||
Memory::CWeakPointer<SAnimationPropertyConfig> pValues;
|
|
||||||
Memory::CWeakPointer<SAnimationPropertyConfig> pParentAnimation;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* A base class for animated variables. */
|
/* A base class for animated variables. */
|
||||||
class CBaseAnimatedVariable {
|
class CBaseAnimatedVariable {
|
||||||
public:
|
public:
|
||||||
|
|
56
include/hyprutils/animation/AnimationConfig.hpp
Normal file
56
include/hyprutils/animation/AnimationConfig.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../memory/WeakPtr.hpp"
|
||||||
|
#include "hyprutils/memory/WeakPtr.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace Hyprutils {
|
||||||
|
namespace Animation {
|
||||||
|
/*
|
||||||
|
Structure for animation properties.
|
||||||
|
Config properties need to have a static lifetime to allow for config reload.
|
||||||
|
*/
|
||||||
|
struct SAnimationPropertyConfig {
|
||||||
|
bool overridden = false;
|
||||||
|
|
||||||
|
std::string internalBezier = "";
|
||||||
|
std::string internalStyle = "";
|
||||||
|
float internalSpeed = 0.f;
|
||||||
|
int internalEnabled = -1;
|
||||||
|
|
||||||
|
Memory::CWeakPointer<SAnimationPropertyConfig> pValues;
|
||||||
|
Memory::CWeakPointer<SAnimationPropertyConfig> pParentAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A class to manage SAnimationPropertyConfig objects in a tree structure */
|
||||||
|
class CAnimationConfigTree {
|
||||||
|
public:
|
||||||
|
CAnimationConfigTree() = default;
|
||||||
|
~CAnimationConfigTree() = default;
|
||||||
|
|
||||||
|
/* Add a new animation node inheriting from a parent.
|
||||||
|
If parent is empty, a root node will be created that references it's own values.
|
||||||
|
Make sure the parent node has already been created through this interface. */
|
||||||
|
void createNode(const std::string& nodeName, const std::string& parent = "");
|
||||||
|
|
||||||
|
/* check if a node name has been created using createNode */
|
||||||
|
bool nodeExists(const std::string& nodeName) const;
|
||||||
|
|
||||||
|
/* Override the values of a node. The root node can also be overriden. */
|
||||||
|
void setConfigForNode(const std::string& nodeName, int enabled, float speed, const std::string& bezier, const std::string& style = "");
|
||||||
|
|
||||||
|
Memory::CSharedPointer<SAnimationPropertyConfig> getConfig(const std::string& name) const;
|
||||||
|
const std::unordered_map<std::string, Memory::CSharedPointer<SAnimationPropertyConfig>>& getFullConfig() const;
|
||||||
|
|
||||||
|
CAnimationConfigTree(const CAnimationConfigTree&) = delete;
|
||||||
|
CAnimationConfigTree(CAnimationConfigTree&&) = delete;
|
||||||
|
CAnimationConfigTree& operator=(const CAnimationConfigTree&) = delete;
|
||||||
|
CAnimationConfigTree& operator=(CAnimationConfigTree&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setAnimForChildren(Memory::CSharedPointer<SAnimationPropertyConfig> PANIM);
|
||||||
|
std::unordered_map<std::string, Memory::CSharedPointer<SAnimationPropertyConfig>> m_mAnimationConfig;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
70
src/animation/AnimationConfig.cpp
Normal file
70
src/animation/AnimationConfig.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include <hyprutils/animation/AnimationConfig.hpp>
|
||||||
|
|
||||||
|
using namespace Hyprutils::Animation;
|
||||||
|
using namespace Hyprutils::Memory;
|
||||||
|
|
||||||
|
#define SP CSharedPointer
|
||||||
|
#define WP CWeakPointer
|
||||||
|
|
||||||
|
void CAnimationConfigTree::createNode(const std::string& nodeName, const std::string& parent) {
|
||||||
|
auto pConfig = m_mAnimationConfig[nodeName];
|
||||||
|
if (!pConfig)
|
||||||
|
pConfig = makeShared<SAnimationPropertyConfig>();
|
||||||
|
|
||||||
|
WP<SAnimationPropertyConfig> parentRef;
|
||||||
|
if (!parent.empty() && m_mAnimationConfig.find(parent) != m_mAnimationConfig.end())
|
||||||
|
parentRef = m_mAnimationConfig[parent];
|
||||||
|
|
||||||
|
*pConfig = {
|
||||||
|
.overridden = false,
|
||||||
|
.internalBezier = "",
|
||||||
|
.internalStyle = "",
|
||||||
|
.internalSpeed = 0.f,
|
||||||
|
.internalEnabled = -1,
|
||||||
|
.pValues = (parentRef) ? parentRef->pValues : pConfig,
|
||||||
|
.pParentAnimation = (parentRef) ? parentRef : pConfig,
|
||||||
|
};
|
||||||
|
|
||||||
|
m_mAnimationConfig[nodeName] = pConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAnimationConfigTree::nodeExists(const std::string& nodeName) const {
|
||||||
|
return m_mAnimationConfig.find(nodeName) != m_mAnimationConfig.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAnimationConfigTree::setConfigForNode(const std::string& nodeName, int enabled, float speed, const std::string& bezier, const std::string& style) {
|
||||||
|
auto pConfig = m_mAnimationConfig[nodeName];
|
||||||
|
if (!pConfig)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*pConfig = {
|
||||||
|
.overridden = true,
|
||||||
|
.internalBezier = bezier,
|
||||||
|
.internalStyle = style,
|
||||||
|
.internalSpeed = speed,
|
||||||
|
.internalEnabled = enabled,
|
||||||
|
.pValues = pConfig,
|
||||||
|
.pParentAnimation = pConfig->pParentAnimation, // keep the parent!
|
||||||
|
};
|
||||||
|
|
||||||
|
setAnimForChildren(pConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<SAnimationPropertyConfig> CAnimationConfigTree::getConfig(const std::string& name) const {
|
||||||
|
return m_mAnimationConfig.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, SP<SAnimationPropertyConfig>>& CAnimationConfigTree::getFullConfig() const {
|
||||||
|
return m_mAnimationConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAnimationConfigTree::setAnimForChildren(SP<SAnimationPropertyConfig> PANIM) {
|
||||||
|
for (auto& [name, anim] : m_mAnimationConfig) {
|
||||||
|
if (anim->pParentAnimation == PANIM && !anim->overridden) {
|
||||||
|
// if a child isnt overridden, set the values of the parent
|
||||||
|
anim->pValues = PANIM->pValues;
|
||||||
|
|
||||||
|
setAnimForChildren(anim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <hyprutils/animation/AnimationConfig.hpp>
|
||||||
#include <hyprutils/animation/AnimationManager.hpp>
|
#include <hyprutils/animation/AnimationManager.hpp>
|
||||||
#include <hyprutils/animation/AnimatedVariable.hpp>
|
#include <hyprutils/animation/AnimatedVariable.hpp>
|
||||||
#include <hyprutils/memory/WeakPtr.hpp>
|
#include <hyprutils/memory/WeakPtr.hpp>
|
||||||
|
@ -37,7 +38,7 @@ struct SomeTestType {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<std::string, SP<SAnimationPropertyConfig>> animationConfig;
|
CAnimationConfigTree animationTree;
|
||||||
|
|
||||||
class CMyAnimationManager : public CAnimationManager {
|
class CMyAnimationManager : public CAnimationManager {
|
||||||
public:
|
public:
|
||||||
|
@ -90,7 +91,7 @@ class CMyAnimationManager : public CAnimationManager {
|
||||||
const auto PAV = makeShared<CGenericAnimatedVariable<VarType, EmtpyContext>>();
|
const auto PAV = makeShared<CGenericAnimatedVariable<VarType, EmtpyContext>>();
|
||||||
|
|
||||||
PAV->create(EAVTYPE, static_cast<CAnimationManager*>(this), PAV, v);
|
PAV->create(EAVTYPE, static_cast<CAnimationManager*>(this), PAV, v);
|
||||||
PAV->setConfig(animationConfig[animationConfigName]);
|
PAV->setConfig(animationTree.getConfig(animationConfigName));
|
||||||
av = std::move(PAV);
|
av = std::move(PAV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ class Subject {
|
||||||
public:
|
public:
|
||||||
Subject(const int& a, const int& b) {
|
Subject(const int& a, const int& b) {
|
||||||
gAnimationManager.createAnimation(a, m_iA, "default");
|
gAnimationManager.createAnimation(a, m_iA, "default");
|
||||||
gAnimationManager.createAnimation(b, m_iB, "default");
|
gAnimationManager.createAnimation(b, m_iB, "internal");
|
||||||
gAnimationManager.createAnimation({}, m_iC, "default");
|
gAnimationManager.createAnimation({}, m_iC, "default");
|
||||||
}
|
}
|
||||||
PANIMVAR<int> m_iA;
|
PANIMVAR<int> m_iA;
|
||||||
|
@ -117,15 +118,78 @@ class Subject {
|
||||||
PANIMVAR<SomeTestType> m_iC;
|
PANIMVAR<SomeTestType> m_iC;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv, char** envp) {
|
int config() {
|
||||||
animationConfig["default"] = makeShared<SAnimationPropertyConfig>();
|
int ret = 0;
|
||||||
animationConfig["default"]->internalBezier = "default";
|
|
||||||
animationConfig["default"]->internalSpeed = 1.0;
|
animationTree.createNode("global");
|
||||||
animationConfig["default"]->internalStyle = "asdf";
|
animationTree.createNode("internal");
|
||||||
animationConfig["default"]->internalEnabled = 1;
|
|
||||||
animationConfig["default"]->pValues = animationConfig["default"];
|
animationTree.createNode("foo", "internal");
|
||||||
|
animationTree.createNode("default", "global");
|
||||||
|
animationTree.createNode("bar", "default");
|
||||||
|
|
||||||
|
/*
|
||||||
|
internal
|
||||||
|
↳ foo
|
||||||
|
global
|
||||||
|
↳ default
|
||||||
|
↳ bar
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto barCfg = animationTree.getConfig("bar");
|
||||||
|
auto internalCfg = animationTree.getConfig("internal");
|
||||||
|
|
||||||
|
// internal is a root node and should point to itself
|
||||||
|
EXPECT(internalCfg->pParentAnimation.get(), internalCfg.get());
|
||||||
|
EXPECT(internalCfg->pValues.get(), internalCfg.get());
|
||||||
|
|
||||||
|
animationTree.setConfigForNode("global", 1, 4.0, "default", "asdf");
|
||||||
|
|
||||||
|
EXPECT(barCfg->internalEnabled, -1);
|
||||||
|
{
|
||||||
|
const auto PVALUES = barCfg->pValues.lock();
|
||||||
|
EXPECT(PVALUES->internalEnabled, 1);
|
||||||
|
EXPECT(PVALUES->internalBezier, "default");
|
||||||
|
EXPECT(PVALUES->internalStyle, "asdf");
|
||||||
|
EXPECT(PVALUES->internalSpeed, 4.0);
|
||||||
|
}
|
||||||
|
EXPECT(barCfg->pParentAnimation.get(), animationTree.getConfig("default").get());
|
||||||
|
|
||||||
|
// Overwrite our own values
|
||||||
|
animationTree.setConfigForNode("bar", 1, 4.2, "test", "qwer");
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto PVALUES = barCfg->pValues.lock();
|
||||||
|
EXPECT(PVALUES->internalEnabled, 1);
|
||||||
|
EXPECT(PVALUES->internalBezier, "test");
|
||||||
|
EXPECT(PVALUES->internalStyle, "qwer");
|
||||||
|
EXPECT(PVALUES->internalSpeed, 4.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now overwrite the parent
|
||||||
|
animationTree.setConfigForNode("default", 0, 0.0, "zxcv", "foo");
|
||||||
|
|
||||||
|
{
|
||||||
|
// Expecting no change
|
||||||
|
const auto PVALUES = barCfg->pValues.lock();
|
||||||
|
EXPECT(PVALUES->internalEnabled, 1);
|
||||||
|
EXPECT(PVALUES->internalBezier, "test");
|
||||||
|
EXPECT(PVALUES->internalStyle, "qwer");
|
||||||
|
EXPECT(PVALUES->internalSpeed, 4.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv, char** envp) {
|
||||||
|
int ret = config();
|
||||||
|
|
||||||
|
animationTree.createNode("global");
|
||||||
|
animationTree.createNode("internal");
|
||||||
|
|
||||||
|
animationTree.createNode("default", "global");
|
||||||
|
animationTree.setConfigForNode("global", 1, 4.0, "default", "asdf");
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
Subject s(0, 0);
|
Subject s(0, 0);
|
||||||
|
|
||||||
EXPECT(s.m_iA->value(), 0);
|
EXPECT(s.m_iA->value(), 0);
|
||||||
|
@ -172,7 +236,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
EXPECT(s.m_iA->getStyle(), "asdf");
|
EXPECT(s.m_iA->getStyle(), "asdf");
|
||||||
EXPECT(s.m_iA->enabled(), true);
|
EXPECT(s.m_iA->enabled(), true);
|
||||||
|
|
||||||
animationConfig["default"]->internalEnabled = 0;
|
animationTree.getConfig("global")->internalEnabled = 0;
|
||||||
|
|
||||||
EXPECT(s.m_iA->enabled(), false);
|
EXPECT(s.m_iA->enabled(), false);
|
||||||
|
|
||||||
|
@ -181,16 +245,14 @@ int main(int argc, char** argv, char** envp) {
|
||||||
EXPECT(s.m_iA->value(), 50);
|
EXPECT(s.m_iA->value(), 50);
|
||||||
|
|
||||||
// Test missing pValues
|
// Test missing pValues
|
||||||
animationConfig["default"]->internalEnabled = 1;
|
animationTree.getConfig("global")->internalEnabled = 0;
|
||||||
animationConfig["default"]->pValues.reset();
|
animationTree.getConfig("default")->pValues.reset();
|
||||||
|
|
||||||
EXPECT(s.m_iA->enabled(), false);
|
EXPECT(s.m_iA->enabled(), false);
|
||||||
EXPECT(s.m_iA->getBezierName(), "default");
|
EXPECT(s.m_iA->getBezierName(), "default");
|
||||||
EXPECT(s.m_iA->getStyle(), "");
|
EXPECT(s.m_iA->getStyle(), "");
|
||||||
EXPECT(s.m_iA->getPercent(), 1.f);
|
EXPECT(s.m_iA->getPercent(), 1.f);
|
||||||
|
|
||||||
animationConfig["default"]->pValues = animationConfig["default"];
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Test callbacks
|
// Test callbacks
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue