mirror of
https://github.com/hyprwm/hyprlock.git
synced 2025-02-03 16:29:48 +01:00
core: introduce animation manager and animation config (#631)
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,...`
This commit is contained in:
parent
8f68fad50a
commit
00d2cbfee3
27 changed files with 787 additions and 424 deletions
|
@ -76,7 +76,7 @@ pkg_check_modules(
|
|||
pangocairo
|
||||
libdrm
|
||||
gbm
|
||||
hyprutils>=0.2.6
|
||||
hyprutils>=0.3.3
|
||||
sdbus-c++>=2.0.0
|
||||
hyprgraphics)
|
||||
|
||||
|
|
18
flake.lock
18
flake.lock
|
@ -13,11 +13,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1734906236,
|
||||
"narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=",
|
||||
"lastModified": 1736115290,
|
||||
"narHash": "sha256-Jcn6yAzfUMcxy3tN/iZRbi/QgrYm7XLyVRl9g/nbUl4=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c",
|
||||
"rev": "52202272d89da32a9f866c0d10305a5e3d954c50",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -62,11 +62,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1735316583,
|
||||
"narHash": "sha256-AiiUwHWHfEdpFzXy7l1x3zInCUa1xcRMrbZ1XRSkzwU=",
|
||||
"lastModified": 1736164519,
|
||||
"narHash": "sha256-1LimBKvDpBbeX+qW7T240WEyw+DBVpDotZB4JYm8Aps=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "8f15d45b120b33712f6db477fe5ffb18034d0ea8",
|
||||
"rev": "3c895da64b0eb19870142196fa48c07090b441c4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -100,11 +100,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1735291276,
|
||||
"narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=",
|
||||
"lastModified": 1736012469,
|
||||
"narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "634fd46801442d760e09493a794c4f15db2d0cbb",
|
||||
"rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -62,8 +62,9 @@ class CLayoutValueData : public ICustomConfigValueData {
|
|||
class CGradientValueData : public ICustomConfigValueData {
|
||||
public:
|
||||
CGradientValueData() {};
|
||||
CGradientValueData(CColor col) {
|
||||
CGradientValueData(CHyprColor col) {
|
||||
m_vColors.push_back(col);
|
||||
updateColorsOk();
|
||||
};
|
||||
virtual ~CGradientValueData() {};
|
||||
|
||||
|
@ -71,14 +72,29 @@ class CGradientValueData : public ICustomConfigValueData {
|
|||
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;
|
||||
|
@ -86,6 +102,7 @@ class CGradientValueData : public ICustomConfigValueData {
|
|||
/* 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;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#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>
|
||||
|
@ -10,6 +12,9 @@
|
|||
#include <cstring>
|
||||
#include <mutex>
|
||||
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::Animation;
|
||||
|
||||
ICustomConfigValueData::~ICustomConfigValueData() {
|
||||
; // empty
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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});
|
||||
|
@ -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{""});
|
||||
|
@ -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});
|
||||
|
@ -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(""));
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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())},
|
||||
|
@ -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())},
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -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::string configCurrentPath;
|
||||
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;
|
||||
|
||||
Hyprutils::Animation::CAnimationConfigTree m_AnimationTree;
|
||||
|
||||
private:
|
||||
Hyprlang::CConfig m_config;
|
||||
|
|
127
src/core/AnimationManager.cpp
Normal file
127
src/core/AnimationManager.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include "AnimationManager.hpp"
|
||||
#include "../helpers/AnimatedVariable.hpp"
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
CHyprlockAnimationManager::CHyprlockAnimationManager() {
|
||||
;
|
||||
}
|
||||
|
||||
template <Animable VarType>
|
||||
void updateVariable(CAnimatedVariable<VarType>& av, const float POINTY, bool warp = false) {
|
||||
if (POINTY >= 1.f || warp || !av.enabled() || av.value() == av.goal()) {
|
||||
av.warp();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto DELTA = av.goal() - av.begun();
|
||||
av.value() = av.begun() + DELTA * POINTY;
|
||||
}
|
||||
|
||||
void updateColorVariable(CAnimatedVariable<CHyprColor>& av, const float POINTY, bool warp = false) {
|
||||
if (POINTY >= 1.f || warp || !av.enabled() || av.value() == av.goal()) {
|
||||
av.warp();
|
||||
return;
|
||||
}
|
||||
|
||||
// convert both to OkLab, then lerp that, and convert back.
|
||||
// This is not as fast as just lerping rgb, but it's WAY more precise...
|
||||
// Use the CHyprColor cache for OkLab
|
||||
|
||||
const auto& L1 = av.begun().asOkLab();
|
||||
const auto& L2 = av.goal().asOkLab();
|
||||
|
||||
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
|
||||
|
||||
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
|
||||
.l = lerp(L1.l, L2.l, POINTY),
|
||||
.a = lerp(L1.a, L2.a, POINTY),
|
||||
.b = lerp(L1.b, L2.b, POINTY),
|
||||
};
|
||||
|
||||
av.value() = {lerped, lerp(av.begun().a, av.goal().a, POINTY)};
|
||||
}
|
||||
|
||||
void updateGradientVariable(CAnimatedVariable<CGradientValueData>& av, const float POINTY, bool warp = false) {
|
||||
if (POINTY >= 1.f || warp || av.value() == av.goal()) {
|
||||
av.warp();
|
||||
return;
|
||||
}
|
||||
|
||||
av.value().m_vColors.resize(av.goal().m_vColors.size(), av.goal().m_vColors.back());
|
||||
|
||||
for (size_t i = 0; i < av.value().m_vColors.size(); ++i) {
|
||||
const CHyprColor& sourceCol = (i < av.begun().m_vColors.size()) ? av.begun().m_vColors[i] : av.begun().m_vColors.back();
|
||||
const CHyprColor& targetCol = (i < av.goal().m_vColors.size()) ? av.goal().m_vColors[i] : av.goal().m_vColors.back();
|
||||
|
||||
const auto& L1 = sourceCol.asOkLab();
|
||||
const auto& L2 = targetCol.asOkLab();
|
||||
|
||||
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
|
||||
|
||||
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
|
||||
.l = lerp(L1.l, L2.l, POINTY),
|
||||
.a = lerp(L1.a, L2.a, POINTY),
|
||||
.b = lerp(L1.b, L2.b, POINTY),
|
||||
};
|
||||
|
||||
av.value().m_vColors[i] = {lerped, lerp(sourceCol.a, targetCol.a, POINTY)};
|
||||
av.value().updateColorsOk();
|
||||
}
|
||||
|
||||
if (av.begun().m_fAngle != av.goal().m_fAngle) {
|
||||
const float DELTA = av.goal().m_fAngle - av.begun().m_fAngle;
|
||||
av.value().m_fAngle = av.begun().m_fAngle + DELTA * POINTY;
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprlockAnimationManager::tick() {
|
||||
static auto* const PANIMATIONSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("animations:enabled");
|
||||
for (auto const& av : m_vActiveAnimatedVariables) {
|
||||
const auto PAV = av.lock();
|
||||
if (!PAV || !PAV->ok())
|
||||
continue;
|
||||
|
||||
const auto SPENT = PAV->getPercent();
|
||||
const auto PBEZIER = getBezier(PAV->getBezierName());
|
||||
const auto POINTY = PBEZIER->getYForPoint(SPENT);
|
||||
|
||||
switch (PAV->m_Type) {
|
||||
case AVARTYPE_FLOAT: {
|
||||
auto pTypedAV = dynamic_cast<CAnimatedVariable<float>*>(PAV.get());
|
||||
RASSERT(pTypedAV, "Failed to upcast animated float");
|
||||
updateVariable(*pTypedAV, POINTY, !**PANIMATIONSENABLED);
|
||||
} break;
|
||||
case AVARTYPE_VECTOR: {
|
||||
auto pTypedAV = dynamic_cast<CAnimatedVariable<Vector2D>*>(PAV.get());
|
||||
RASSERT(pTypedAV, "Failed to upcast animated Vector2D");
|
||||
updateVariable(*pTypedAV, POINTY, !**PANIMATIONSENABLED);
|
||||
} break;
|
||||
case AVARTYPE_COLOR: {
|
||||
auto pTypedAV = dynamic_cast<CAnimatedVariable<CHyprColor>*>(PAV.get());
|
||||
RASSERT(pTypedAV, "Failed to upcast animated CHyprColor");
|
||||
updateColorVariable(*pTypedAV, POINTY, !**PANIMATIONSENABLED);
|
||||
} break;
|
||||
case AVARTYPE_GRADIENT: {
|
||||
auto pTypedAV = dynamic_cast<CAnimatedVariable<CGradientValueData>*>(PAV.get());
|
||||
RASSERT(pTypedAV, "Failed to upcast animated CGradientValueData");
|
||||
updateGradientVariable(*pTypedAV, POINTY, !**PANIMATIONSENABLED);
|
||||
} break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
av->onUpdate();
|
||||
}
|
||||
|
||||
tickDone();
|
||||
}
|
||||
|
||||
void CHyprlockAnimationManager::scheduleTick() {
|
||||
m_bTickScheduled = true;
|
||||
}
|
||||
|
||||
void CHyprlockAnimationManager::onTicked() {
|
||||
m_bTickScheduled = false;
|
||||
}
|
34
src/core/AnimationManager.hpp
Normal file
34
src/core/AnimationManager.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <hyprutils/animation/AnimationManager.hpp>
|
||||
#include <hyprutils/animation/AnimatedVariable.hpp>
|
||||
|
||||
#include "../helpers/AnimatedVariable.hpp"
|
||||
#include "../helpers/Math.hpp"
|
||||
#include "../defines.hpp"
|
||||
|
||||
class CHyprlockAnimationManager : public Hyprutils::Animation::CAnimationManager {
|
||||
public:
|
||||
CHyprlockAnimationManager();
|
||||
|
||||
void tick();
|
||||
virtual void scheduleTick();
|
||||
virtual void onTicked();
|
||||
|
||||
using SAnimationPropertyConfig = Hyprutils::Animation::SAnimationPropertyConfig;
|
||||
|
||||
template <Animable VarType>
|
||||
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig) {
|
||||
constexpr const eAnimatedVarType EAVTYPE = typeToeAnimatedVarType<VarType>;
|
||||
const auto PAV = makeShared<CAnimatedVariable<VarType>>();
|
||||
|
||||
PAV->create(EAVTYPE, static_cast<Hyprutils::Animation::CAnimationManager*>(this), PAV, v);
|
||||
PAV->setConfig(pConfig);
|
||||
|
||||
pav = std::move(PAV);
|
||||
}
|
||||
|
||||
bool m_bTickScheduled = false;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprlockAnimationManager> g_pAnimationManager;
|
|
@ -1,9 +1,10 @@
|
|||
#include "LockSurface.hpp"
|
||||
#include "hyprlock.hpp"
|
||||
#include "../helpers/Log.hpp"
|
||||
#include "Egl.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
#include "../core/AnimationManager.hpp"
|
||||
#include "../helpers/Log.hpp"
|
||||
#include "../renderer/Renderer.hpp"
|
||||
#include "src/config/ConfigManager.hpp"
|
||||
|
||||
CSessionLockSurface::~CSessionLockSurface() {
|
||||
if (eglWindow)
|
||||
|
@ -123,6 +124,7 @@ void CSessionLockSurface::render() {
|
|||
return;
|
||||
}
|
||||
|
||||
g_pAnimationManager->tick();
|
||||
const auto FEEDBACK = g_pRenderer->renderLock(*this);
|
||||
frameCallback = makeShared<CCWlCallback>(surface->sendFrame());
|
||||
frameCallback->setDone([this](CCWlCallback* r, uint32_t data) {
|
||||
|
@ -134,7 +136,7 @@ void CSessionLockSurface::render() {
|
|||
|
||||
eglSwapBuffers(g_pEGL->eglDisplay, eglSurface);
|
||||
|
||||
needsFrame = FEEDBACK.needsFrame;
|
||||
needsFrame = FEEDBACK.needsFrame || g_pAnimationManager->shouldTickForNext();
|
||||
}
|
||||
|
||||
void CSessionLockSurface::onCallback() {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "hyprlock.hpp"
|
||||
#include "AnimationManager.hpp"
|
||||
#include "../helpers/Log.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
#include "../renderer/Renderer.hpp"
|
||||
|
@ -22,7 +23,7 @@
|
|||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender, const bool noFadeIn) {
|
||||
CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender) {
|
||||
m_sWaylandState.display = wl_display_connect(wlDisplay.empty() ? nullptr : wlDisplay.c_str());
|
||||
if (!m_sWaylandState.display) {
|
||||
Debug::log(CRIT, "Couldn't connect to a wayland compositor");
|
||||
|
@ -40,9 +41,6 @@ CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const b
|
|||
const auto PIMMEDIATERENDER = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:immediate_render");
|
||||
m_bImmediateRender = immediateRender || **PIMMEDIATERENDER;
|
||||
|
||||
const auto* const PNOFADEIN = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:no_fade_in");
|
||||
m_bNoFadeIn = noFadeIn || **PNOFADEIN;
|
||||
|
||||
const auto CURRENTDESKTOP = getenv("XDG_CURRENT_DESKTOP");
|
||||
const auto SZCURRENTD = std::string{CURRENTDESKTOP ? CURRENTDESKTOP : ""};
|
||||
m_sCurrentDesktop = SZCURRENTD;
|
||||
|
@ -316,9 +314,6 @@ void CHyprlock::run() {
|
|||
g_pAuth = std::make_unique<CAuth>();
|
||||
g_pAuth->start();
|
||||
|
||||
static auto* const PNOFADEOUT = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:no_fade_out");
|
||||
const bool NOFADEOUT = **PNOFADEOUT;
|
||||
|
||||
Debug::log(LOG, "Running on {}", m_sCurrentDesktop);
|
||||
|
||||
// Hyprland violates the protocol a bit to allow for this.
|
||||
|
@ -430,17 +425,13 @@ void CHyprlock::run() {
|
|||
});
|
||||
|
||||
m_sLoopState.event = true; // let it process once
|
||||
g_pRenderer->startFadeIn();
|
||||
|
||||
while (!m_bTerminate) {
|
||||
std::unique_lock lk(m_sLoopState.eventRequestMutex);
|
||||
if (m_sLoopState.event == false)
|
||||
m_sLoopState.loopCV.wait_for(lk, std::chrono::milliseconds(5000), [this] { return m_sLoopState.event; });
|
||||
|
||||
if (!NOFADEOUT && m_bFadeStarted && std::chrono::system_clock::now() > m_tFadeEnds) {
|
||||
releaseSessionLock();
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_bTerminate)
|
||||
break;
|
||||
|
||||
|
@ -494,11 +485,6 @@ void CHyprlock::run() {
|
|||
m_sLoopState.timersMutex.unlock();
|
||||
|
||||
passed.clear();
|
||||
|
||||
if (!NOFADEOUT && m_bFadeStarted && std::chrono::system_clock::now() > m_tFadeEnds) {
|
||||
releaseSessionLock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto DPY = m_sWaylandState.display;
|
||||
|
@ -529,21 +515,16 @@ void CHyprlock::run() {
|
|||
}
|
||||
|
||||
void CHyprlock::unlock() {
|
||||
static auto* const PNOFADEOUT = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:no_fade_out");
|
||||
const bool IMMEDIATE = m_sCurrentDesktop != "Hyprland";
|
||||
|
||||
if (**PNOFADEOUT || m_sCurrentDesktop != "Hyprland") {
|
||||
releaseSessionLock();
|
||||
return;
|
||||
}
|
||||
|
||||
m_tFadeEnds = std::chrono::system_clock::now() + std::chrono::milliseconds(500);
|
||||
m_bFadeStarted = true;
|
||||
g_pRenderer->startFadeOut(true, IMMEDIATE);
|
||||
m_bUnlockedCalled = true;
|
||||
|
||||
renderAllOutputs();
|
||||
}
|
||||
|
||||
bool CHyprlock::isUnlocked() {
|
||||
return m_bFadeStarted || m_bTerminate;
|
||||
return m_bUnlockedCalled || m_bTerminate;
|
||||
}
|
||||
|
||||
void CHyprlock::clearPasswordBuffer() {
|
||||
|
@ -607,7 +588,7 @@ void CHyprlock::repeatKey(xkb_keysym_t sym) {
|
|||
}
|
||||
|
||||
void CHyprlock::onKey(uint32_t key, bool down) {
|
||||
if (m_bFadeStarted || m_bTerminate)
|
||||
if (isUnlocked())
|
||||
return;
|
||||
|
||||
if (down && std::chrono::system_clock::now() < m_tGraceEnds) {
|
||||
|
@ -715,6 +696,7 @@ void CHyprlock::acquireSessionLock() {
|
|||
|
||||
void CHyprlock::releaseSessionLock() {
|
||||
Debug::log(LOG, "Unlocking session");
|
||||
|
||||
if (m_bTerminate) {
|
||||
Debug::log(ERR, "Unlock already happend?");
|
||||
return;
|
||||
|
|
|
@ -29,7 +29,7 @@ struct SDMABUFModifier {
|
|||
|
||||
class CHyprlock {
|
||||
public:
|
||||
CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender, const bool noFadeIn);
|
||||
CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender);
|
||||
~CHyprlock();
|
||||
|
||||
void run();
|
||||
|
@ -89,20 +89,16 @@ class CHyprlock {
|
|||
|
||||
bool m_bLocked = false;
|
||||
|
||||
bool m_bCapsLock = false;
|
||||
bool m_bNumLock = false;
|
||||
bool m_bCtrl = false;
|
||||
bool m_bFadeStarted = false;
|
||||
bool m_bCapsLock = false;
|
||||
bool m_bNumLock = false;
|
||||
bool m_bCtrl = false;
|
||||
|
||||
bool m_bImmediateRender = false;
|
||||
|
||||
bool m_bNoFadeIn = false;
|
||||
|
||||
std::string m_sCurrentDesktop = "";
|
||||
|
||||
//
|
||||
std::chrono::system_clock::time_point m_tGraceEnds;
|
||||
std::chrono::system_clock::time_point m_tFadeEnds;
|
||||
Vector2D m_vLastEnterCoords = {};
|
||||
|
||||
std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr;
|
||||
|
@ -160,6 +156,8 @@ class CHyprlock {
|
|||
bool timerEvent = false;
|
||||
} m_sLoopState;
|
||||
|
||||
bool m_bUnlockedCalled = false;
|
||||
|
||||
std::vector<std::shared_ptr<CTimer>> m_vTimers;
|
||||
|
||||
std::vector<uint32_t> m_vPressedKeys;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
using namespace Hyprutils::Memory;
|
||||
using namespace Hyprgraphics;
|
||||
#define SP CSharedPointer
|
||||
#define WP CWeakPointer
|
67
src/helpers/AnimatedVariable.hpp
Normal file
67
src/helpers/AnimatedVariable.hpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
#include <hyprutils/animation/AnimatedVariable.hpp>
|
||||
|
||||
#include "Color.hpp"
|
||||
#include "Math.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
|
||||
enum eAnimatedVarType {
|
||||
AVARTYPE_INVALID = -1,
|
||||
AVARTYPE_FLOAT,
|
||||
AVARTYPE_VECTOR,
|
||||
AVARTYPE_COLOR,
|
||||
AVARTYPE_GRADIENT
|
||||
};
|
||||
|
||||
// Utility to bind a type with its corresponding eAnimatedVarType
|
||||
template <class T>
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
struct STypeToAnimatedVarType_t {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_INVALID;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct STypeToAnimatedVarType_t<float> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_FLOAT;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct STypeToAnimatedVarType_t<Vector2D> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_VECTOR;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct STypeToAnimatedVarType_t<CHyprColor> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_COLOR;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct STypeToAnimatedVarType_t<CGradientValueData> {
|
||||
static constexpr eAnimatedVarType value = AVARTYPE_GRADIENT;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t<T>::value;
|
||||
|
||||
// Utility to define a concept as a list of possible type
|
||||
template <class T, class... U>
|
||||
concept OneOf = (... or std::same_as<T, U>);
|
||||
|
||||
// Concept to describe which type can be placed into CAnimatedVariable
|
||||
// This is mainly to get better errors if we put a type that's not supported
|
||||
// Otherwise template errors are ugly
|
||||
template <class T>
|
||||
concept Animable = OneOf<T, Vector2D, float, CHyprColor, CGradientValueData>;
|
||||
|
||||
struct SAnimationContext {};
|
||||
|
||||
template <Animable VarType>
|
||||
using CAnimatedVariable = Hyprutils::Animation::CGenericAnimatedVariable<VarType, SAnimationContext>;
|
||||
|
||||
template <Animable VarType>
|
||||
using PHLANIMVAR = SP<CAnimatedVariable<VarType>>;
|
||||
|
||||
template <Animable VarType>
|
||||
using PHLANIMVARREF = WP<CAnimatedVariable<VarType>>;
|
|
@ -5,22 +5,52 @@
|
|||
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
||||
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
||||
|
||||
CColor::CColor() {}
|
||||
CHyprColor::CHyprColor() {}
|
||||
|
||||
CColor::CColor(float r, float g, float b, float a) {
|
||||
this->r = r;
|
||||
this->g = g;
|
||||
this->b = b;
|
||||
this->a = a;
|
||||
CHyprColor::CHyprColor(float r_, float g_, float b_, float a_) {
|
||||
r = r_;
|
||||
g = g_;
|
||||
b = b_;
|
||||
a = a_;
|
||||
|
||||
okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab();
|
||||
}
|
||||
|
||||
CColor::CColor(uint64_t hex) {
|
||||
this->r = RED(hex);
|
||||
this->g = GREEN(hex);
|
||||
this->b = BLUE(hex);
|
||||
this->a = ALPHA(hex);
|
||||
CHyprColor::CHyprColor(uint64_t hex) {
|
||||
r = RED(hex);
|
||||
g = GREEN(hex);
|
||||
b = BLUE(hex);
|
||||
a = ALPHA(hex);
|
||||
|
||||
okLab = Hyprgraphics::CColor(Hyprgraphics::CColor::SSRGB{r, g, b}).asOkLab();
|
||||
}
|
||||
|
||||
uint32_t CColor::getAsHex() const {
|
||||
CHyprColor::CHyprColor(const Hyprgraphics::CColor& color, float a_) {
|
||||
const auto SRGB = color.asRgb();
|
||||
r = SRGB.r;
|
||||
g = SRGB.g;
|
||||
b = SRGB.b;
|
||||
a = a_;
|
||||
|
||||
okLab = color.asOkLab();
|
||||
}
|
||||
|
||||
uint32_t CHyprColor::getAsHex() const {
|
||||
return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1;
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::SSRGB CHyprColor::asRGB() const {
|
||||
return {r, g, b};
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::SOkLab CHyprColor::asOkLab() const {
|
||||
return okLab;
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::SHSL CHyprColor::asHSL() const {
|
||||
return Hyprgraphics::CColor(okLab).asHSL();
|
||||
}
|
||||
|
||||
CHyprColor CHyprColor::stripA() const {
|
||||
return {r, g, b, 1.F};
|
||||
}
|
|
@ -1,35 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "../helpers/Log.hpp"
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
|
||||
class CColor {
|
||||
class CHyprColor {
|
||||
public:
|
||||
CColor();
|
||||
CColor(float r, float g, float b, float a);
|
||||
CColor(uint64_t);
|
||||
|
||||
float r = 0, g = 0, b = 0, a = 1.f;
|
||||
CHyprColor();
|
||||
CHyprColor(float r, float g, float b, float a);
|
||||
CHyprColor(const Hyprgraphics::CColor& col, float a);
|
||||
CHyprColor(uint64_t);
|
||||
|
||||
// AR32
|
||||
uint32_t getAsHex() const;
|
||||
uint32_t getAsHex() const;
|
||||
Hyprgraphics::CColor::SSRGB asRGB() const;
|
||||
Hyprgraphics::CColor::SOkLab asOkLab() const;
|
||||
Hyprgraphics::CColor::SHSL asHSL() const;
|
||||
CHyprColor stripA() const;
|
||||
|
||||
CColor operator-(const CColor& c2) const {
|
||||
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
|
||||
//
|
||||
bool operator==(const CHyprColor& c2) const {
|
||||
return c2.r == r && c2.g == g && c2.b == b && c2.a == a;
|
||||
}
|
||||
|
||||
CColor operator+(const CColor& c2) const {
|
||||
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
|
||||
// stubs for the AnimationMgr
|
||||
CHyprColor operator-(const CHyprColor& c2) const {
|
||||
RASSERT(false, "CHyprColor: - is a STUB");
|
||||
return {};
|
||||
}
|
||||
|
||||
CColor operator*(const float& v) const {
|
||||
return CColor(r * v, g * v, b * v, a * v);
|
||||
CHyprColor operator+(const CHyprColor& c2) const {
|
||||
RASSERT(false, "CHyprColor: + is a STUB");
|
||||
return {};
|
||||
}
|
||||
|
||||
bool operator==(const CColor& c2) const {
|
||||
return r == c2.r && g == c2.g && b == c2.b && a == c2.a;
|
||||
CHyprColor operator*(const float& c2) const {
|
||||
RASSERT(false, "CHyprColor: * is a STUB");
|
||||
return {};
|
||||
}
|
||||
|
||||
CColor stripA() const {
|
||||
return {r, g, b, 1};
|
||||
}
|
||||
double r = 0, g = 0, b = 0, a = 0;
|
||||
|
||||
private:
|
||||
Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "config/ConfigManager.hpp"
|
||||
#include "core/hyprlock.hpp"
|
||||
#include "helpers/Log.hpp"
|
||||
#include "core/AnimationManager.hpp"
|
||||
#include <cstddef>
|
||||
#include <string_view>
|
||||
|
||||
|
@ -89,6 +90,8 @@ int main(int argc, char** argv, char** envp) {
|
|||
}
|
||||
}
|
||||
|
||||
g_pAnimationManager = std::make_unique<CHyprlockAnimationManager>();
|
||||
|
||||
try {
|
||||
g_pConfigManager = std::make_unique<CConfigManager>(configPath);
|
||||
g_pConfigManager->init();
|
||||
|
@ -100,8 +103,11 @@ int main(int argc, char** argv, char** envp) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (noFadeIn)
|
||||
g_pConfigManager->m_AnimationTree.setConfigForNode("fadeIn", false, 0.f, "default");
|
||||
|
||||
try {
|
||||
g_pHyprlock = std::make_unique<CHyprlock>(wlDisplay, immediate, immediateRender, noFadeIn);
|
||||
g_pHyprlock = std::make_unique<CHyprlock>(wlDisplay, immediate, immediateRender);
|
||||
g_pHyprlock->run();
|
||||
} catch (const std::exception& ex) {
|
||||
Debug::log(CRIT, "Hyprlock threw: {}", ex.what());
|
||||
|
|
|
@ -216,7 +216,7 @@ void CAsyncResourceGatherer::renderText(const SPreloadRequest& rq) {
|
|||
target.id = rq.id;
|
||||
|
||||
const int FONTSIZE = rq.props.contains("font_size") ? std::any_cast<int>(rq.props.at("font_size")) : 16;
|
||||
const CColor FONTCOLOR = rq.props.contains("color") ? std::any_cast<CColor>(rq.props.at("color")) : CColor(1.0, 1.0, 1.0, 1.0);
|
||||
const CHyprColor FONTCOLOR = rq.props.contains("color") ? std::any_cast<CHyprColor>(rq.props.at("color")) : CHyprColor(1.0, 1.0, 1.0, 1.0);
|
||||
const std::string FONTFAMILY = rq.props.contains("font_family") ? std::any_cast<std::string>(rq.props.at("font_family")) : "Sans";
|
||||
const bool ISCMD = rq.props.contains("cmd") ? std::any_cast<bool>(rq.props.at("cmd")) : false;
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
#include "Renderer.hpp"
|
||||
#include "../core/Egl.hpp"
|
||||
#include "Shaders.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
#include "../helpers/Color.hpp"
|
||||
#include "../core/AnimationManager.hpp"
|
||||
#include "../core/Egl.hpp"
|
||||
#include "../core/Output.hpp"
|
||||
#include "../core/hyprlock.hpp"
|
||||
#include "../helpers/Color.hpp"
|
||||
#include "../helpers/Log.hpp"
|
||||
#include "../renderer/DMAFrame.hpp"
|
||||
#include <GLES3/gl32.h>
|
||||
#include <GLES3/gl3ext.h>
|
||||
#include <algorithm>
|
||||
#include "Shaders.hpp"
|
||||
#include "src/helpers/Log.hpp"
|
||||
#include "widgets/PasswordInputField.hpp"
|
||||
#include "widgets/Background.hpp"
|
||||
#include "widgets/Label.hpp"
|
||||
|
@ -186,18 +187,22 @@ CRenderer::CRenderer() {
|
|||
borderShader.gradient = glGetUniformLocation(prog, "gradient");
|
||||
borderShader.gradientLength = glGetUniformLocation(prog, "gradientLength");
|
||||
borderShader.angle = glGetUniformLocation(prog, "angle");
|
||||
borderShader.gradient2 = glGetUniformLocation(prog, "gradient2");
|
||||
borderShader.gradient2Length = glGetUniformLocation(prog, "gradient2Length");
|
||||
borderShader.angle2 = glGetUniformLocation(prog, "angle2");
|
||||
borderShader.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
|
||||
borderShader.alpha = glGetUniformLocation(prog, "alpha");
|
||||
|
||||
asyncResourceGatherer = std::make_unique<CAsyncResourceGatherer>();
|
||||
|
||||
g_pAnimationManager->createAnimation(0.f, opacity, g_pConfigManager->m_AnimationTree.getConfig("fadeIn"));
|
||||
}
|
||||
|
||||
static int frames = 0;
|
||||
static bool firstFullFrame = false;
|
||||
static int frames = 0;
|
||||
|
||||
//
|
||||
CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf) {
|
||||
static auto* const PDISABLEBAR = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:disable_loading_bar");
|
||||
static auto* const PNOFADEOUT = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:no_fade_out");
|
||||
|
||||
projection = Mat3x3::outputProjection(surf.size, HYPRUTILS_TRANSFORM_NORMAL);
|
||||
|
||||
|
@ -215,7 +220,6 @@ CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf
|
|||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
SRenderFeedback feedback;
|
||||
float bga = 0.0;
|
||||
const bool WAITFORASSETS = !g_pHyprlock->m_bImmediateRender && !asyncResourceGatherer->gathered;
|
||||
|
||||
if (WAITFORASSETS) {
|
||||
|
@ -223,29 +227,14 @@ CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf
|
|||
// render status
|
||||
if (!**PDISABLEBAR) {
|
||||
CBox progress = {0, 0, asyncResourceGatherer->progress * surf.size.x, 2};
|
||||
renderRect(progress, CColor{0.2f, 0.1f, 0.1f, 1.f}, 0);
|
||||
renderRect(progress, CHyprColor{0.2f, 0.1f, 0.1f, 1.f}, 0);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!firstFullFrame) {
|
||||
firstFullFrameTime = std::chrono::system_clock::now();
|
||||
firstFullFrame = true;
|
||||
}
|
||||
|
||||
bga = std::clamp(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - firstFullFrameTime).count() / 500000.0, 0.0, 1.0);
|
||||
|
||||
if (g_pHyprlock->m_bNoFadeIn)
|
||||
bga = 1.0;
|
||||
|
||||
if (g_pHyprlock->m_bFadeStarted && !**PNOFADEOUT) {
|
||||
bga =
|
||||
std::clamp(std::chrono::duration_cast<std::chrono::microseconds>(g_pHyprlock->m_tFadeEnds - std::chrono::system_clock::now()).count() / 500000.0 - 0.02, 0.0, 1.0);
|
||||
// - 0.02 so that the fade ends a little earlier than the final second
|
||||
}
|
||||
// render widgets
|
||||
const auto WIDGETS = getOrCreateWidgetsFor(&surf);
|
||||
for (auto& w : *WIDGETS) {
|
||||
feedback.needsFrame = w->draw({bga}) || feedback.needsFrame;
|
||||
feedback.needsFrame = w->draw({opacity->value()}) || feedback.needsFrame;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,14 +242,14 @@ CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf
|
|||
|
||||
Debug::log(TRACE, "frame {}", frames);
|
||||
|
||||
feedback.needsFrame = feedback.needsFrame || !asyncResourceGatherer->gathered || bga < 1.0;
|
||||
feedback.needsFrame = feedback.needsFrame || !asyncResourceGatherer->gathered;
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
return feedback;
|
||||
}
|
||||
|
||||
void CRenderer::renderRect(const CBox& box, const CColor& col, int rounding) {
|
||||
void CRenderer::renderRect(const CBox& box, const CHyprColor& col, int rounding) {
|
||||
const auto ROUNDEDBOX = box.copy().round();
|
||||
Mat3x3 matrix = projMatrix.projectBox(ROUNDEDBOX, HYPRUTILS_TRANSFORM_NORMAL, box.rot);
|
||||
Mat3x3 glMatrix = projection.copy().multiply(matrix);
|
||||
|
@ -298,12 +287,11 @@ void CRenderer::renderBorder(const CBox& box, const CGradientValueData& gradient
|
|||
|
||||
glUniformMatrix3fv(borderShader.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
|
||||
|
||||
static_assert(sizeof(CColor) == 4 * sizeof(float)); // otherwise the line below this will fail
|
||||
|
||||
glUniform4fv(borderShader.gradient, gradient.m_vColors.size(), (float*)gradient.m_vColors.data());
|
||||
glUniform1i(borderShader.gradientLength, gradient.m_vColors.size());
|
||||
glUniform4fv(borderShader.gradient, gradient.m_vColorsOkLabA.size(), (float*)gradient.m_vColorsOkLabA.data());
|
||||
glUniform1i(borderShader.gradientLength, gradient.m_vColorsOkLabA.size() / 4);
|
||||
glUniform1f(borderShader.angle, (int)(gradient.m_fAngle / (M_PI / 180.0)) % 360 * (M_PI / 180.0));
|
||||
glUniform1f(borderShader.alpha, alpha);
|
||||
glUniform1i(borderShader.gradient2Length, 0);
|
||||
|
||||
const auto TOPLEFT = Vector2D(ROUNDEDBOX.x, ROUNDEDBOX.y);
|
||||
const auto FULLSIZE = Vector2D(ROUNDEDBOX.width, ROUNDEDBOX.height);
|
||||
|
@ -637,4 +625,21 @@ void CRenderer::popFb() {
|
|||
|
||||
void CRenderer::removeWidgetsFor(const CSessionLockSurface* surf) {
|
||||
widgets.erase(surf);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::startFadeIn() {
|
||||
Debug::log(LOG, "Starting fade in");
|
||||
*opacity = 1.f;
|
||||
|
||||
opacity->setCallbackOnEnd([this](auto) { opacity->setConfig(g_pConfigManager->m_AnimationTree.getConfig("fadeOut")); }, true);
|
||||
}
|
||||
|
||||
void CRenderer::startFadeOut(bool unlock, bool immediate) {
|
||||
if (immediate)
|
||||
opacity->setValueAndWarp(0.f);
|
||||
else
|
||||
*opacity = 0.f;
|
||||
|
||||
if (unlock)
|
||||
opacity->setCallbackOnEnd([](auto) { g_pHyprlock->releaseSessionLock(); }, true);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <optional>
|
||||
#include "Shader.hpp"
|
||||
#include "../core/LockSurface.hpp"
|
||||
#include "../helpers/AnimatedVariable.hpp"
|
||||
#include "../helpers/Color.hpp"
|
||||
#include "AsyncResourceGatherer.hpp"
|
||||
#include "../config/ConfigDataValues.hpp"
|
||||
|
@ -22,15 +23,15 @@ class CRenderer {
|
|||
};
|
||||
|
||||
struct SBlurParams {
|
||||
int size = 0, passes = 0;
|
||||
float noise = 0, contrast = 0, brightness = 0, vibrancy = 0, vibrancy_darkness = 0;
|
||||
std::optional<CColor> colorize;
|
||||
float boostA = 1.0;
|
||||
int size = 0, passes = 0;
|
||||
float noise = 0, contrast = 0, brightness = 0, vibrancy = 0, vibrancy_darkness = 0;
|
||||
std::optional<CHyprColor> colorize;
|
||||
float boostA = 1.0;
|
||||
};
|
||||
|
||||
SRenderFeedback renderLock(const CSessionLockSurface& surface);
|
||||
|
||||
void renderRect(const CBox& box, const CColor& col, int rounding = 0);
|
||||
void renderRect(const CBox& box, const CHyprColor& col, int rounding = 0);
|
||||
void renderBorder(const CBox& box, const CGradientValueData& gradient, int thickness, int rounding = 0, float alpha = 1.0);
|
||||
void renderTexture(const CBox& box, const CTexture& tex, float a = 1.0, int rounding = 0, std::optional<eTransform> tr = {});
|
||||
void renderTextureMix(const CBox& box, const CTexture& tex, const CTexture& tex2, float a = 1.0, float mixFactor = 0.0, int rounding = 0, std::optional<eTransform> tr = {});
|
||||
|
@ -44,6 +45,9 @@ class CRenderer {
|
|||
|
||||
void removeWidgetsFor(const CSessionLockSurface* surf);
|
||||
|
||||
void startFadeIn();
|
||||
void startFadeOut(bool unlock = false, bool immediate = true);
|
||||
|
||||
private:
|
||||
widgetMap_t widgets;
|
||||
|
||||
|
@ -61,6 +65,8 @@ class CRenderer {
|
|||
Mat3x3 projMatrix = Mat3x3::identity();
|
||||
Mat3x3 projection;
|
||||
|
||||
PHLANIMVAR<float> opacity;
|
||||
|
||||
std::vector<GLint> boundFBs;
|
||||
};
|
||||
|
||||
|
|
|
@ -41,9 +41,13 @@ class CShader {
|
|||
GLint applyTint = -1;
|
||||
GLint tint = -1;
|
||||
|
||||
GLint gradient = -1;
|
||||
GLint gradientLength = -1;
|
||||
GLint angle = -1;
|
||||
GLint gradient = -1;
|
||||
GLint gradientLength = -1;
|
||||
GLint gradient2 = -1;
|
||||
GLint gradient2Length = -1;
|
||||
GLint gradientLerp = -1;
|
||||
GLint angle = -1;
|
||||
GLint angle2 = -1;
|
||||
|
||||
GLint time = -1;
|
||||
GLint distort = -1;
|
||||
|
|
|
@ -427,12 +427,32 @@ uniform float radius;
|
|||
uniform float radiusOuter;
|
||||
uniform float thick;
|
||||
|
||||
// Gradients are in OkLabA!!!! {l, a, b, alpha}
|
||||
uniform vec4 gradient[10];
|
||||
uniform vec4 gradient2[10];
|
||||
uniform int gradientLength;
|
||||
uniform int gradient2Length;
|
||||
uniform float angle;
|
||||
uniform float angle2;
|
||||
uniform float gradientLerp;
|
||||
uniform float alpha;
|
||||
|
||||
vec4 getColorForCoord(vec2 normalizedCoord) {
|
||||
float linearToGamma(float x) {
|
||||
return x >= 0.0031308 ? 1.055 * pow(x, 0.416666666) - 0.055 : 12.92 * x;
|
||||
}
|
||||
|
||||
vec4 okLabAToSrgb(vec4 lab) {
|
||||
float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0);
|
||||
float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0);
|
||||
float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0);
|
||||
|
||||
return vec4(linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292),
|
||||
linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)),
|
||||
linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010),
|
||||
lab[3]);
|
||||
}
|
||||
|
||||
vec4 getOkColorForCoordArray1(vec2 normalizedCoord) {
|
||||
if (gradientLength < 2)
|
||||
return gradient[0];
|
||||
|
||||
|
@ -461,6 +481,46 @@ vec4 getColorForCoord(vec2 normalizedCoord) {
|
|||
return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress);
|
||||
}
|
||||
|
||||
vec4 getOkColorForCoordArray2(vec2 normalizedCoord) {
|
||||
if (gradient2Length < 2)
|
||||
return gradient2[0];
|
||||
|
||||
float finalAng = 0.0;
|
||||
|
||||
if (angle2 > 4.71 /* 270 deg */) {
|
||||
normalizedCoord[1] = 1.0 - normalizedCoord[1];
|
||||
finalAng = 6.28 - angle;
|
||||
} else if (angle2 > 3.14 /* 180 deg */) {
|
||||
normalizedCoord[0] = 1.0 - normalizedCoord[0];
|
||||
normalizedCoord[1] = 1.0 - normalizedCoord[1];
|
||||
finalAng = angle - 3.14;
|
||||
} else if (angle2 > 1.57 /* 90 deg */) {
|
||||
normalizedCoord[0] = 1.0 - normalizedCoord[0];
|
||||
finalAng = 3.14 - angle2;
|
||||
} else {
|
||||
finalAng = angle2;
|
||||
}
|
||||
|
||||
float sine = sin(finalAng);
|
||||
|
||||
float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1);
|
||||
int bottom = int(floor(progress));
|
||||
int top = bottom + 1;
|
||||
|
||||
return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress);
|
||||
}
|
||||
|
||||
vec4 getColorForCoord(vec2 normalizedCoord) {
|
||||
vec4 result1 = getOkColorForCoordArray1(normalizedCoord);
|
||||
|
||||
if (gradient2Length <= 0)
|
||||
return okLabAToSrgb(result1);
|
||||
|
||||
vec4 result2 = getOkColorForCoordArray2(normalizedCoord);
|
||||
|
||||
return okLabAToSrgb(mix(result1, result2, gradientLerp));
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
highp vec2 pixCoord = vec2(gl_FragCoord);
|
||||
|
|
|
@ -57,7 +57,7 @@ CBackground::CBackground(const Vector2D& viewport_, COutput* output_, const std:
|
|||
}
|
||||
}
|
||||
|
||||
void CBackground::renderRect(CColor color) {
|
||||
void CBackground::renderRect(CHyprColor color) {
|
||||
CBox monbox = {0, 0, viewport.x, viewport.y};
|
||||
g_pRenderer->renderRect(monbox, color, 0);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static void onAssetCallbackTimer(std::shared_ptr<CTimer> self, void* data) {
|
|||
bool CBackground::draw(const SRenderData& data) {
|
||||
|
||||
if (resourceID.empty()) {
|
||||
CColor col = color;
|
||||
CHyprColor col = color;
|
||||
col.a *= data.opacity;
|
||||
renderRect(col);
|
||||
return data.opacity < 1.0;
|
||||
|
@ -96,7 +96,7 @@ bool CBackground::draw(const SRenderData& data) {
|
|||
asset = g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID);
|
||||
|
||||
if (!asset) {
|
||||
CColor col = color;
|
||||
CHyprColor col = color;
|
||||
col.a *= data.opacity;
|
||||
renderRect(col);
|
||||
return true;
|
||||
|
|
|
@ -27,7 +27,7 @@ class CBackground : public IWidget {
|
|||
~CBackground();
|
||||
|
||||
virtual bool draw(const SRenderData& data);
|
||||
void renderRect(CColor color);
|
||||
void renderRect(CHyprColor color);
|
||||
|
||||
void onReloadTimerUpdate();
|
||||
void onCrossFadeTimerUpdate();
|
||||
|
@ -53,7 +53,7 @@ class CBackground : public IWidget {
|
|||
|
||||
float crossFadeTime = -1.0;
|
||||
|
||||
CColor color;
|
||||
CHyprColor color;
|
||||
SPreloadedAsset* asset = nullptr;
|
||||
COutput* output = nullptr;
|
||||
bool isScreenshot = false;
|
||||
|
|
|
@ -82,7 +82,7 @@ CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string,
|
|||
|
||||
std::string textAlign = std::any_cast<Hyprlang::STRING>(props.at("text_align"));
|
||||
std::string fontFamily = std::any_cast<Hyprlang::STRING>(props.at("font_family"));
|
||||
CColor labelColor = std::any_cast<Hyprlang::INT>(props.at("color"));
|
||||
CHyprColor labelColor = std::any_cast<Hyprlang::INT>(props.at("color"));
|
||||
int fontSize = std::any_cast<Hyprlang::INT>(props.at("font_size"));
|
||||
|
||||
label = formatString(labelPreFormat);
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
#include "../../core/hyprlock.hpp"
|
||||
#include "../../auth/Auth.hpp"
|
||||
#include "../../config/ConfigDataValues.hpp"
|
||||
#include "../../config/ConfigManager.hpp"
|
||||
#include "../../helpers/Log.hpp"
|
||||
#include "../../core/AnimationManager.hpp"
|
||||
#include "../../helpers/Color.hpp"
|
||||
#include <cmath>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <algorithm>
|
||||
#include <hyprlang.hpp>
|
||||
|
@ -14,7 +19,7 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
|||
viewport(viewport_), outputStringPort(output), shadow(this, props, viewport_) {
|
||||
try {
|
||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
|
||||
size = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport_);
|
||||
configSize = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport_);
|
||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||
outThick = std::any_cast<Hyprlang::INT>(props.at("outline_thickness"));
|
||||
|
@ -22,7 +27,6 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
|||
dots.spacing = std::any_cast<Hyprlang::FLOAT>(props.at("dots_spacing"));
|
||||
dots.center = std::any_cast<Hyprlang::INT>(props.at("dots_center"));
|
||||
dots.rounding = std::any_cast<Hyprlang::INT>(props.at("dots_rounding"));
|
||||
dots.fadeMs = std::any_cast<Hyprlang::INT>(props.at("dots_fade_time"));
|
||||
dots.textFormat = std::any_cast<Hyprlang::STRING>(props.at("dots_text_format"));
|
||||
fadeOnEmpty = std::any_cast<Hyprlang::INT>(props.at("fade_on_empty"));
|
||||
fadeTimeoutMs = std::any_cast<Hyprlang::INT>(props.at("fade_timeout"));
|
||||
|
@ -32,7 +36,6 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
|||
configFailText = std::any_cast<Hyprlang::STRING>(props.at("fail_text"));
|
||||
configFailTimeoutMs = std::any_cast<Hyprlang::INT>(props.at("fail_timeout"));
|
||||
fontFamily = std::any_cast<Hyprlang::STRING>(props.at("font_family"));
|
||||
colorConfig.transitionMs = std::any_cast<Hyprlang::INT>(props.at("fail_transition"));
|
||||
colorConfig.outer = CGradientValueData::fromAnyPv(props.at("outer_color"));
|
||||
colorConfig.inner = std::any_cast<Hyprlang::INT>(props.at("inner_color"));
|
||||
colorConfig.font = std::any_cast<Hyprlang::INT>(props.at("font_color"));
|
||||
|
@ -49,19 +52,14 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
|||
RASSERT(false, "Missing property for CPasswordInputField: {}", e.what()); //
|
||||
}
|
||||
|
||||
configPos = pos;
|
||||
configSize = size;
|
||||
configPos = pos;
|
||||
colorState.font = colorConfig.font;
|
||||
|
||||
pos = posFromHVAlign(viewport, size, pos, halign, valign);
|
||||
dots.size = std::clamp(dots.size, 0.2f, 0.8f);
|
||||
dots.spacing = std::clamp(dots.spacing, -1.f, 1.f);
|
||||
colorConfig.transitionMs = std::clamp(colorConfig.transitionMs, 0, 1000);
|
||||
colorConfig.caps = colorConfig.caps->m_bIsFallback ? colorConfig.fail : colorConfig.caps;
|
||||
pos = posFromHVAlign(viewport, configSize, pos, halign, valign);
|
||||
dots.size = std::clamp(dots.size, 0.2f, 0.8f);
|
||||
dots.spacing = std::clamp(dots.spacing, -1.f, 1.f);
|
||||
|
||||
colorState.inner = colorConfig.inner;
|
||||
colorState.outer = *colorConfig.outer;
|
||||
colorState.font = colorConfig.font;
|
||||
colorState.outerSource = colorConfig.outer;
|
||||
colorConfig.caps = colorConfig.caps->m_bIsFallback ? colorConfig.fail : colorConfig.caps;
|
||||
|
||||
if (!dots.textFormat.empty()) {
|
||||
dots.textResourceID = std::format("input:{}-{}", (uintptr_t)this, dots.textFormat);
|
||||
|
@ -70,12 +68,21 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
|||
request.asset = dots.textFormat;
|
||||
request.type = CAsyncResourceGatherer::eTargetType::TARGET_TEXT;
|
||||
request.props["font_family"] = fontFamily;
|
||||
request.props["color"] = colorState.font;
|
||||
request.props["font_size"] = (int)(std::nearbyint(size.y * dots.size * 0.5f) * 2.f);
|
||||
request.props["color"] = colorConfig.font;
|
||||
request.props["font_size"] = (int)(std::nearbyint(configSize.y * dots.size * 0.5f) * 2.f);
|
||||
|
||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||
}
|
||||
|
||||
g_pAnimationManager->createAnimation(0.f, fade.a, g_pConfigManager->m_AnimationTree.getConfig("inputFieldFade"));
|
||||
g_pAnimationManager->createAnimation(0.f, dots.currentAmount, g_pConfigManager->m_AnimationTree.getConfig("inputFieldDots"));
|
||||
g_pAnimationManager->createAnimation(configSize, size, g_pConfigManager->m_AnimationTree.getConfig("inputFieldWidth"));
|
||||
|
||||
g_pAnimationManager->createAnimation(colorConfig.inner, colorState.inner, g_pConfigManager->m_AnimationTree.getConfig("inputFieldColors"));
|
||||
g_pAnimationManager->createAnimation(*colorConfig.outer, colorState.outer, g_pConfigManager->m_AnimationTree.getConfig("inputFieldColors"));
|
||||
|
||||
srand(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
|
||||
// request the inital placeholder asset
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
@ -95,7 +102,7 @@ void CPasswordInputField::onFadeOutTimer() {
|
|||
|
||||
void CPasswordInputField::updateFade() {
|
||||
if (!fadeOnEmpty) {
|
||||
fade.a = 1.0;
|
||||
fade.a->setValueAndWarp(1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -109,73 +116,30 @@ void CPasswordInputField::updateFade() {
|
|||
fade.fadeOutTimer.reset();
|
||||
}
|
||||
|
||||
if (!INPUTUSED && fade.a != 0.0 && (!fade.animated || fade.appearing)) {
|
||||
if (!INPUTUSED && fade.a->goal() != 0.0) {
|
||||
if (fade.allowFadeOut || fadeTimeoutMs == 0) {
|
||||
fade.a = 1.0;
|
||||
fade.animated = true;
|
||||
fade.appearing = false;
|
||||
fade.start = std::chrono::system_clock::now();
|
||||
*fade.a = 0.0;
|
||||
fade.allowFadeOut = false;
|
||||
} else if (!fade.fadeOutTimer.get())
|
||||
fade.fadeOutTimer = g_pHyprlock->addTimer(std::chrono::milliseconds(fadeTimeoutMs), fadeOutCallback, this);
|
||||
}
|
||||
|
||||
if (INPUTUSED && fade.a != 1.0 && (!fade.animated || !fade.appearing)) {
|
||||
fade.a = 0.0;
|
||||
fade.animated = true;
|
||||
fade.appearing = true;
|
||||
fade.start = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
if (fade.animated) {
|
||||
if (fade.appearing)
|
||||
fade.a = std::clamp(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - fade.start).count() / 100000.0, 0.0, 1.0);
|
||||
else
|
||||
fade.a = std::clamp(1.0 - std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - fade.start).count() / 100000.0, 0.0, 1.0);
|
||||
|
||||
if ((fade.appearing && fade.a == 1.0) || (!fade.appearing && fade.a == 0.0))
|
||||
fade.animated = false;
|
||||
} else if (INPUTUSED && fade.a->goal() != 1.0)
|
||||
*fade.a = 1.0;
|
||||
|
||||
if (fade.a->isBeingAnimated())
|
||||
redrawShadow = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CPasswordInputField::updateDots() {
|
||||
if (passwordLength == dots.currentAmount)
|
||||
if (dots.currentAmount->goal() == passwordLength)
|
||||
return;
|
||||
|
||||
// Fully fading the dots to 0 currently does not look good
|
||||
if (passwordLength == 0 && dots.currentAmount > 2) {
|
||||
dots.currentAmount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::abs(passwordLength - dots.currentAmount) > 1) {
|
||||
dots.currentAmount = std::clamp(dots.currentAmount, passwordLength - 1.f, passwordLength + 1.f);
|
||||
dots.lastFrame = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
const auto DELTA = std::clamp((int)std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - dots.lastFrame).count(), 0, 20000);
|
||||
|
||||
const float TOADD = dots.fadeMs > 0 ? ((double)DELTA / 1000000.0) * (1000.0 / (double)dots.fadeMs) : 1;
|
||||
|
||||
if (passwordLength > dots.currentAmount) {
|
||||
dots.currentAmount += TOADD;
|
||||
if (dots.currentAmount > passwordLength)
|
||||
dots.currentAmount = passwordLength;
|
||||
} else if (passwordLength < dots.currentAmount) {
|
||||
dots.currentAmount -= TOADD;
|
||||
if (dots.currentAmount < passwordLength)
|
||||
dots.currentAmount = passwordLength;
|
||||
}
|
||||
|
||||
dots.lastFrame = std::chrono::system_clock::now();
|
||||
if (passwordLength == 0)
|
||||
dots.currentAmount->setValueAndWarp(passwordLength);
|
||||
else
|
||||
*dots.currentAmount = passwordLength;
|
||||
}
|
||||
|
||||
bool CPasswordInputField::draw(const SRenderData& data) {
|
||||
CBox inputFieldBox = {pos, size};
|
||||
CBox outerBox = {pos - Vector2D{outThick, outThick}, size + Vector2D{outThick * 2, outThick * 2}};
|
||||
|
||||
if (firstRender || redrawShadow) {
|
||||
firstRender = false;
|
||||
redrawShadow = false;
|
||||
|
@ -195,26 +159,29 @@ bool CPasswordInputField::draw(const SRenderData& data) {
|
|||
updateWidth();
|
||||
updateHiddenInputState();
|
||||
|
||||
SRenderData shadowData = data;
|
||||
shadowData.opacity *= fade.a;
|
||||
CBox inputFieldBox = {pos, size->value()};
|
||||
CBox outerBox = {pos - Vector2D{outThick, outThick}, size->value() + Vector2D{outThick * 2, outThick * 2}};
|
||||
|
||||
if (!dynamicWidth.animated || size.x > dynamicWidth.source)
|
||||
SRenderData shadowData = data;
|
||||
shadowData.opacity *= fade.a->value();
|
||||
|
||||
if (!size->isBeingAnimated())
|
||||
shadow.draw(shadowData);
|
||||
|
||||
CGradientValueData outerGrad = colorState.outer;
|
||||
for (auto& c : outerGrad.m_vColors)
|
||||
c.a *= fade.a * data.opacity;
|
||||
//CGradientValueData outerGrad = colorState.outer->value();
|
||||
//for (auto& c : outerGrad.m_vColors)
|
||||
// c.a *= fade.a->value() * data.opacity;
|
||||
|
||||
CColor innerCol = colorState.inner;
|
||||
innerCol.a *= fade.a * data.opacity;
|
||||
CColor fontCol = colorState.font;
|
||||
fontCol.a *= fade.a * data.opacity;
|
||||
CHyprColor innerCol = colorState.inner->value();
|
||||
innerCol.a *= fade.a->value() * data.opacity;
|
||||
CHyprColor fontCol = colorState.font;
|
||||
fontCol.a *= fade.a->value() * data.opacity;
|
||||
|
||||
if (outThick > 0) {
|
||||
const int BORDERROUND = roundingForBorderBox(outerBox, rounding, outThick);
|
||||
g_pRenderer->renderBorder(outerBox, outerGrad, outThick, BORDERROUND, fade.a * data.opacity);
|
||||
const auto OUTERROUND = roundingForBorderBox(outerBox, rounding, outThick);
|
||||
g_pRenderer->renderBorder(outerBox, colorState.outer->value(), outThick, OUTERROUND, fade.a->value() * data.opacity);
|
||||
|
||||
if (passwordLength != 0 && hiddenInputState.enabled && !fade.animated && data.opacity == 1.0) {
|
||||
if (passwordLength != 0 && !checkWaiting && hiddenInputState.enabled) {
|
||||
CBox outerBoxScaled = outerBox;
|
||||
Vector2D p = outerBox.pos();
|
||||
outerBoxScaled.translate(-p).scale(0.5).translate(p);
|
||||
|
@ -224,7 +191,7 @@ bool CPasswordInputField::draw(const SRenderData& data) {
|
|||
outerBoxScaled.x += outerBoxScaled.w;
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(outerBoxScaled.x, outerBoxScaled.y, outerBoxScaled.w, outerBoxScaled.h);
|
||||
g_pRenderer->renderBorder(outerBox, hiddenInputState.lastColor, outThick, BORDERROUND, fade.a * data.opacity);
|
||||
g_pRenderer->renderBorder(outerBox, hiddenInputState.lastColor, outThick, OUTERROUND, fade.a->value() * data.opacity);
|
||||
glScissor(0, 0, viewport.x, viewport.y);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
@ -233,7 +200,7 @@ bool CPasswordInputField::draw(const SRenderData& data) {
|
|||
const int ROUND = roundingForBox(inputFieldBox, rounding);
|
||||
g_pRenderer->renderRect(inputFieldBox, innerCol, ROUND);
|
||||
|
||||
if (!hiddenInputState.enabled && !g_pHyprlock->m_bFadeStarted) {
|
||||
if (!hiddenInputState.enabled) {
|
||||
const int RECTPASSSIZE = std::nearbyint(inputFieldBox.h * dots.size * 0.5f) * 2.f;
|
||||
Vector2D passSize{RECTPASSSIZE, RECTPASSSIZE};
|
||||
int passSpacing = std::floor(passSize.x * dots.spacing);
|
||||
|
@ -250,49 +217,53 @@ bool CPasswordInputField::draw(const SRenderData& data) {
|
|||
}
|
||||
}
|
||||
|
||||
const int DOT_PAD = (inputFieldBox.h - passSize.y) / 2;
|
||||
const int DOT_AREA_WIDTH = inputFieldBox.w - DOT_PAD * 2; // avail width for dots
|
||||
const int MAX_DOTS = std::round(DOT_AREA_WIDTH * 1.0 / (passSize.x + passSpacing)); // max amount of dots that can fit in the area
|
||||
const int DOT_FLOORED = std::floor(dots.currentAmount);
|
||||
const float DOT_ALPHA = fontCol.a;
|
||||
const auto CURRDOTS = dots.currentAmount->value();
|
||||
const int DOTPAD = (inputFieldBox.h - passSize.y) / 2;
|
||||
const int DOTAREAWIDTH = inputFieldBox.w - DOTPAD * 2;
|
||||
const int MAXDOTS = std::round(DOTAREAWIDTH * 1.0 / (passSize.x + passSpacing));
|
||||
const int DOTFLOORED = std::floor(CURRDOTS);
|
||||
const auto DOTALPHA = fontCol.a;
|
||||
|
||||
// Calculate the total width required for all dots including spaces between them
|
||||
const int TOTAL_DOTS_WIDTH = (passSize.x + passSpacing) * dots.currentAmount - passSpacing;
|
||||
const int CURRWIDTH = (passSize.x + passSpacing) * CURRDOTS - passSpacing;
|
||||
|
||||
// Calculate starting x-position to ensure dots stay centered within the input field
|
||||
int xstart = dots.center ? (DOT_AREA_WIDTH - TOTAL_DOTS_WIDTH) / 2 + DOT_PAD : DOT_PAD;
|
||||
int xstart = dots.center ? (DOTAREAWIDTH - CURRWIDTH) / 2 + DOTPAD : DOTPAD;
|
||||
|
||||
if (dots.currentAmount > MAX_DOTS)
|
||||
xstart = (inputFieldBox.w + MAX_DOTS * (passSize.x + passSpacing) - passSpacing - 2 * TOTAL_DOTS_WIDTH) / 2;
|
||||
if (CURRDOTS > MAXDOTS)
|
||||
xstart = (inputFieldBox.w + MAXDOTS * (passSize.x + passSpacing) - passSpacing - 2 * CURRWIDTH) / 2;
|
||||
|
||||
if (dots.rounding == -1)
|
||||
dots.rounding = passSize.x / 2.0;
|
||||
else if (dots.rounding == -2)
|
||||
dots.rounding = rounding == -1 ? passSize.x / 2.0 : rounding * dots.size;
|
||||
|
||||
for (int i = 0; i < dots.currentAmount; ++i) {
|
||||
if (i < DOT_FLOORED - MAX_DOTS)
|
||||
for (int i = 0; i < CURRDOTS; ++i) {
|
||||
if (i < DOTFLOORED - MAXDOTS)
|
||||
continue;
|
||||
|
||||
if (dots.currentAmount != DOT_FLOORED) {
|
||||
if (i == DOT_FLOORED)
|
||||
fontCol.a *= (dots.currentAmount - DOT_FLOORED) * data.opacity;
|
||||
else if (i == DOT_FLOORED - MAX_DOTS)
|
||||
fontCol.a *= (1 - dots.currentAmount + DOT_FLOORED) * data.opacity;
|
||||
if (CURRDOTS != DOTFLOORED) {
|
||||
if (i == DOTFLOORED)
|
||||
fontCol.a *= (CURRDOTS - DOTFLOORED) * data.opacity;
|
||||
else if (i == DOTFLOORED - MAXDOTS)
|
||||
fontCol.a *= (1 - CURRDOTS + DOTFLOORED) * data.opacity;
|
||||
}
|
||||
|
||||
Vector2D dotPosition =
|
||||
inputFieldBox.pos() + Vector2D{xstart + (int)inputFieldBox.w % 2 / 2.f + i * (passSize.x + passSpacing), inputFieldBox.h / 2.f - passSize.y / 2.f};
|
||||
inputFieldBox.pos() + Vector2D{xstart + (int)inputFieldBox.w % 2 / 2.0 + i * (passSize.x + passSpacing), inputFieldBox.h / 2.0 - passSize.y / 2.0};
|
||||
CBox box{dotPosition, passSize};
|
||||
if (!dots.textFormat.empty()) {
|
||||
if (!dots.textAsset)
|
||||
if (!dots.textAsset) {
|
||||
forceReload = true;
|
||||
fontCol.a = DOTALPHA;
|
||||
break;
|
||||
}
|
||||
|
||||
g_pRenderer->renderTexture(box, dots.textAsset->texture, fontCol.a, dots.rounding);
|
||||
} else {
|
||||
g_pRenderer->renderRect(box, fontCol, dots.rounding);
|
||||
}
|
||||
fontCol.a = DOT_ALPHA;
|
||||
fontCol.a = DOTALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,16 +275,16 @@ bool CPasswordInputField::draw(const SRenderData& data) {
|
|||
|
||||
currAsset = placeholder.asset;
|
||||
|
||||
if (currAsset && currAsset->texture.m_vSize.x + size.y <= size.x) {
|
||||
if (currAsset && currAsset->texture.m_vSize.x + size->value().y <= size->value().x) {
|
||||
Vector2D pos = outerBox.pos() + outerBox.size() / 2.f;
|
||||
pos = pos - currAsset->texture.m_vSize / 2.f;
|
||||
CBox textbox{pos, currAsset->texture.m_vSize};
|
||||
g_pRenderer->renderTexture(textbox, currAsset->texture, data.opacity * fade.a, 0);
|
||||
g_pRenderer->renderTexture(textbox, currAsset->texture, data.opacity * fade.a->value(), 0);
|
||||
} else
|
||||
forceReload = true;
|
||||
}
|
||||
|
||||
return dots.currentAmount != passwordLength || fade.animated || colorState.animated || redrawShadow || data.opacity < 1.0 || dynamicWidth.animated || forceReload;
|
||||
return redrawShadow || forceReload;
|
||||
}
|
||||
|
||||
static void failTimeoutCallback(std::shared_ptr<CTimer> self, void* data) {
|
||||
|
@ -368,42 +339,26 @@ void CPasswordInputField::updatePlaceholder() {
|
|||
request.type = CAsyncResourceGatherer::eTargetType::TARGET_TEXT;
|
||||
request.props["font_family"] = fontFamily;
|
||||
request.props["color"] = colorState.font;
|
||||
request.props["font_size"] = (int)size.y / 4;
|
||||
request.props["font_size"] = (int)size->value().y / 4;
|
||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||
}
|
||||
|
||||
void CPasswordInputField::updateWidth() {
|
||||
const auto NOW = std::chrono::system_clock::now();
|
||||
double targetSizeX = configSize.x;
|
||||
double targetSizeX = configSize.x;
|
||||
|
||||
if (placeholder.asset)
|
||||
targetSizeX = placeholder.asset->texture.m_vSize.x + size.y;
|
||||
targetSizeX = placeholder.asset->texture.m_vSize.x + size->goal().y;
|
||||
|
||||
if (targetSizeX < configSize.x)
|
||||
targetSizeX = configSize.x;
|
||||
|
||||
if (size.x != targetSizeX) {
|
||||
if (!dynamicWidth.animated) {
|
||||
dynamicWidth.source = size.x;
|
||||
dynamicWidth.start = NOW;
|
||||
dynamicWidth.animated = true;
|
||||
}
|
||||
if (size->goal().x != targetSizeX)
|
||||
*size = Vector2D{targetSizeX, configSize.y};
|
||||
|
||||
const auto TIMEDELTA = std::clamp((int)std::chrono::duration_cast<std::chrono::microseconds>(NOW - dynamicWidth.start).count(), 1000, 100000);
|
||||
const auto INCR = std::clamp(std::abs(targetSizeX - dynamicWidth.source) * TIMEDELTA / 1000000.0, 1.0, 1000.0);
|
||||
if (size.x > targetSizeX)
|
||||
size.x -= INCR;
|
||||
else
|
||||
size.x += INCR;
|
||||
if (size->isBeingAnimated())
|
||||
redrawShadow = true;
|
||||
|
||||
if ((dynamicWidth.source < targetSizeX && size.x > targetSizeX) || (dynamicWidth.source > targetSizeX && size.x < targetSizeX)) {
|
||||
size.x = targetSizeX;
|
||||
redrawShadow = true;
|
||||
dynamicWidth.animated = false;
|
||||
}
|
||||
}
|
||||
|
||||
pos = posFromHVAlign(viewport, size, configPos, halign, valign);
|
||||
pos = posFromHVAlign(viewport, size->value(), configPos, halign, valign);
|
||||
}
|
||||
|
||||
void CPasswordInputField::updateHiddenInputState() {
|
||||
|
@ -413,78 +368,29 @@ void CPasswordInputField::updateHiddenInputState() {
|
|||
// randomize new thang
|
||||
hiddenInputState.lastPasswordLength = passwordLength;
|
||||
|
||||
srand(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
float r1 = (rand() % 100) / 255.0;
|
||||
float r2 = (rand() % 100) / 255.0;
|
||||
int r3 = rand() % 3;
|
||||
int r4 = rand() % 2;
|
||||
int r5 = rand() % 2;
|
||||
const auto BASEOK = colorConfig.outer->m_vColors.front().asOkLab();
|
||||
|
||||
((float*)&hiddenInputState.lastColor.r)[r3] = r1 + 155 / 255.0;
|
||||
((float*)&hiddenInputState.lastColor.r)[(r3 + r4) % 3] = r2 + 155 / 255.0;
|
||||
// convert to polar coordinates
|
||||
const auto OKICHCHROMA = std::sqrt(std::pow(BASEOK.a, 2) + std::pow(BASEOK.b, 2));
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (i != r3 && i != ((r3 + r4) % 3)) {
|
||||
((float*)&hiddenInputState.lastColor.r)[i] = 1.0 - ((float*)&hiddenInputState.lastColor.r)[r5 ? r3 : ((r3 + r4) % 3)];
|
||||
}
|
||||
}
|
||||
// now randomly rotate the hue
|
||||
const double OKICHHUE = (rand() % 10000000 / 10000000.0) * M_PI * 4;
|
||||
|
||||
hiddenInputState.lastColor.a = 1.0;
|
||||
// convert back to OkLab
|
||||
const Hyprgraphics::CColor newColor = Hyprgraphics::CColor::SOkLab{
|
||||
.l = BASEOK.l,
|
||||
.a = OKICHCHROMA * std::cos(OKICHHUE),
|
||||
.b = OKICHCHROMA * std::sin(OKICHHUE),
|
||||
};
|
||||
|
||||
hiddenInputState.lastColor = {newColor, 1.0};
|
||||
hiddenInputState.lastQuadrant = (hiddenInputState.lastQuadrant + rand() % 3 + 1) % 4;
|
||||
}
|
||||
|
||||
static void changeChannel(const float& source, const float& target, float& subject, const double& multi, bool& animated) {
|
||||
|
||||
const float DELTA = target - source;
|
||||
|
||||
if (subject != target) {
|
||||
subject += DELTA * multi;
|
||||
animated = true;
|
||||
|
||||
if ((source < target && subject > target) || (source > target && subject < target))
|
||||
subject = target;
|
||||
}
|
||||
}
|
||||
|
||||
static void changeColor(const CColor& source, const CColor& target, CColor& subject, const double& multi, bool& animated) {
|
||||
|
||||
changeChannel(source.r, target.r, subject.r, multi, animated);
|
||||
changeChannel(source.g, target.g, subject.g, multi, animated);
|
||||
changeChannel(source.b, target.b, subject.b, multi, animated);
|
||||
changeChannel(source.a, target.a, subject.a, multi, animated);
|
||||
}
|
||||
|
||||
static void changeGrad(CGradientValueData* psource, CGradientValueData* ptarget, CGradientValueData& subject, const double& multi, bool& animated) {
|
||||
if (!psource || !ptarget)
|
||||
return;
|
||||
|
||||
subject.m_vColors.resize(ptarget->m_vColors.size(), subject.m_vColors.back());
|
||||
|
||||
for (size_t i = 0; i < subject.m_vColors.size(); ++i) {
|
||||
const CColor& sourceCol = (i < psource->m_vColors.size()) ? psource->m_vColors[i] : psource->m_vColors.back();
|
||||
const CColor& targetCol = (i < ptarget->m_vColors.size()) ? ptarget->m_vColors[i] : ptarget->m_vColors.back();
|
||||
changeColor(sourceCol, targetCol, subject.m_vColors[i], multi, animated);
|
||||
}
|
||||
|
||||
if (psource->m_fAngle != ptarget->m_fAngle) {
|
||||
const float DELTA = ptarget->m_fAngle - psource->m_fAngle;
|
||||
subject.m_fAngle += DELTA * multi;
|
||||
animated = true;
|
||||
|
||||
if ((psource->m_fAngle < ptarget->m_fAngle && subject.m_fAngle > ptarget->m_fAngle) || (psource->m_fAngle > ptarget->m_fAngle && subject.m_fAngle < ptarget->m_fAngle))
|
||||
subject.m_fAngle = ptarget->m_fAngle;
|
||||
}
|
||||
}
|
||||
|
||||
void CPasswordInputField::updateColors() {
|
||||
const bool BORDERLESS = outThick == 0;
|
||||
const bool NUMLOCK = (colorConfig.invertNum) ? !g_pHyprlock->m_bNumLock : g_pHyprlock->m_bNumLock;
|
||||
const auto MULTI = colorConfig.transitionMs == 0 ?
|
||||
1.0 :
|
||||
std::clamp(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - colorState.lastFrame).count() / (double)colorConfig.transitionMs,
|
||||
0.0016, 0.5);
|
||||
const bool BORDERLESS = outThick == 0;
|
||||
const bool NUMLOCK = (colorConfig.invertNum) ? !g_pHyprlock->m_bNumLock : g_pHyprlock->m_bNumLock;
|
||||
|
||||
//
|
||||
CGradientValueData* targetGrad = nullptr;
|
||||
|
||||
if (g_pHyprlock->m_bCapsLock && NUMLOCK && !colorConfig.both->m_bIsFallback)
|
||||
|
@ -500,37 +406,26 @@ void CPasswordInputField::updateColors() {
|
|||
targetGrad = colorConfig.fail;
|
||||
|
||||
CGradientValueData* outerTarget = colorConfig.outer;
|
||||
CColor innerTarget = colorConfig.inner;
|
||||
CColor fontTarget = (displayFail) ? colorConfig.fail->m_vColors.front() : colorConfig.font;
|
||||
CHyprColor innerTarget = colorConfig.inner;
|
||||
CHyprColor fontTarget = (displayFail) ? colorConfig.fail->m_vColors.front() : colorConfig.font;
|
||||
|
||||
if (checkWaiting || displayFail || g_pHyprlock->m_bCapsLock || NUMLOCK) {
|
||||
if (BORDERLESS && colorConfig.swapFont) {
|
||||
fontTarget = colorConfig.fail->m_vColors.front();
|
||||
} else if (BORDERLESS && !colorConfig.swapFont) {
|
||||
innerTarget = colorConfig.fail->m_vColors.front();
|
||||
// When changing the inner color the font cannot be fail_color
|
||||
// When changing the inner color, the font cannot be fail_color
|
||||
fontTarget = colorConfig.font;
|
||||
} else {
|
||||
} else if (targetGrad) {
|
||||
outerTarget = targetGrad;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetGrad != colorState.currentTarget) {
|
||||
colorState.outerSource = &colorState.outer;
|
||||
colorState.innerSource = colorState.inner;
|
||||
if (!BORDERLESS && *outerTarget != colorState.outer->goal())
|
||||
*colorState.outer = *outerTarget;
|
||||
|
||||
colorState.currentTarget = targetGrad;
|
||||
}
|
||||
if (innerTarget != colorState.inner->goal())
|
||||
*colorState.inner = innerTarget;
|
||||
|
||||
colorState.animated = false;
|
||||
|
||||
if (!BORDERLESS)
|
||||
changeGrad(colorState.outerSource, outerTarget, colorState.outer, MULTI, colorState.animated);
|
||||
changeColor(colorState.innerSource, innerTarget, colorState.inner, MULTI, colorState.animated);
|
||||
|
||||
// Font color is only chaned, when `swap_font_color` is set to true and no border is present.
|
||||
// It is not animated, because that does not look good and we would need to rerender the text for each frame.
|
||||
colorState.font = fontTarget;
|
||||
|
||||
colorState.lastFrame = std::chrono::system_clock::now();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include "../../helpers/Math.hpp"
|
||||
#include "../../core/Timer.hpp"
|
||||
#include "Shadowable.hpp"
|
||||
#include "src/config/ConfigDataValues.hpp"
|
||||
#include "../../config/ConfigDataValues.hpp"
|
||||
#include "../../helpers/AnimatedVariable.hpp"
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <any>
|
||||
|
@ -21,58 +22,48 @@ class CPasswordInputField : public IWidget {
|
|||
void onFadeOutTimer();
|
||||
|
||||
private:
|
||||
void updateDots();
|
||||
void updateFade();
|
||||
void updatePlaceholder();
|
||||
void updateWidth();
|
||||
void updateHiddenInputState();
|
||||
void updateInputState();
|
||||
void updateColors();
|
||||
void updateDots();
|
||||
void updateFade();
|
||||
void updatePlaceholder();
|
||||
void updateWidth();
|
||||
void updateHiddenInputState();
|
||||
void updateInputState();
|
||||
void updateColors();
|
||||
|
||||
bool firstRender = true;
|
||||
bool redrawShadow = false;
|
||||
bool checkWaiting = false;
|
||||
bool displayFail = false;
|
||||
bool firstRender = true;
|
||||
bool redrawShadow = false;
|
||||
bool checkWaiting = false;
|
||||
bool displayFail = false;
|
||||
|
||||
size_t passwordLength = 0;
|
||||
size_t passwordLength = 0;
|
||||
|
||||
Vector2D size;
|
||||
Vector2D pos;
|
||||
Vector2D viewport;
|
||||
Vector2D configPos;
|
||||
Vector2D configSize;
|
||||
PHLANIMVAR<Vector2D> size;
|
||||
Vector2D pos;
|
||||
Vector2D viewport;
|
||||
Vector2D configPos;
|
||||
Vector2D configSize;
|
||||
|
||||
std::string halign, valign, configFailText, outputStringPort, configPlaceholderText, fontFamily;
|
||||
uint64_t configFailTimeoutMs = 2000;
|
||||
std::string halign, valign, configFailText, outputStringPort, configPlaceholderText, fontFamily;
|
||||
uint64_t configFailTimeoutMs = 2000;
|
||||
|
||||
int outThick, rounding;
|
||||
int outThick, rounding;
|
||||
|
||||
struct {
|
||||
std::chrono::system_clock::time_point start;
|
||||
bool animated = false;
|
||||
double source = 0;
|
||||
} dynamicWidth;
|
||||
|
||||
struct {
|
||||
float currentAmount = 0;
|
||||
int fadeMs = 0;
|
||||
std::chrono::system_clock::time_point lastFrame;
|
||||
bool center = false;
|
||||
float size = 0;
|
||||
float spacing = 0;
|
||||
int rounding = 0;
|
||||
std::string textFormat = "";
|
||||
SPreloadedAsset* textAsset = nullptr;
|
||||
std::string textResourceID;
|
||||
PHLANIMVAR<float> currentAmount;
|
||||
bool center = false;
|
||||
float size = 0;
|
||||
float spacing = 0;
|
||||
int rounding = 0;
|
||||
std::string textFormat = "";
|
||||
std::string textResourceID;
|
||||
SPreloadedAsset* textAsset = nullptr;
|
||||
} dots;
|
||||
|
||||
struct {
|
||||
std::chrono::system_clock::time_point start;
|
||||
float a = 0;
|
||||
bool appearing = true;
|
||||
bool animated = false;
|
||||
std::shared_ptr<CTimer> fadeOutTimer = nullptr;
|
||||
bool allowFadeOut = false;
|
||||
PHLANIMVAR<float> a;
|
||||
bool appearing = true;
|
||||
std::shared_ptr<CTimer> fadeOutTimer = nullptr;
|
||||
bool allowFadeOut = false;
|
||||
} fade;
|
||||
|
||||
struct {
|
||||
|
@ -90,16 +81,16 @@ class CPasswordInputField : public IWidget {
|
|||
} placeholder;
|
||||
|
||||
struct {
|
||||
CColor lastColor;
|
||||
int lastQuadrant = 0;
|
||||
int lastPasswordLength = 0;
|
||||
bool enabled = false;
|
||||
CHyprColor lastColor;
|
||||
int lastQuadrant = 0;
|
||||
int lastPasswordLength = 0;
|
||||
bool enabled = false;
|
||||
} hiddenInputState;
|
||||
|
||||
struct {
|
||||
CGradientValueData* outer = nullptr;
|
||||
CColor inner;
|
||||
CColor font;
|
||||
CHyprColor inner;
|
||||
CHyprColor font;
|
||||
CGradientValueData* fail = nullptr;
|
||||
CGradientValueData* check = nullptr;
|
||||
CGradientValueData* caps = nullptr;
|
||||
|
@ -112,19 +103,11 @@ class CPasswordInputField : public IWidget {
|
|||
} colorConfig;
|
||||
|
||||
struct {
|
||||
CGradientValueData outer;
|
||||
CColor inner;
|
||||
CColor font;
|
||||
|
||||
CGradientValueData* outerSource = nullptr;
|
||||
CColor innerSource;
|
||||
|
||||
CGradientValueData* currentTarget = nullptr;
|
||||
|
||||
bool animated = false;
|
||||
|
||||
//
|
||||
std::chrono::system_clock::time_point lastFrame;
|
||||
PHLANIMVAR<CGradientValueData> outer;
|
||||
PHLANIMVAR<CHyprColor> inner;
|
||||
// Font color is only chaned, when `swap_font_color` is set to true and no border is present.
|
||||
// It is not animated, because that does not look good and we would need to rerender the text for each frame.
|
||||
CHyprColor font;
|
||||
} colorState;
|
||||
|
||||
bool fadeOnEmpty;
|
||||
|
|
|
@ -18,12 +18,12 @@ class CShadowable {
|
|||
virtual bool draw(const IWidget::SRenderData& data);
|
||||
|
||||
private:
|
||||
IWidget* widget = nullptr;
|
||||
int size = 10;
|
||||
int passes = 4;
|
||||
float boostA = 1.0;
|
||||
CColor color{0, 0, 0, 1.0};
|
||||
Vector2D viewport;
|
||||
IWidget* widget = nullptr;
|
||||
int size = 10;
|
||||
int passes = 4;
|
||||
float boostA = 1.0;
|
||||
CHyprColor color{0, 0, 0, 1.0};
|
||||
Vector2D viewport;
|
||||
|
||||
// to avoid recursive shadows
|
||||
bool ignoreDraw = false;
|
||||
|
|
|
@ -21,7 +21,7 @@ class CShape : public IWidget {
|
|||
int rounding;
|
||||
double border;
|
||||
double angle;
|
||||
CColor color;
|
||||
CHyprColor color;
|
||||
CGradientValueData borderGrad;
|
||||
Vector2D size;
|
||||
Vector2D pos;
|
||||
|
|
Loading…
Reference in a new issue