mirror of
https://github.com/virtcode/hypr-dynamic-cursors
synced 2025-09-19 16:13:21 +02:00
feat: new shake to find behaviour
This commit is contained in:
parent
eabab33f00
commit
553dc93cc0
6 changed files with 118 additions and 37 deletions
|
@ -12,10 +12,14 @@
|
|||
|
||||
#define CONFIG_SHAKE "shake:enabled"
|
||||
#define CONFIG_SHAKE_NEAREST "shake:nearest"
|
||||
#define CONFIG_SHAKE_THRESHOLD "shake:threshold"
|
||||
#define CONFIG_SHAKE_FACTOR "shake:factor"
|
||||
#define CONFIG_SHAKE_EFFECTS "shake:effects"
|
||||
#define CONFIG_SHAKE_IPC "shake:ipc"
|
||||
#define CONFIG_SHAKE_THRESHOLD "shake:threshold"
|
||||
#define CONFIG_SHAKE_SPEED "shake:speed"
|
||||
#define CONFIG_SHAKE_INFLUENCE "shake:influence"
|
||||
#define CONFIG_SHAKE_BASE "shake:base"
|
||||
#define CONFIG_SHAKE_LIMIT "shake:limit"
|
||||
#define CONFIG_SHAKE_TIMEOUT "shake:timeout"
|
||||
|
||||
#define CONFIG_ROTATE_LENGTH "rotate:length"
|
||||
#define CONFIG_ROTATE_OFFSET "rotate:offset"
|
||||
|
|
|
@ -80,9 +80,6 @@ void CDynamicCursors::renderSoftware(CPointerManager* pointers, SP<CMonitor> pMo
|
|||
box.x = box.x + pointers->currentCursorImage.hotspot.x - pointers->currentCursorImage.hotspot.x * zoom;
|
||||
box.y = box.y + pointers->currentCursorImage.hotspot.y - pointers->currentCursorImage.hotspot.y * zoom;
|
||||
|
||||
if (box.intersection(CBox{{}, {pMonitor->vecSize}}).empty())
|
||||
return;
|
||||
|
||||
auto texture = pointers->getCurrentCursorTexture();
|
||||
if (!texture)
|
||||
return;
|
||||
|
@ -91,6 +88,9 @@ void CDynamicCursors::renderSoftware(CPointerManager* pointers, SP<CMonitor> pMo
|
|||
box.w *= zoom;
|
||||
box.h *= zoom;
|
||||
|
||||
if (box.intersection(CBox{{}, {pMonitor->vecSize}}).empty())
|
||||
return;
|
||||
|
||||
// we rotate the cursor by our calculated amount
|
||||
box.rot = resultShown.rotation;
|
||||
|
||||
|
|
|
@ -109,8 +109,12 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
|||
addConfig(CONFIG_SHAKE_NEAREST, true);
|
||||
addConfig(CONFIG_SHAKE_EFFECTS, false);
|
||||
addConfig(CONFIG_SHAKE_IPC, false);
|
||||
addConfig(CONFIG_SHAKE_THRESHOLD, 4.0f);
|
||||
addConfig(CONFIG_SHAKE_FACTOR, 1.5f);
|
||||
addConfig(CONFIG_SHAKE_THRESHOLD, 6.0f);
|
||||
addConfig(CONFIG_SHAKE_BASE, 4.0F);
|
||||
addConfig(CONFIG_SHAKE_SPEED, 4.0F);
|
||||
addConfig(CONFIG_SHAKE_INFLUENCE, 0.0F);
|
||||
addConfig(CONFIG_SHAKE_LIMIT, 0.0F);
|
||||
addConfig(CONFIG_SHAKE_TIMEOUT, 2000);
|
||||
|
||||
addShapeConfig(CONFIG_TILT_FUNCTION, "negative_quadratic");
|
||||
addShapeConfig(CONFIG_TILT_LIMIT, 5000);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue