Added bezier curves

This commit is contained in:
vaxerski 2022-04-23 21:47:16 +02:00
parent 306d163613
commit 3ebe7d7972
14 changed files with 255 additions and 67 deletions

View file

@ -50,7 +50,8 @@ Try it out and report bugs / suggestions!
- Easily expandable and readable codebase - Easily expandable and readable codebase
- Config reloaded instantly upon saving - Config reloaded instantly upon saving
- Parabolic window animations - Bezier-curve window animations
- Custom bezier curves
- Workspaces protocol support - Workspaces protocol support
- Tiling/floating/fullscreen windows - Tiling/floating/fullscreen windows
- Window/monitor rules - Window/monitor rules

View file

@ -41,7 +41,9 @@ decoration {
animations { animations {
enabled=1 enabled=1
speed=7 speed=7 # speed is measured in 100s of ms, 7 = 700ms
curve=default # you can customize your own bezier curves, see the wiki
windows_curve=default # specific curve for all window animations
windows_speed=6 # specific speeds for components can be made with name_speed=float. 0 means use global (speed=float). If not set, will use the global value. windows_speed=6 # specific speeds for components can be made with name_speed=float. 0 means use global (speed=float). If not set, will use the global value.
windows=1 windows=1
borders=1 borders=1

View file

@ -158,6 +158,9 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "Creating the KeybindManager!"); Debug::log(LOG, "Creating the KeybindManager!");
g_pKeybindManager = std::make_unique<CKeybindManager>(); g_pKeybindManager = std::make_unique<CKeybindManager>();
Debug::log(LOG, "Creating the AnimationManager!");
g_pAnimationManager = std::make_unique<CAnimationManager>();
Debug::log(LOG, "Creating the ConfigManager!"); Debug::log(LOG, "Creating the ConfigManager!");
g_pConfigManager = std::make_unique<CConfigManager>(); g_pConfigManager = std::make_unique<CConfigManager>();
@ -178,9 +181,6 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "Creating the LayoutManager!"); Debug::log(LOG, "Creating the LayoutManager!");
g_pLayoutManager = std::make_unique<CLayoutManager>(); g_pLayoutManager = std::make_unique<CLayoutManager>();
Debug::log(LOG, "Creating the AnimationManager!");
g_pAnimationManager = std::make_unique<CAnimationManager>();
// //
// //

View file

@ -2,10 +2,10 @@
#include "Compositor.hpp" #include "Compositor.hpp"
CWindow::CWindow() { CWindow::CWindow() {
m_vRealPosition.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, (void*)this); m_vRealPosition.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*) this);
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, (void*)this); m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this);
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, (void*)this); m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this);
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, (void*)this); m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this);
} }
CWindow::~CWindow() { CWindow::~CWindow() {

View file

@ -43,10 +43,14 @@ void CConfigManager::setDefaultVars() {
configValues["animations:enabled"].intValue = 1; configValues["animations:enabled"].intValue = 1;
configValues["animations:speed"].floatValue = 7.f; configValues["animations:speed"].floatValue = 7.f;
configValues["animations:curve"].strValue = "default";
configValues["animations:windows_curve"].strValue = "[[f]]";
configValues["animations:windows_speed"].floatValue = 0.f; configValues["animations:windows_speed"].floatValue = 0.f;
configValues["animations:windows"].intValue = 1; configValues["animations:windows"].intValue = 1;
configValues["animations:borders_curve"].strValue = "[[f]]";
configValues["animations:borders_speed"].floatValue = 0.f; configValues["animations:borders_speed"].floatValue = 0.f;
configValues["animations:borders"].intValue = 1; configValues["animations:borders"].intValue = 1;
configValues["animations:fadein_curve"].strValue = "[[f]]";
configValues["animations:fadein_speed"].floatValue = 0.f; configValues["animations:fadein_speed"].floatValue = 0.f;
configValues["animations:fadein"].intValue = 1; configValues["animations:fadein"].intValue = 1;
@ -207,6 +211,39 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
m_dMonitorRules.push_back(newrule); m_dMonitorRules.push_back(newrule);
} }
void CConfigManager::handleBezier(const std::string& command, const std::string& args) {
std::string curitem = "";
std::string argZ = args;
auto nextItem = [&]() {
auto idx = argZ.find_first_of(',');
if (idx != std::string::npos) {
curitem = argZ.substr(0, idx);
argZ = argZ.substr(idx + 1);
} else {
curitem = argZ;
argZ = "";
}
};
nextItem();
std::string bezierName = curitem;
nextItem();
float p1x = std::stof(curitem);
nextItem();
float p1y = std::stof(curitem);
nextItem();
float p2x = std::stof(curitem);
nextItem();
float p2y = std::stof(curitem);
g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));
}
void CConfigManager::handleBind(const std::string& command, const std::string& value) { void CConfigManager::handleBind(const std::string& command, const std::string& value) {
// example: // example:
// bind=SUPER,G,exec,dmenu_run <args> // bind=SUPER,G,exec,dmenu_run <args>
@ -311,6 +348,8 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
handleDefaultWorkspace(COMMAND, VALUE); handleDefaultWorkspace(COMMAND, VALUE);
} else if (COMMAND == "windowrule") { } else if (COMMAND == "windowrule") {
handleWindowRule(COMMAND, VALUE); handleWindowRule(COMMAND, VALUE);
} else if (COMMAND == "bezier") {
handleBezier(COMMAND, VALUE);
} else { } else {
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
} }
@ -379,10 +418,10 @@ void CConfigManager::loadConfigLoadVars() {
// reset all vars before loading // reset all vars before loading
setDefaultVars(); setDefaultVars();
m_dMonitorRules.clear(); m_dMonitorRules.clear();
m_dWindowRules.clear(); m_dWindowRules.clear();
g_pKeybindManager->clearKeybinds(); g_pKeybindManager->clearKeybinds();
g_pAnimationManager->removeAllBeziers();
const char* const ENVHOME = getenv("HOME"); const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf"); const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");

View file

@ -92,6 +92,7 @@ private:
void handleUnbind(const std::string&, const std::string&); void handleUnbind(const std::string&, const std::string&);
void handleWindowRule(const std::string&, const std::string&); void handleWindowRule(const std::string&, const std::string&);
void handleDefaultWorkspace(const std::string&, const std::string&); void handleDefaultWorkspace(const std::string&, const std::string&);
void handleBezier(const std::string&, const std::string&);
}; };
inline std::unique_ptr<CConfigManager> g_pConfigManager; inline std::unique_ptr<CConfigManager> g_pConfigManager;

View file

@ -5,19 +5,20 @@ CAnimatedVariable::CAnimatedVariable() {
; // dummy var ; // dummy var
} }
void CAnimatedVariable::create(ANIMATEDVARTYPE type, float* speed, int64_t* enabled, void* pWindow) { void CAnimatedVariable::create(ANIMATEDVARTYPE type, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow) {
m_eVarType = type; m_eVarType = type;
m_pSpeed = speed; m_pSpeed = speed;
m_pEnabled = enabled; m_pEnabled = enabled;
m_pWindow = pWindow; m_pWindow = pWindow;
m_pBezier = pBezier;
g_pAnimationManager->m_lAnimatedVariables.push_back(this); g_pAnimationManager->m_lAnimatedVariables.push_back(this);
m_bDummy = false; m_bDummy = false;
} }
void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, float* speed, int64_t* enabled, void* pWindow) { void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow) {
create(type, speed, enabled, pWindow); create(type, speed, enabled, pBezier, pWindow);
try { try {
switch (type) { switch (type) {

View file

@ -16,8 +16,8 @@ class CAnimatedVariable {
public: public:
CAnimatedVariable(); // dummy var CAnimatedVariable(); // dummy var
void create(ANIMATEDVARTYPE, float* speed, int64_t* enabled, void* pWindow); void create(ANIMATEDVARTYPE, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow);
void create(ANIMATEDVARTYPE, std::any val, float* speed, int64_t* enabled, void* pWindow); void create(ANIMATEDVARTYPE, std::any val, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow);
~CAnimatedVariable(); ~CAnimatedVariable();
@ -60,34 +60,46 @@ public:
void operator=(const Vector2D& v) { void operator=(const Vector2D& v) {
ASSERT(m_eVarType == AVARTYPE_VECTOR); ASSERT(m_eVarType == AVARTYPE_VECTOR);
m_vGoal = v; m_vGoal = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
} }
void operator=(const float& v) { void operator=(const float& v) {
ASSERT(m_eVarType == AVARTYPE_FLOAT); ASSERT(m_eVarType == AVARTYPE_FLOAT);
m_fGoal = v; m_fGoal = v;
animationBegin = std::chrono::system_clock::now();
m_fBegun = m_fValue;
} }
void operator=(const CColor& v) { void operator=(const CColor& v) {
ASSERT(m_eVarType == AVARTYPE_COLOR); ASSERT(m_eVarType == AVARTYPE_COLOR);
m_cGoal = v; m_cGoal = v;
animationBegin = std::chrono::system_clock::now();
m_cBegun = m_cValue;
} }
// Sets the actual stored value, without affecting the goal // Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const Vector2D& v) { void setValue(const Vector2D& v) {
ASSERT(m_eVarType == AVARTYPE_VECTOR); ASSERT(m_eVarType == AVARTYPE_VECTOR);
m_vValue = v; m_vValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
} }
// Sets the actual stored value, without affecting the goal // Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const float& v) { void setValue(const float& v) {
ASSERT(m_eVarType == AVARTYPE_FLOAT); ASSERT(m_eVarType == AVARTYPE_FLOAT);
m_fValue = v; m_fValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
} }
// Sets the actual stored value, without affecting the goal // Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const CColor& v) { void setValue(const CColor& v) {
ASSERT(m_eVarType == AVARTYPE_COLOR); ASSERT(m_eVarType == AVARTYPE_COLOR);
m_cValue = v; m_cValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
} }
// Sets the actual value and goal // Sets the actual value and goal
@ -140,12 +152,19 @@ private:
float m_fGoal = 0; float m_fGoal = 0;
CColor m_cGoal; CColor m_cGoal;
Vector2D m_vBegun = Vector2D(0,0);
float m_fBegun = 0;
CColor m_cBegun;
float* m_pSpeed = nullptr; float* m_pSpeed = nullptr;
int64_t* m_pEnabled = nullptr; int64_t* m_pEnabled = nullptr;
void* m_pWindow = nullptr; void* m_pWindow = nullptr;
std::string* m_pBezier = nullptr;
bool m_bDummy = true; bool m_bDummy = true;
std::chrono::system_clock::time_point animationBegin;
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID; ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
friend class CAnimationManager; friend class CAnimationManager;

View file

@ -0,0 +1,55 @@
#include "BezierCurve.hpp"
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
m_dPoints.clear();
m_dPoints.emplace_back(Vector2D(0,0));
for (auto& p : *pVec) {
m_dPoints.push_back(p);
}
m_dPoints.emplace_back(Vector2D(1,1));
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: %i)", m_dPoints.size());
// bake 100 points for faster lookups
// T -> X ( / 100 )
for (int i = 0; i < 100; ++i) {
m_aPointsBaked[i] = getXForT((i + 1) / 100.f);
}
}
float CBezierCurve::getYForT(float t) {
return 3 * t * pow(1 - t, 2) * m_dPoints[1].y + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].y + pow(t, 3);
}
float CBezierCurve::getXForT(float t) {
return 3 * t * pow(1 - t, 2) * m_dPoints[1].x + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].x + pow(t, 3);
}
// Todo: this probably can be done better and faster
float CBezierCurve::getYForPoint(float x) {
// binary search for the range UPDOWN X
float upperX = 1;
float lowerX = 0;
float mid = 0.5;
while(std::abs(upperX - lowerX) > 0.01f) {
if (m_aPointsBaked[((int)(mid * 100.f))] > x) {
upperX = mid;
} else {
lowerX = mid;
}
mid = (upperX + lowerX) / 2.f;
}
// in the name of performance i shall make a hack
const auto PERCINDELTA = (x - m_aPointsBaked[(int)(100.f * lowerX)]) / (m_aPointsBaked[(int)(100.f * upperX)] - m_aPointsBaked[(int)(100.f * lowerX)]);
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
return 0.f;
return getYForT(mid + PERCINDELTA * 0.01f);
}

View file

@ -0,0 +1,24 @@
#pragma once
#include "../defines.hpp"
#include <deque>
// an implementation of a cubic bezier curve
// might do better later
// TODO: n-point curves
class CBezierCurve {
public:
// sets up the bezier curve.
// this EXCLUDES the 0,0 and 1,1 points,
void setup(std::vector<Vector2D>* points);
float getYForT(float t);
float getXForT(float t);
float getYForPoint(float x);
private:
// this INCLUDES the 0,0 and 1,1 points.
std::deque<Vector2D> m_dPoints;
std::array<float, 100> m_aPointsBaked;
};

View file

@ -12,4 +12,16 @@ public:
uint64_t getAsHex(); uint64_t getAsHex();
CColor operator- (const CColor& c2) const {
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
}
CColor operator+ (const CColor& c2) const {
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
}
CColor operator* (const float& v) const {
return CColor(r * v, g * v, b * v, a * v);
}
}; };

View file

@ -451,10 +451,10 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA); DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
} else { } else {
if (DRAGGINGWINDOW->m_bIsFloating) { if (DRAGGINGWINDOW->m_bIsFloating) {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA); DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999))); DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.vec()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else { } else {
// we need to adjust the splitratio // we need to adjust the splitratio

View file

@ -1,6 +1,24 @@
#include "AnimationManager.hpp" #include "AnimationManager.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
CAnimationManager::CAnimationManager() {
std::vector<Vector2D> points = {Vector2D(0, 0.75f), Vector2D(0.25f, 1.f)};
m_mBezierCurves["default"].setup(&points);
}
void CAnimationManager::removeAllBeziers() {
m_mBezierCurves.clear();
// add the default one
std::vector<Vector2D> points = {Vector2D(0, 0.75f), Vector2D(0.25f, 1.f)};
m_mBezierCurves["default"].setup(&points);
}
void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1, const Vector2D& p2) {
std::vector points = {p1, p2};
m_mBezierCurves[name].setup(&points);
}
void CAnimationManager::tick() { void CAnimationManager::tick() {
bool animationsDisabled = false; bool animationsDisabled = false;
@ -9,61 +27,88 @@ void CAnimationManager::tick() {
animationsDisabled = true; animationsDisabled = true;
const float ANIMSPEED = g_pConfigManager->getFloat("animations:speed"); const float ANIMSPEED = g_pConfigManager->getFloat("animations:speed");
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size"); const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
const auto BEZIERSTR = g_pConfigManager->getString("animations:curve");
auto DEFAULTBEZIER = m_mBezierCurves.find(BEZIERSTR);
if (DEFAULTBEZIER == m_mBezierCurves.end())
DEFAULTBEZIER = m_mBezierCurves.find("default");
for (auto& av : m_lAnimatedVariables) { for (auto& av : m_lAnimatedVariables) {
// first, we check if it's disabled, if so, warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
continue;
}
// get speed // get speed
const auto SPEED = *av->m_pSpeed == 0 ? ANIMSPEED : *av->m_pSpeed; const auto SPEED = *av->m_pSpeed == 0 ? ANIMSPEED : *av->m_pSpeed;
// window stuff // window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow; const auto PWINDOW = (CWindow*)av->m_pWindow;
bool needsDamage = false;
wlr_box WLRBOXPREV = {PWINDOW->m_vRealPosition.vec().x - BORDERSIZE - 1, PWINDOW->m_vRealPosition.vec().y - BORDERSIZE - 1, PWINDOW->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, PWINDOW->m_vRealSize.vec().y + 2 * BORDERSIZE + 2}; wlr_box WLRBOXPREV = {PWINDOW->m_vRealPosition.vec().x - BORDERSIZE - 1, PWINDOW->m_vRealPosition.vec().y - BORDERSIZE - 1, PWINDOW->m_vRealSize.vec().x + 2 * BORDERSIZE + 2, PWINDOW->m_vRealSize.vec().y + 2 * BORDERSIZE + 2};
// TODO: curves // check if it's disabled, if so, warp
if (av->m_pEnabled == 0 || animationsDisabled) {
av->warp();
g_pHyprRenderer->damageBox(&WLRBOXPREV);
g_pHyprRenderer->damageWindow(PWINDOW);
continue;
}
// parabolic with a switch unforto // beziers are with a switch unforto
// TODO: maybe do something cleaner // TODO: maybe do something cleaner
// get the spent % (0 - 1)
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - av->animationBegin).count();
const float SPENT = std::clamp((DURATIONPASSED / 100.f) / SPEED, 0.f, 1.f);
switch (av->m_eVarType) { switch (av->m_eVarType) {
case AVARTYPE_FLOAT: { case AVARTYPE_FLOAT: {
if (!deltazero(av->m_fValue, av->m_fGoal)) { if (!deltazero(av->m_fValue, av->m_fGoal)) {
if (deltaSmallToFlip(av->m_fValue, av->m_fGoal)) { const auto DELTA = av->m_fGoal - av->m_fBegun;
av->warp(); const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
} else {
av->m_fValue = parabolic(av->m_fValue, av->m_fGoal, SPEED);
}
needsDamage = true; if (BEZIER != m_mBezierCurves.end())
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
else
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
if (SPENT >= 1.f) {
av->warp();
}
} else {
continue; // dont process
} }
break; break;
} }
case AVARTYPE_VECTOR: { case AVARTYPE_VECTOR: {
if (!deltazero(av->m_vValue, av->m_vGoal)) { if (!deltazero(av->m_vValue, av->m_vGoal)) {
if (deltaSmallToFlip(av->m_vValue, av->m_vGoal)) { const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
if (SPENT >= 1.f) {
av->warp(); av->warp();
} else {
av->m_vValue.x = parabolic(av->m_vValue.x, av->m_vGoal.x, SPEED);
av->m_vValue.y = parabolic(av->m_vValue.y, av->m_vGoal.y, SPEED);
} }
needsDamage = true; } else {
continue; // dont process
} }
break; break;
} }
case AVARTYPE_COLOR: { case AVARTYPE_COLOR: {
if (!deltazero(av->m_cValue, av->m_cGoal)) { if (!deltazero(av->m_cValue, av->m_cGoal)) {
if (deltaSmallToFlip(av->m_cValue, av->m_cGoal)) { const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
if (BEZIER != m_mBezierCurves.end())
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
else
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
if (SPENT >= 1.f) {
av->warp(); av->warp();
} else {
av->m_cValue = parabolic(SPEED, av->m_cValue, av->m_cGoal);
} }
needsDamage = true; } else {
continue; // dont process
} }
break; break;
} }
@ -72,13 +117,11 @@ void CAnimationManager::tick() {
} }
} }
// invalidate the window // damage the window
if (needsDamage) {
g_pHyprRenderer->damageBox(&WLRBOXPREV); g_pHyprRenderer->damageBox(&WLRBOXPREV);
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
} }
}
bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) { bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) {
return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f; return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f;
@ -103,18 +146,3 @@ bool CAnimationManager::deltazero(const float& a, const float& b) {
bool CAnimationManager::deltazero(const CColor& a, const CColor& b) { bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
} }
double CAnimationManager::parabolic(const double from, const double to, const double incline) {
return from + ((to - from) / incline);
}
CColor CAnimationManager::parabolic(const double incline, const CColor& from, const CColor& to) {
CColor newColor;
newColor.r = parabolic(from.r, to.r, incline);
newColor.g = parabolic(from.g, to.g, incline);
newColor.b = parabolic(from.b, to.b, incline);
newColor.a = parabolic(from.a, to.a, incline);
return newColor;
}

View file

@ -2,12 +2,18 @@
#include "../defines.hpp" #include "../defines.hpp"
#include <list> #include <list>
#include <unordered_map>
#include "../helpers/AnimatedVariable.hpp" #include "../helpers/AnimatedVariable.hpp"
#include "../helpers/BezierCurve.hpp"
class CAnimationManager { class CAnimationManager {
public: public:
CAnimationManager();
void tick(); void tick();
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
void removeAllBeziers();
std::list<CAnimatedVariable*> m_lAnimatedVariables; std::list<CAnimatedVariable*> m_lAnimatedVariables;
@ -18,8 +24,8 @@ private:
bool deltazero(const Vector2D& a, const Vector2D& b); bool deltazero(const Vector2D& a, const Vector2D& b);
bool deltazero(const CColor& a, const CColor& b); bool deltazero(const CColor& a, const CColor& b);
bool deltazero(const float& a, const float& b); bool deltazero(const float& a, const float& b);
double parabolic(const double, const double, const double);
CColor parabolic(const double, const CColor&, const CColor&); std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
}; };
inline std::unique_ptr<CAnimationManager> g_pAnimationManager; inline std::unique_ptr<CAnimationManager> g_pAnimationManager;