feat: new shake to find behaviour

This commit is contained in:
Virt 2024-08-25 20:00:16 +02:00
commit 553dc93cc0
6 changed files with 118 additions and 37 deletions

View file

@ -1,13 +1,49 @@
#include "../globals.hpp"
#include "../config/config.hpp"
#include "src/config/ConfigManager.hpp"
#include "src/helpers/AnimatedVariable.hpp"
#include "src/managers/AnimationManager.hpp"
#include "src/managers/EventManager.hpp"
#include "Shake.hpp"
#include <algorithm>
#include <chrono>
#include <hyprland/src/Compositor.hpp>
#include <hyprland/src/debug/Log.hpp>
CShake::CShake() {
// the timing and the bezier are quite crucial, as things will break down if they are just changed slighly
// this is not ideal and should be fixed some time in the future, then it may be made configurable (if it has a substatntial enough effect on behaviour)
int time = 400;
// add custom bezier (and readd it after config reload)
static auto bezier = "dynamic-cursors-magnification";
g_pAnimationManager->addBezierWithName(bezier, {0.22, 1.0}, {0.36, 1.0});
static const auto PCALLBACK = HyprlandAPI::registerCallbackDynamic( PHANDLE, "configReloaded", [&](void* self, SCallbackInfo&, std::any data) {
g_pAnimationManager->addBezierWithName(bezier, {0.22, 1.0}, {0.36, 1.0});
});
// wtf is this struct?
static SAnimationPropertyConfig properties = {false, bezier, "", time / 100.F, 1, nullptr, nullptr };
properties.pValues = &properties;
zoom.create(&properties, AVARDAMAGE_NONE);
zoom.registerVar();
zoom.setValueAndWarp(1);
}
CShake::~CShake() {
zoom.unregister();
}
double CShake::update(Vector2D pos) {
static auto* const* PTHRESHOLD = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_THRESHOLD);
static auto* const* PFACTOR = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_FACTOR);
static auto* const* PBASE = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_BASE);
static auto* const* PSPEED = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_SPEED);
static auto* const* PINFLUENCE = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_INFLUENCE);
static auto* const* PLIMIT = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_LIMIT);
static auto* const* PTIMEOUT = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_TIMEOUT);
static auto* const* PIPC = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_IPC);
int max = g_pHyprRenderer->m_pMostHzMonitor->refreshRate; // 1s worth of history
@ -36,19 +72,35 @@ double CShake::update(Vector2D pos) {
}
double diagonal = Vector2D{left, top}.distance(Vector2D(right, bottom));
// discard when the diagonal is small, return so we don't have issues with inaccuracies
if (diagonal < 100) return 1.0;
// if diagonal sufficiently large and over threshold
double amount = (trail / diagonal) - **PTHRESHOLD;
if (diagonal > 100 && amount > 0) {
float delta = 1.F / g_pHyprRenderer->m_pMostHzMonitor->refreshRate;
double zoom = ((trail / diagonal) - **PTHRESHOLD);
float next = this->zoom.goal();
if (!started) next = **PBASE; // start on base zoom
next += delta * (**PSPEED + (amount * amount) * **PINFLUENCE); // increase when moving
if (**PLIMIT > 1) next = std::min(**PLIMIT, next); // limit overall zoom
if (next != this->zoom.goal()) this->zoom = next;
this->end = steady_clock::now() + milliseconds(**PTIMEOUT);
started = true;
} else {
if (started && end < std::chrono::steady_clock::now()) {
this->zoom = 1;
started = false;
}
}
if (**PIPC) {
if (zoom > 1) {
if (started || this->zoom.value() > 1) {
if (!ipc) {
g_pEventManager->postEvent(SHyprIPCEvent { IPC_SHAKE_START });
ipc = true;
}
g_pEventManager->postEvent(SHyprIPCEvent { IPC_SHAKE_UPDATE, std::format("{},{},{},{}", (int) pos.x, (int) pos.y, trail, diagonal) });
g_pEventManager->postEvent(SHyprIPCEvent { IPC_SHAKE_UPDATE, std::format("{},{},{},{},{}", (int) pos.x, (int) pos.y, trail, diagonal, this->zoom.value()) });
} else {
if (ipc) {
g_pEventManager->postEvent(SHyprIPCEvent { IPC_SHAKE_END });
@ -57,14 +109,5 @@ double CShake::update(Vector2D pos) {
}
}
// fix jitter by allowing the diagonal to only grow, until we are below the threshold again
if (zoom > 0) { // larger than 0 because of factor
if (diagonal > this->diagonal)
this->diagonal = diagonal;
zoom = ((trail / this->diagonal) - **PTHRESHOLD);
} else this->diagonal = 0;
// we want ipc to work with factor = 0, so we use it here
return std::max(1.0, zoom * **PFACTOR);
return this->zoom.value();
}

View file

@ -1,3 +1,4 @@
#include "src/helpers/AnimatedVariable.hpp"
#include <hyprutils/math/Vector2D.hpp>
#include <vector>
@ -6,9 +7,13 @@
#define IPC_SHAKE_END "shakeend"
using namespace Hyprutils::Math;
using namespace std::chrono;
class CShake {
public:
CShake();
~CShake();
/* calculates the new zoom factor for the current pos */
double update(Vector2D pos);
@ -16,8 +21,9 @@ class CShake {
/* tracks whether the current shake has already been announced in the ipc */
bool ipc = false;
/* stores last measured diagonal */
float diagonal = 0;
bool started = false;
CAnimatedVariable<float> zoom;
steady_clock::time_point end;
/* ringbuffer for last samples */
std::vector<Vector2D> samples;