mirror of
https://github.com/hyprwm/hyprutils.git
synced 2025-01-27 17:39: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
|
||||
|
||||
#include "AnimationConfig.hpp"
|
||||
#include "../memory/WeakPtr.hpp"
|
||||
#include "hyprutils/memory/SharedPtr.hpp"
|
||||
|
||||
|
@ -10,22 +11,6 @@ namespace Hyprutils {
|
|||
namespace Animation {
|
||||
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. */
|
||||
class CBaseAnimatedVariable {
|
||||
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/AnimatedVariable.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 {
|
||||
public:
|
||||
|
@ -90,7 +91,7 @@ class CMyAnimationManager : public CAnimationManager {
|
|||
const auto PAV = makeShared<CGenericAnimatedVariable<VarType, EmtpyContext>>();
|
||||
|
||||
PAV->create(EAVTYPE, static_cast<CAnimationManager*>(this), PAV, v);
|
||||
PAV->setConfig(animationConfig[animationConfigName]);
|
||||
PAV->setConfig(animationTree.getConfig(animationConfigName));
|
||||
av = std::move(PAV);
|
||||
}
|
||||
|
||||
|
@ -109,7 +110,7 @@ class Subject {
|
|||
public:
|
||||
Subject(const int& a, const int& b) {
|
||||
gAnimationManager.createAnimation(a, m_iA, "default");
|
||||
gAnimationManager.createAnimation(b, m_iB, "default");
|
||||
gAnimationManager.createAnimation(b, m_iB, "internal");
|
||||
gAnimationManager.createAnimation({}, m_iC, "default");
|
||||
}
|
||||
PANIMVAR<int> m_iA;
|
||||
|
@ -117,15 +118,78 @@ class Subject {
|
|||
PANIMVAR<SomeTestType> m_iC;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv, char** envp) {
|
||||
animationConfig["default"] = makeShared<SAnimationPropertyConfig>();
|
||||
animationConfig["default"]->internalBezier = "default";
|
||||
animationConfig["default"]->internalSpeed = 1.0;
|
||||
animationConfig["default"]->internalStyle = "asdf";
|
||||
animationConfig["default"]->internalEnabled = 1;
|
||||
animationConfig["default"]->pValues = animationConfig["default"];
|
||||
int config() {
|
||||
int ret = 0;
|
||||
|
||||
animationTree.createNode("global");
|
||||
animationTree.createNode("internal");
|
||||
|
||||
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);
|
||||
|
||||
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->enabled(), true);
|
||||
|
||||
animationConfig["default"]->internalEnabled = 0;
|
||||
animationTree.getConfig("global")->internalEnabled = 0;
|
||||
|
||||
EXPECT(s.m_iA->enabled(), false);
|
||||
|
||||
|
@ -181,16 +245,14 @@ int main(int argc, char** argv, char** envp) {
|
|||
EXPECT(s.m_iA->value(), 50);
|
||||
|
||||
// Test missing pValues
|
||||
animationConfig["default"]->internalEnabled = 1;
|
||||
animationConfig["default"]->pValues.reset();
|
||||
animationTree.getConfig("global")->internalEnabled = 0;
|
||||
animationTree.getConfig("default")->pValues.reset();
|
||||
|
||||
EXPECT(s.m_iA->enabled(), false);
|
||||
EXPECT(s.m_iA->getBezierName(), "default");
|
||||
EXPECT(s.m_iA->getStyle(), "");
|
||||
EXPECT(s.m_iA->getPercent(), 1.f);
|
||||
|
||||
animationConfig["default"]->pValues = animationConfig["default"];
|
||||
|
||||
//
|
||||
// Test callbacks
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue