Skip to content

Commit

Permalink
core: introduce animation manager and animation config (#631)
Browse files Browse the repository at this point in the history
BREAKING:
- Removed `input-field:dots_fade_time`. Now configured via
`animation=inputFieldDots,...`
- Removed `input-field:fail_transition`. Now configured via
`animation=inputFieldColors,...`
- Removed `general:no_fade_in` and `general:no_fade_out`. Now configured
globally via `animations:enabled` or via `animation=fadeIn,...` and
`animation=fadeOut,...`
  • Loading branch information
PaideiaDilemma authored Jan 6, 2025
1 parent 8f68fad commit 00d2cbf
Show file tree
Hide file tree
Showing 27 changed files with 788 additions and 425 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pkg_check_modules(
pangocairo
libdrm
gbm
hyprutils>=0.2.6
hyprutils>=0.3.3
sdbus-c++>=2.0.0
hyprgraphics)

Expand Down
18 changes: 9 additions & 9 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 20 additions & 3 deletions src/config/ConfigDataValues.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,30 +62,47 @@ class CLayoutValueData : public ICustomConfigValueData {
class CGradientValueData : public ICustomConfigValueData {
public:
CGradientValueData() {};
CGradientValueData(CColor col) {
CGradientValueData(CHyprColor col) {
m_vColors.push_back(col);
updateColorsOk();
};
virtual ~CGradientValueData() {};

virtual eConfigValueDataTypes getDataType() {
return CVD_TYPE_GRADIENT;
}

void reset(CColor col) {
void reset(CHyprColor col) {
m_vColors.clear();
m_vColors.emplace_back(col);
m_fAngle = 0;
updateColorsOk();
}

void updateColorsOk() {
m_vColorsOkLabA.clear();
for (auto& c : m_vColors) {
const auto OKLAB = c.asOkLab();
m_vColorsOkLabA.emplace_back(OKLAB.l);
m_vColorsOkLabA.emplace_back(OKLAB.a);
m_vColorsOkLabA.emplace_back(OKLAB.b);
m_vColorsOkLabA.emplace_back(c.a);
}
}

/* Vector containing the colors */
std::vector<CColor> m_vColors;
std::vector<CHyprColor> m_vColors;

/* Vector containing pure colors for shoving into opengl */
std::vector<float> m_vColorsOkLabA;

/* Float corresponding to the angle (rad) */
float m_fAngle = 0;

/* Whether this gradient stores a fallback value (not exlicitly set) */
bool m_bIsFallback = false;

//
bool operator==(const CGradientValueData& other) const {
if (other.m_vColors.size() != m_vColors.size() || m_fAngle != other.m_fAngle)
return false;
Expand Down
141 changes: 133 additions & 8 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#include "ConfigManager.hpp"
#include "ConfigDataValues.hpp"
#include "../helpers/MiscFunctions.hpp"
#include "../helpers/Log.hpp"
#include "../config/ConfigDataValues.hpp"
#include "../core/AnimationManager.hpp"
#include <hyprlang.hpp>
#include <hyprutils/string/String.hpp>
#include <hyprutils/path/Path.hpp>
#include <hyprutils/string/String.hpp>
#include <filesystem>
#include <glob.h>
#include <cstring>
#include <mutex>

using namespace Hyprutils::String;
using namespace Hyprutils::Animation;

ICustomConfigValueData::~ICustomConfigValueData() {
; // empty
}
Expand All @@ -26,6 +31,30 @@ static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
return result;
}

static Hyprlang::CParseResult handleBezier(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;

const auto RESULT = g_pConfigManager->handleBezier(COMMAND, VALUE);

Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}

static Hyprlang::CParseResult handleAnimation(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;

const auto RESULT = g_pConfigManager->handleAnimation(COMMAND, VALUE);

Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}

static Hyprlang::CParseResult configHandleLayoutOption(const char* v, void** data) {
const std::string VALUE = v;

Expand Down Expand Up @@ -120,7 +149,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void**
continue;

try {
DATA->m_vColors.push_back(CColor(configStringToInt(var)));
DATA->m_vColors.push_back(CHyprColor(configStringToInt(var)));
} catch (std::exception& e) {
Debug::log(WARN, "Error parsing gradient {}", V);
parseError = "Error parsing gradient " + V + ": " + e.what();
Expand All @@ -139,6 +168,8 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void**
DATA->m_vColors.push_back(0); // transparent
}

DATA->updateColorsOk();

Hyprlang::CParseResult result;
if (!parseError.empty())
result.setError(parseError.c_str());
Expand Down Expand Up @@ -183,8 +214,6 @@ void CConfigManager::init() {
m_config.addConfigValue("general:text_trim", Hyprlang::INT{1});
m_config.addConfigValue("general:hide_cursor", Hyprlang::INT{0});
m_config.addConfigValue("general:grace", Hyprlang::INT{0});
m_config.addConfigValue("general:no_fade_in", Hyprlang::INT{0});
m_config.addConfigValue("general:no_fade_out", Hyprlang::INT{0});
m_config.addConfigValue("general:ignore_empty_input", Hyprlang::INT{0});
m_config.addConfigValue("general:immediate_render", Hyprlang::INT{0});
m_config.addConfigValue("general:fractional_scaling", Hyprlang::INT{2});
Expand All @@ -196,6 +225,8 @@ void CConfigManager::init() {
m_config.addConfigValue("auth:fingerprint:present_message", Hyprlang::STRING{"Scanning fingerprint"});
m_config.addConfigValue("auth:fingerprint:retry_delay", Hyprlang::INT{250});

m_config.addConfigValue("animations:enabled", Hyprlang::INT{1});

m_config.addSpecialCategory("background", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("background", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("background", "path", Hyprlang::STRING{""});
Expand Down Expand Up @@ -253,7 +284,6 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("input-field", "dots_center", Hyprlang::INT{1});
m_config.addSpecialConfigValue("input-field", "dots_spacing", Hyprlang::FLOAT{0.2});
m_config.addSpecialConfigValue("input-field", "dots_rounding", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("input-field", "dots_fade_time", Hyprlang::INT{200});
m_config.addSpecialConfigValue("input-field", "dots_text_format", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("input-field", "fade_on_empty", Hyprlang::INT{1});
m_config.addSpecialConfigValue("input-field", "fade_timeout", Hyprlang::INT{2000});
Expand All @@ -269,7 +299,6 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("input-field", "fail_color", GRADIENTCONFIG("0xFFCC2222"));
m_config.addSpecialConfigValue("input-field", "fail_text", Hyprlang::STRING{"<i>$FAIL</i>"});
m_config.addSpecialConfigValue("input-field", "fail_timeout", Hyprlang::INT{2000});
m_config.addSpecialConfigValue("input-field", "fail_transition", Hyprlang::INT{300});
m_config.addSpecialConfigValue("input-field", "capslock_color", GRADIENTCONFIG(""));
m_config.addSpecialConfigValue("input-field", "numlock_color", GRADIENTCONFIG(""));
m_config.addSpecialConfigValue("input-field", "bothlock_color", GRADIENTCONFIG(""));
Expand All @@ -293,6 +322,30 @@ void CConfigManager::init() {
SHADOWABLE("label");

m_config.registerHandler(&::handleSource, "source", {false});
m_config.registerHandler(&::handleBezier, "bezier", {false});
m_config.registerHandler(&::handleAnimation, "animation", {false});

//
// Init Animations
//
m_AnimationTree.createNode("global");

// toplevel
m_AnimationTree.createNode("fade", "global");
m_AnimationTree.createNode("inputField", "global");

// inputField
m_AnimationTree.createNode("inputFieldColors", "inputField");
m_AnimationTree.createNode("inputFieldFade", "inputField");
m_AnimationTree.createNode("inputFieldWidth", "inputField");
m_AnimationTree.createNode("inputFieldDots", "inputField");

// fade
m_AnimationTree.createNode("fadeIn", "fade");
m_AnimationTree.createNode("fadeOut", "fade");

// set config for root node
m_AnimationTree.setConfigForNode("global", 1, 8.f, "default");

m_config.commence();

Expand Down Expand Up @@ -412,7 +465,6 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
{"dots_spacing", m_config.getSpecialConfigValue("input-field", "dots_spacing", k.c_str())},
{"dots_center", m_config.getSpecialConfigValue("input-field", "dots_center", k.c_str())},
{"dots_rounding", m_config.getSpecialConfigValue("input-field", "dots_rounding", k.c_str())},
{"dots_fade_time", m_config.getSpecialConfigValue("input-field", "dots_fade_time", k.c_str())},
{"dots_text_format", m_config.getSpecialConfigValue("input-field", "dots_text_format", k.c_str())},
{"fade_on_empty", m_config.getSpecialConfigValue("input-field", "fade_on_empty", k.c_str())},
{"fade_timeout", m_config.getSpecialConfigValue("input-field", "fade_timeout", k.c_str())},
Expand All @@ -428,7 +480,6 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
{"fail_color", m_config.getSpecialConfigValue("input-field", "fail_color", k.c_str())},
{"fail_text", m_config.getSpecialConfigValue("input-field", "fail_text", k.c_str())},
{"fail_timeout", m_config.getSpecialConfigValue("input-field", "fail_timeout", k.c_str())},
{"fail_transition", m_config.getSpecialConfigValue("input-field", "fail_transition", k.c_str())},
{"capslock_color", m_config.getSpecialConfigValue("input-field", "capslock_color", k.c_str())},
{"numlock_color", m_config.getSpecialConfigValue("input-field", "numlock_color", k.c_str())},
{"bothlock_color", m_config.getSpecialConfigValue("input-field", "bothlock_color", k.c_str())},
Expand Down Expand Up @@ -512,3 +563,77 @@ std::optional<std::string> CConfigManager::handleSource(const std::string& comma

return {};
}

std::optional<std::string> CConfigManager::handleBezier(const std::string& command, const std::string& args) {
const auto ARGS = CVarList(args);

std::string bezierName = ARGS[0];

if (ARGS[1] == "")
return "too few arguments";
float p1x = std::stof(ARGS[1]);

if (ARGS[2] == "")
return "too few arguments";
float p1y = std::stof(ARGS[2]);

if (ARGS[3] == "")
return "too few arguments";
float p2x = std::stof(ARGS[3]);

if (ARGS[4] == "")
return "too few arguments";
float p2y = std::stof(ARGS[4]);

if (ARGS[5] != "")
return "too many arguments";

g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));

return {};
}

std::optional<std::string> CConfigManager::handleAnimation(const std::string& command, const std::string& args) {
const auto ARGS = CVarList(args);

const auto ANIMNAME = ARGS[0];

if (!m_AnimationTree.nodeExists(ANIMNAME))
return "no such animation";

// This helper casts strings like "1", "true", "off", "yes"... to int.
int64_t enabledInt = configStringToInt(ARGS[1]);

// Checking that the int is 1 or 0 because the helper can return integers out of range.
if (enabledInt != 0 && enabledInt != 1)
return "invalid animation on/off state";

if (enabledInt) {
int64_t speed = -1;

// speed
if (isNumber(ARGS[2], true)) {
speed = std::stof(ARGS[2]);

if (speed <= 0) {
speed = 1.f;
return "invalid speed";
}
} else {
speed = 10.f;
return "invalid speed";
}

std::string bezierName = ARGS[3];
// ARGS[4] (style) currently usused by hyprlock
m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, ARGS[3], "");

if (!g_pAnimationManager->bezierExists(bezierName)) {
const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME);
PANIMNODE->internalBezier = "default";
return "no such bezier";
}
}

return {};
}
15 changes: 12 additions & 3 deletions src/config/ConfigManager.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#pragma once

#include <hyprutils/animation/AnimationConfig.hpp>

#include <hyprlang.hpp>
#include <optional>
#include <vector>
#include <memory>
#include <unordered_map>

#include "../defines.hpp"

class CConfigManager {
public:
CConfigManager(std::string configPath);
Expand All @@ -19,10 +23,15 @@ class CConfigManager {
std::unordered_map<std::string, std::any> values;
};

std::vector<SWidgetConfig> getWidgetConfigs();
std::optional<std::string> handleSource(const std::string&, const std::string&);
std::vector<SWidgetConfig> getWidgetConfigs();

std::optional<std::string> handleSource(const std::string&, const std::string&);
std::optional<std::string> handleBezier(const std::string&, const std::string&);
std::optional<std::string> handleAnimation(const std::string&, const std::string&);

std::string configCurrentPath;

std::string configCurrentPath;
Hyprutils::Animation::CAnimationConfigTree m_AnimationTree;

private:
Hyprlang::CConfig m_config;
Expand Down
Loading

0 comments on commit 00d2cbf

Please sign in to comment.