From 16dc4df3d438142ae378c9c6983585d06e0c6a33 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Mon, 29 Mar 2021 17:14:49 -0400 Subject: refactor common/settings only driver compiles remove accel-base types merge linear + classic move gain cap logic into classic impl, cap is now set in terms of output use cap/limit to determine negation remove weight, add replacement for power mode only remove legacy offset option remove naturalgain mode add legacy mode flag naturalgain -> natural natural -> natural + legacy flag add dpi setting and more accel args + defaults (prep for ips mode) replace output speed cap with input cap --- common/rawaccel.hpp | 233 ++++++++++++++++------------------------------------ 1 file changed, 72 insertions(+), 161 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index e28cd92..cb30820 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -3,13 +3,10 @@ #define _USE_MATH_DEFINES #include -#include "rawaccel-settings.h" #include "x64-util.hpp" -#include "accel-linear.hpp" #include "accel-classic.hpp" #include "accel-natural.hpp" -#include "accel-naturalgain.hpp" #include "accel-power.hpp" #include "accel-motivity.hpp" #include "accel-noaccel.hpp" @@ -62,81 +59,86 @@ namespace rawaccel { snapper() = default; }; - /// Struct to hold clamp (min and max) details for acceleration application - struct accel_scale_clamp { - double lo = 0; - double hi = 1e9; + inline void cap_speed(vec2d& v, double cap, double norm) { + double speed = sqrtsd(v.x * v.x + v.y * v.y) * norm; + double ratio = minsd(speed, cap) / speed; + v.x *= ratio; + v.y *= ratio; + } + + enum class internal_mode { + classic_lgcy, + classic_gain, + natural_lgcy, + natural_gain, + power, + motivity, + noaccel + }; - /// - /// Clamps given input to min at lo, max at hi. - /// - /// Double to be clamped - /// Clamped input as double - inline double operator()(double scale) const { - return clampsd(scale, lo, hi); + constexpr internal_mode make_mode(accel_mode m, bool legacy) { + switch (m) { + case accel_mode::classic: + return legacy ? internal_mode::classic_lgcy : internal_mode::classic_gain; + case accel_mode::natural: + return legacy ? internal_mode::natural_lgcy : internal_mode::natural_gain; + case accel_mode::power: + return internal_mode::power; + case accel_mode::motivity: + return internal_mode::motivity; + default: + return internal_mode::noaccel; } + } - accel_scale_clamp(double cap) { - if (cap <= 0) { - // use default, effectively uncapped accel - return; - } - - if (cap < 1) { - // assume negative accel - lo = cap; - hi = 1; - } - else hi = cap; - } + constexpr internal_mode make_mode(const accel_args& args) { + return make_mode(args.mode, args.legacy); + } - accel_scale_clamp() = default; - }; - template inline auto visit_accel(Visitor vis, Variant&& var) { switch (var.tag) { - case accel_mode::linear: return vis(var.u.linear); - case accel_mode::classic: return vis(var.u.classic); - case accel_mode::natural: return vis(var.u.natural); - case accel_mode::naturalgain: return vis(var.u.naturalgain); - case accel_mode::power: return vis(var.u.power); - case accel_mode::motivity: return vis(var.u.motivity); - default: return vis(var.u.noaccel); + case internal_mode::classic_lgcy: return vis(var.u.classic_l); + case internal_mode::classic_gain: return vis(var.u.classic_g); + case internal_mode::natural_lgcy: return vis(var.u.natural_l); + case internal_mode::natural_gain: return vis(var.u.natural_g); + case internal_mode::power: return vis(var.u.power); + case internal_mode::motivity: return vis(var.u.motivity); + default: return vis(var.u.noaccel); } } struct accel_variant { si_pair* lookup; - accel_mode tag = accel_mode::noaccel; + internal_mode tag = internal_mode::noaccel; union union_t { - accel_linear linear; - accel_classic classic; - accel_natural natural; - accel_naturalgain naturalgain; - accel_power power; - accel_motivity motivity; + classic classic_g; + classic_legacy classic_l; + natural natural_g; + natural_legacy natural_l; + power power; + motivity motivity; accel_noaccel noaccel = {}; } u = {}; - accel_variant(const accel_args& args, accel_mode mode, si_pair* lut = nullptr) : - tag(mode), lookup(lut) + accel_variant(const accel_args& args, si_pair* lut = nullptr) : + tag(make_mode(args)), lookup(lut) { visit_accel([&](auto& impl) { impl = { args }; }, *this); - if (lookup && tag == accel_mode::motivity) { - u.motivity.fn.fill(lookup); + if (lookup && tag == internal_mode::motivity) { + u.motivity.fill(lookup); } } inline double apply(double speed) const { - if (lookup && tag == accel_mode::motivity) { - return u.motivity.fn.apply(lookup, speed); + if (lookup && tag == internal_mode::motivity) { + return u.motivity.apply(lookup, speed); } return visit_accel([=](auto&& impl) { @@ -147,104 +149,6 @@ namespace rawaccel { accel_variant() = default; }; - /// Struct to hold information about applying a gain cap. - struct velocity_gain_cap { - - // The minimum speed past which gain cap is applied. - double threshold = 0; - - // The gain at the point of cap - double slope = 0; - - // The intercept for the line with above slope to give continuous velocity function - double intercept = 0; - - /// - /// Initializes a velocity gain cap for a certain speed threshold - /// by estimating the slope at the threshold and creating a line - /// with that slope for output velocity calculations. - /// - /// The speed at which velocity gain cap will kick in - /// The accel implementation used in the containing accel_variant - velocity_gain_cap(double speed, const accel_variant& accel) - { - if (speed <= 0) return; - - // Estimate gain at cap point by taking line between two input vs output velocity points. - // First input velocity point is at cap; for second pick a velocity a tiny bit larger. - double speed_second = 1.001 * speed; - double speed_diff = speed_second - speed; - - // Return if by glitch or strange values the difference in points is 0. - if (speed_diff == 0) return; - - // Find the corresponding output velocities for the two points. - double out_first = accel.apply(speed) * speed; - double out_second = accel.apply(speed_second) * speed_second; - - // Calculate slope and intercept from two points. - slope = (out_second - out_first) / speed_diff; - intercept = out_first - slope * speed; - - threshold = speed; - } - - /// - /// Applies velocity gain cap to speed. - /// Returns scale value by which to multiply input to place on gain cap line. - /// - /// Speed to be capped - /// Scale multiplier for input - inline double apply(double speed) const { - return slope + intercept / speed; - } - - /// - /// Whether gain cap should be applied to given speed. - /// - /// Speed to check against threshold. - /// Whether gain cap should be applied. - inline bool should_apply(double speed) const { - return threshold > 0 && speed > threshold; - } - - velocity_gain_cap() = default; - }; - - struct accelerator { - accel_variant accel; - velocity_gain_cap gain_cap; - accel_scale_clamp clamp; - double output_speed_cap = 0; - - accelerator(const accel_args& args, accel_mode mode, si_pair* lut = nullptr) : - accel(args, mode, lut), gain_cap(args.gain_cap, accel), clamp(args.scale_cap) - { - output_speed_cap = maxsd(args.speed_cap, 0); - } - - inline double apply(double speed) const { - double scale; - - if (gain_cap.should_apply(speed)) { - scale = gain_cap.apply(speed); - } - else { - scale = accel.apply(speed); - } - - scale = clamp(scale); - - if (output_speed_cap > 0 && (scale * speed) > output_speed_cap) { - scale = output_speed_cap / speed; - } - - return scale; - } - - accelerator() = default; - }; - struct weighted_distance { double p = 2.0; double p_inverse = 0.5; @@ -318,17 +222,21 @@ namespace rawaccel { bool apply_rotate = false; bool apply_snap = false; bool apply_accel = false; - bool combine_magnitudes = true; + bool by_component = false; rotator rotate; snapper snap; + double dpi_factor = 1; + double speed_cap = 0; weighted_distance distance; direction_weight directional; - vec2 accels; + vec2 accels; vec2d sensitivity = { 1, 1 }; vec2d directional_multipliers = {}; mouse_modifier(const settings& args, vec2 luts = {}) : - combine_magnitudes(args.combine_mags) + by_component(!args.combine_mags), + dpi_factor(1000 / args.dpi), + speed_cap(args.speed_cap) { if (args.degrees_rotation != 0) { rotate = rotator(args.degrees_rotation); @@ -346,16 +254,16 @@ namespace rawaccel { directional_multipliers.x = fabs(args.dir_multipliers.x); directional_multipliers.y = fabs(args.dir_multipliers.y); - if ((combine_magnitudes && args.modes.x == accel_mode::noaccel) || - (args.modes.x == accel_mode::noaccel && - args.modes.y == accel_mode::noaccel)) { + if ((!by_component && args.argsv.x.mode == accel_mode::noaccel) || + (args.argsv.x.mode == accel_mode::noaccel && + args.argsv.y.mode == accel_mode::noaccel)) { return; } - accels.x = accelerator(args.argsv.x, args.modes.x, luts.x); - accels.y = accelerator(args.argsv.y, args.modes.y, luts.y); + accels.x = accel_variant(args.argsv.x, luts.x); + accels.y = accel_variant(args.argsv.y, luts.y); - distance = weighted_distance(args.domain_args); + distance = weighted_distance(args.dom_args); directional = direction_weight(args.range_weights); apply_accel = true; @@ -380,10 +288,13 @@ namespace rawaccel { inline void apply_acceleration(vec2d& movement, TimeSupplier time_supp) { if (apply_accel) { milliseconds time = time_supp(); + double norm = dpi_factor / time; + + if (speed_cap > 0) cap_speed(movement, speed_cap, norm); - if (combine_magnitudes) { + if (!by_component) { double mag = distance.calculate(movement.x, movement.y); - double speed = mag / time; + double speed = mag * norm; double scale = accels.x.apply(speed); if (directional.should_apply) @@ -395,8 +306,8 @@ namespace rawaccel { movement.y *= scale; } else { - movement.x *= accels.x.apply(fabs(movement.x) / time); - movement.y *= accels.y.apply(fabs(movement.y) / time); + movement.x *= accels.x.apply(fabs(movement.x) * norm); + movement.y *= accels.y.apply(fabs(movement.y) * norm); } } } -- cgit v1.2.3 From ed0bbc22681681a16b7d45b05133c38a0b82006f Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Mon, 29 Mar 2021 18:01:20 -0400 Subject: formatting + file renames --- common/rawaccel.hpp | 94 ++--------------------------------------------------- 1 file changed, 3 insertions(+), 91 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index cb30820..67b4e61 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -1,16 +1,11 @@ #pragma once +#include "accel-union.hpp" +#include "utility.hpp" + #define _USE_MATH_DEFINES #include -#include "x64-util.hpp" - -#include "accel-classic.hpp" -#include "accel-natural.hpp" -#include "accel-power.hpp" -#include "accel-motivity.hpp" -#include "accel-noaccel.hpp" - namespace rawaccel { /// Struct to hold vector rotation details. @@ -66,89 +61,6 @@ namespace rawaccel { v.y *= ratio; } - enum class internal_mode { - classic_lgcy, - classic_gain, - natural_lgcy, - natural_gain, - power, - motivity, - noaccel - }; - - constexpr internal_mode make_mode(accel_mode m, bool legacy) { - switch (m) { - case accel_mode::classic: - return legacy ? internal_mode::classic_lgcy : internal_mode::classic_gain; - case accel_mode::natural: - return legacy ? internal_mode::natural_lgcy : internal_mode::natural_gain; - case accel_mode::power: - return internal_mode::power; - case accel_mode::motivity: - return internal_mode::motivity; - default: - return internal_mode::noaccel; - } - } - - constexpr internal_mode make_mode(const accel_args& args) { - return make_mode(args.mode, args.legacy); - } - - template - inline auto visit_accel(Visitor vis, Variant&& var) { - switch (var.tag) { - case internal_mode::classic_lgcy: return vis(var.u.classic_l); - case internal_mode::classic_gain: return vis(var.u.classic_g); - case internal_mode::natural_lgcy: return vis(var.u.natural_l); - case internal_mode::natural_gain: return vis(var.u.natural_g); - case internal_mode::power: return vis(var.u.power); - case internal_mode::motivity: return vis(var.u.motivity); - default: return vis(var.u.noaccel); - } - } - - struct accel_variant { - si_pair* lookup; - - internal_mode tag = internal_mode::noaccel; - - union union_t { - classic classic_g; - classic_legacy classic_l; - natural natural_g; - natural_legacy natural_l; - power power; - motivity motivity; - accel_noaccel noaccel = {}; - } u = {}; - - accel_variant(const accel_args& args, si_pair* lut = nullptr) : - tag(make_mode(args)), lookup(lut) - { - visit_accel([&](auto& impl) { - impl = { args }; - }, *this); - - if (lookup && tag == internal_mode::motivity) { - u.motivity.fill(lookup); - } - - } - - inline double apply(double speed) const { - if (lookup && tag == internal_mode::motivity) { - return u.motivity.apply(lookup, speed); - } - - return visit_accel([=](auto&& impl) { - return impl(speed); - }, *this); - } - - accel_variant() = default; - }; - struct weighted_distance { double p = 2.0; double p_inverse = 0.5; -- cgit v1.2.3 From 11045335c14371847411b8fb5096f479e18fbf5e Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Mon, 29 Mar 2021 19:57:33 -0400 Subject: add zero/inf/nan guards --- common/rawaccel.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 67b4e61..f6bc0fd 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -218,8 +218,12 @@ namespace rawaccel { movement.y *= scale; } else { - movement.x *= accels.x.apply(fabs(movement.x) * norm); - movement.y *= accels.y.apply(fabs(movement.y) * norm); + if (movement.x != 0) { + movement.x *= accels.x.apply(fabs(movement.x) * norm); + } + if (movement.y != 0) { + movement.y *= accels.y.apply(fabs(movement.y) * norm); + } } } } -- cgit v1.2.3 From fa3ebfb1eb054ba88824a908c996094bb98e85c5 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 30 Mar 2021 18:27:02 -0400 Subject: refactor lut/motivity --- common/rawaccel.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index f6bc0fd..5d3ee15 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -145,7 +145,7 @@ namespace rawaccel { vec2d sensitivity = { 1, 1 }; vec2d directional_multipliers = {}; - mouse_modifier(const settings& args, vec2 luts = {}) : + mouse_modifier(const settings& args) : by_component(!args.combine_mags), dpi_factor(1000 / args.dpi), speed_cap(args.speed_cap) @@ -172,8 +172,8 @@ namespace rawaccel { return; } - accels.x = accel_variant(args.argsv.x, luts.x); - accels.y = accel_variant(args.argsv.y, luts.y); + accels.x = accel_variant(args.argsv.x); + accels.y = accel_variant(args.argsv.y); distance = weighted_distance(args.dom_args); directional = direction_weight(args.range_weights); @@ -243,4 +243,9 @@ namespace rawaccel { mouse_modifier() = default; }; + struct io_t { + settings args; + mouse_modifier mod; + }; + } // rawaccel -- cgit v1.2.3 From 31ffabf6f32ae14b6e2f6ce33763bf4ef1bff809 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 19:40:19 -0400 Subject: make weights work in by component mode domain weights now applied under inf norm range weights now applied when equal --- common/rawaccel.hpp | 74 ++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 41 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 5d3ee15..ad4def4 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -88,46 +88,30 @@ namespace rawaccel { inline double calculate(double x, double y) { - double abs_x = fabs(x); - double abs_y = fabs(y); + double abs_scaled_x = fabs(x) * sigma_x; + double abs_scaled_y = fabs(y) * sigma_y; - if (lp_norm_infinity) return maxsd(abs_x, abs_y); + if (lp_norm_infinity) { + return maxsd(abs_scaled_x, abs_scaled_y); + } - double x_scaled = abs_x * sigma_x; - double y_scaled = abs_y * sigma_y; + if (p == 2) { + return sqrtsd(abs_scaled_x * abs_scaled_x + + abs_scaled_y * abs_scaled_y); + } - if (p == 2) return sqrtsd(x_scaled * x_scaled + y_scaled * y_scaled); - else return pow(pow(x_scaled, p) + pow(y_scaled, p), p_inverse); + double dist_p = pow(abs_scaled_x, p) + pow(abs_scaled_y, p); + return pow(dist_p, p_inverse); } weighted_distance() = default; }; - struct direction_weight { - double diff = 0.0; - double start = 1.0; - bool should_apply = false; - - direction_weight(const vec2d& thetas) - { - diff = thetas.y - thetas.x; - start = thetas.x; - - should_apply = diff != 0; - } - - inline double atan_scale(double x, double y) - { - return M_2_PI * atan2(fabs(y), fabs(x)); - } - - inline double apply(double x, double y) - { - return atan_scale(x, y) * diff + start; - } - - direction_weight() = default; - }; + inline double directional_weight(const vec2d& in, const vec2d& weights) + { + double atan_scale = M_2_PI * atan2(fabs(in.y), fabs(in.x)); + return atan_scale * (weights.y - weights.x) + weights.x; + } /// Struct to hold variables and methods for modifying mouse input struct mouse_modifier { @@ -135,12 +119,13 @@ namespace rawaccel { bool apply_snap = false; bool apply_accel = false; bool by_component = false; + bool apply_directional_weight = false; rotator rotate; snapper snap; double dpi_factor = 1; double speed_cap = 0; weighted_distance distance; - direction_weight directional; + vec2d range_weights = { 1, 1 }; vec2 accels; vec2d sensitivity = { 1, 1 }; vec2d directional_multipliers = {}; @@ -148,7 +133,8 @@ namespace rawaccel { mouse_modifier(const settings& args) : by_component(!args.combine_mags), dpi_factor(1000 / args.dpi), - speed_cap(args.speed_cap) + speed_cap(args.speed_cap), + range_weights(args.range_weights) { if (args.degrees_rotation != 0) { rotate = rotator(args.degrees_rotation); @@ -176,8 +162,8 @@ namespace rawaccel { accels.y = accel_variant(args.argsv.y); distance = weighted_distance(args.dom_args); - directional = direction_weight(args.range_weights); + apply_directional_weight = range_weights.x != range_weights.y; apply_accel = true; } @@ -207,22 +193,28 @@ namespace rawaccel { if (!by_component) { double mag = distance.calculate(movement.x, movement.y); double speed = mag * norm; - double scale = accels.x.apply(speed); - if (directional.should_apply) - { - scale = (scale - 1)*directional.apply(movement.x, movement.y) + 1; + double weight; + + if (apply_directional_weight) { + weight = directional_weight(movement, range_weights); + } + else { + weight = range_weights.x; } + double scale = accels.x.apply(speed, weight); movement.x *= scale; movement.y *= scale; } else { if (movement.x != 0) { - movement.x *= accels.x.apply(fabs(movement.x) * norm); + double x = fabs(movement.x) * norm * distance.sigma_x; + movement.x *= accels.x.apply(x, range_weights.x); } if (movement.y != 0) { - movement.y *= accels.y.apply(fabs(movement.y) * norm); + double y = fabs(movement.y) * norm * distance.sigma_y; + movement.y *= accels.y.apply(y, range_weights.y); } } } -- cgit v1.2.3 From 3751ac95831412dbdf9de9744c0ef59c34033d3d Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 20:56:29 -0400 Subject: add minimum to complement speed cap important feature fixes some validation checks --- common/rawaccel.hpp | 84 +++++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 41 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index ad4def4..8e10644 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -49,18 +49,18 @@ namespace rawaccel { return input; } - snapper(double degrees) : threshold(minsd(fabs(degrees), 45) * M_PI / 180) {} + snapper(double degrees) : threshold(minsd(fabs(degrees), 45)* M_PI / 180) {} snapper() = default; }; - inline void cap_speed(vec2d& v, double cap, double norm) { + inline void clamp_speed(vec2d& v, double min, double max, double norm) { double speed = sqrtsd(v.x * v.x + v.y * v.y) * norm; - double ratio = minsd(speed, cap) / speed; + double ratio = clampsd(speed, min, max) / speed; v.x *= ratio; v.y *= ratio; } - + struct weighted_distance { double p = 2.0; double p_inverse = 0.5; @@ -88,8 +88,8 @@ namespace rawaccel { inline double calculate(double x, double y) { - double abs_scaled_x = fabs(x) * sigma_x; - double abs_scaled_y = fabs(y) * sigma_y; + double abs_scaled_x = fabs(x) * sigma_x; + double abs_scaled_y = fabs(y) * sigma_y; if (lp_norm_infinity) { return maxsd(abs_scaled_x, abs_scaled_y); @@ -97,7 +97,7 @@ namespace rawaccel { if (p == 2) { return sqrtsd(abs_scaled_x * abs_scaled_x + - abs_scaled_y * abs_scaled_y); + abs_scaled_y * abs_scaled_y); } double dist_p = pow(abs_scaled_x, p) + pow(abs_scaled_y, p); @@ -117,13 +117,14 @@ namespace rawaccel { struct mouse_modifier { bool apply_rotate = false; bool apply_snap = false; - bool apply_accel = false; + bool apply_speed_clamp = false; bool by_component = false; bool apply_directional_weight = false; rotator rotate; snapper snap; double dpi_factor = 1; - double speed_cap = 0; + double speed_min = 0; + double speed_max = 0; weighted_distance distance; vec2d range_weights = { 1, 1 }; vec2 accels; @@ -133,14 +134,15 @@ namespace rawaccel { mouse_modifier(const settings& args) : by_component(!args.combine_mags), dpi_factor(1000 / args.dpi), - speed_cap(args.speed_cap), + speed_min(args.speed_min), + speed_max(args.speed_max), range_weights(args.range_weights) { if (args.degrees_rotation != 0) { rotate = rotator(args.degrees_rotation); apply_rotate = true; } - + if (args.degrees_snap != 0) { snap = snapper(args.degrees_snap); apply_snap = true; @@ -152,6 +154,8 @@ namespace rawaccel { directional_multipliers.x = fabs(args.dir_multipliers.x); directional_multipliers.y = fabs(args.dir_multipliers.y); + apply_speed_clamp = speed_max > 0; + if ((!by_component && args.argsv.x.mode == accel_mode::noaccel) || (args.argsv.x.mode == accel_mode::noaccel && args.argsv.y.mode == accel_mode::noaccel)) { @@ -164,13 +168,12 @@ namespace rawaccel { distance = weighted_distance(args.dom_args); apply_directional_weight = range_weights.x != range_weights.y; - apply_accel = true; } void modify(vec2d& movement, milliseconds time) { apply_rotation(movement); apply_angle_snap(movement); - apply_acceleration(movement, [=] { return time; }); + apply_acceleration(movement, time); apply_sensitivity(movement); } @@ -182,43 +185,42 @@ namespace rawaccel { if (apply_snap) movement = snap.apply(movement); } - template - inline void apply_acceleration(vec2d& movement, TimeSupplier time_supp) { - if (apply_accel) { - milliseconds time = time_supp(); - double norm = dpi_factor / time; - - if (speed_cap > 0) cap_speed(movement, speed_cap, norm); + inline void apply_acceleration(vec2d& movement, milliseconds time) { + double norm = dpi_factor / time; - if (!by_component) { - double mag = distance.calculate(movement.x, movement.y); - double speed = mag * norm; + if (apply_speed_clamp) { + clamp_speed(movement, speed_min, speed_max, norm); + } - double weight; + if (!by_component) { + double mag = distance.calculate(movement.x, movement.y); + double speed = mag * norm; - if (apply_directional_weight) { - weight = directional_weight(movement, range_weights); - } - else { - weight = range_weights.x; - } + double weight; - double scale = accels.x.apply(speed, weight); - movement.x *= scale; - movement.y *= scale; + if (apply_directional_weight) { + weight = directional_weight(movement, range_weights); } else { - if (movement.x != 0) { - double x = fabs(movement.x) * norm * distance.sigma_x; - movement.x *= accels.x.apply(x, range_weights.x); - } - if (movement.y != 0) { - double y = fabs(movement.y) * norm * distance.sigma_y; - movement.y *= accels.y.apply(y, range_weights.y); - } + weight = range_weights.x; + } + + double scale = accels.x.apply(speed, weight); + movement.x *= scale; + movement.y *= scale; + } + else { + if (movement.x != 0) { + double x = fabs(movement.x) * norm * distance.sigma_x; + movement.x *= accels.x.apply(x, range_weights.x); + } + if (movement.y != 0) { + double y = fabs(movement.y) * norm * distance.sigma_y; + movement.y *= accels.y.apply(y, range_weights.y); } } } + inline void apply_sensitivity(vec2d& movement) { movement.x *= sensitivity.x; -- cgit v1.2.3 From d8140fb31ba622f48756986d4d66db6b6ab8b511 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 23:28:41 -0400 Subject: use callbacks for applying accel --- common/rawaccel.hpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 8e10644..6710a0c 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -1,7 +1,6 @@ #pragma once -#include "accel-union.hpp" -#include "utility.hpp" +#include "accel-invoke.hpp" #define _USE_MATH_DEFINES #include @@ -127,7 +126,7 @@ namespace rawaccel { double speed_max = 0; weighted_distance distance; vec2d range_weights = { 1, 1 }; - vec2 accels; + vec2 accels; vec2d sensitivity = { 1, 1 }; vec2d directional_multipliers = {}; @@ -162,18 +161,18 @@ namespace rawaccel { return; } - accels.x = accel_variant(args.argsv.x); - accels.y = accel_variant(args.argsv.y); + accels.x = accel_union(args.argsv.x); + accels.y = accel_union(args.argsv.y); distance = weighted_distance(args.dom_args); apply_directional_weight = range_weights.x != range_weights.y; } - void modify(vec2d& movement, milliseconds time) { + void modify(vec2d& movement, const vec2& inv = {}, milliseconds time = 1) { apply_rotation(movement); apply_angle_snap(movement); - apply_acceleration(movement, time); + apply_acceleration(movement, inv, time); apply_sensitivity(movement); } @@ -185,7 +184,7 @@ namespace rawaccel { if (apply_snap) movement = snap.apply(movement); } - inline void apply_acceleration(vec2d& movement, milliseconds time) { + inline void apply_acceleration(vec2d& movement, const vec2& inv, milliseconds time) { double norm = dpi_factor / time; if (apply_speed_clamp) { @@ -205,18 +204,18 @@ namespace rawaccel { weight = range_weights.x; } - double scale = accels.x.apply(speed, weight); + double scale = inv.x.invoke(accels.x, speed, weight); movement.x *= scale; movement.y *= scale; } else { if (movement.x != 0) { double x = fabs(movement.x) * norm * distance.sigma_x; - movement.x *= accels.x.apply(x, range_weights.x); + movement.x *= inv.x.invoke(accels.x, x, range_weights.x); } if (movement.y != 0) { double y = fabs(movement.y) * norm * distance.sigma_y; - movement.y *= accels.y.apply(y, range_weights.y); + movement.y *= inv.y.invoke(accels.y, y, range_weights.y); } } } -- cgit v1.2.3 From c55d1bfd01147fa014ac07d4b03ef3cad8427ae6 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 8 Apr 2021 02:30:01 -0400 Subject: optimize a bit/refactor modify --- common/rawaccel.hpp | 323 +++++++++++++++++++++------------------------------- 1 file changed, 129 insertions(+), 194 deletions(-) (limited to 'common/rawaccel.hpp') diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 6710a0c..fb2d81a 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -2,235 +2,170 @@ #include "accel-invoke.hpp" -#define _USE_MATH_DEFINES -#include - namespace rawaccel { - /// Struct to hold vector rotation details. - struct rotator { - - /// Rotational vector, which points in the direction of the post-rotation positive x axis. - vec2d rot_vec = { 1, 0 }; - - /// - /// Rotates given input vector according to struct's rotational vector. - /// - /// Input vector to be rotated - /// 2d vector of rotated input. - inline vec2d apply(const vec2d& input) const { - return { - input.x * rot_vec.x - input.y * rot_vec.y, - input.x * rot_vec.y + input.y * rot_vec.x - }; - } - - rotator(double degrees) { - double rads = degrees * M_PI / 180; - rot_vec = { cos(rads), sin(rads) }; - } - - rotator() = default; - }; - - struct snapper { - double threshold = 0; - - inline vec2d apply(const vec2d& input) const { - if (input.x != 0 && input.y != 0) { - double angle = fabs(atan(input.y / input.x)); - auto mag = [&] { return sqrtsd(input.x * input.x + input.y * input.y); }; - - if (angle > M_PI_2 - threshold) return { 0, _copysign(mag(), input.y) }; - if (angle < threshold) return { _copysign(mag(), input.x), 0 }; - } - - return input; - } - - snapper(double degrees) : threshold(minsd(fabs(degrees), 45)* M_PI / 180) {} - - snapper() = default; - }; - - inline void clamp_speed(vec2d& v, double min, double max, double norm) { - double speed = sqrtsd(v.x * v.x + v.y * v.y) * norm; - double ratio = clampsd(speed, min, max) / speed; - v.x *= ratio; - v.y *= ratio; + inline vec2d direction(double degrees) + { + double radians = degrees * PI / 180; + return { cos(radians), sin(radians) }; } - struct weighted_distance { - double p = 2.0; - double p_inverse = 0.5; - bool lp_norm_infinity = false; - double sigma_x = 1.0; - double sigma_y = 1.0; - - weighted_distance(const domain_args& args) - { - sigma_x = args.domain_weights.x; - sigma_y = args.domain_weights.y; - if (args.lp_norm <= 0) - { - lp_norm_infinity = true; - p = 0.0; - p_inverse = 0.0; - } - else - { - lp_norm_infinity = false; - p = args.lp_norm; - p_inverse = 1 / args.lp_norm; - } - } - - inline double calculate(double x, double y) - { - double abs_scaled_x = fabs(x) * sigma_x; - double abs_scaled_y = fabs(y) * sigma_y; - - if (lp_norm_infinity) { - return maxsd(abs_scaled_x, abs_scaled_y); - } - - if (p == 2) { - return sqrtsd(abs_scaled_x * abs_scaled_x + - abs_scaled_y * abs_scaled_y); - } - - double dist_p = pow(abs_scaled_x, p) + pow(abs_scaled_y, p); - return pow(dist_p, p_inverse); - } + constexpr vec2d rotate(const vec2d& v, const vec2d& direction) + { + return { + v.x * direction.x - v.y * direction.y, + v.x * direction.y + v.y * direction.x + }; + } - weighted_distance() = default; - }; + inline double magnitude(const vec2d& v) + { + return sqrt(v.x * v.x + v.y * v.y); + } - inline double directional_weight(const vec2d& in, const vec2d& weights) + inline double lp_distance(const vec2d& v, double p) { - double atan_scale = M_2_PI * atan2(fabs(in.y), fabs(in.x)); - return atan_scale * (weights.y - weights.x) + weights.x; + return pow(pow(v.x, p) + pow(v.y, p), 1 / p); } - /// Struct to hold variables and methods for modifying mouse input - struct mouse_modifier { + class mouse_modifier { + public: + enum accel_distance_mode : unsigned char { + separate, + max, + Lp, + euclidean, + }; + bool apply_rotate = false; + bool compute_ref_angle = false; bool apply_snap = false; - bool apply_speed_clamp = false; - bool by_component = false; + bool cap_speed = false; + accel_distance_mode dist_mode = euclidean; bool apply_directional_weight = false; - rotator rotate; - snapper snap; - double dpi_factor = 1; + bool apply_dir_mul_x = false; + bool apply_dir_mul_y = false; + + vec2d rot_vec = { 1, 0 }; + double snap = 0; + double dpi_norm_factor = 1; double speed_min = 0; double speed_max = 0; - weighted_distance distance; + vec2d domain_weights = { 1, 1 }; + double p = 2; vec2d range_weights = { 1, 1 }; - vec2 accels; + vec2d directional_multipliers = { 1, 1 }; vec2d sensitivity = { 1, 1 }; - vec2d directional_multipliers = {}; + vec2 accel; - mouse_modifier(const settings& args) : - by_component(!args.combine_mags), - dpi_factor(1000 / args.dpi), - speed_min(args.speed_min), - speed_max(args.speed_max), - range_weights(args.range_weights) +#ifdef _KERNEL_MODE + __forceinline +#endif + void modify(vec2d& in, const vec2& inv, milliseconds time = 1) const { - if (args.degrees_rotation != 0) { - rotate = rotator(args.degrees_rotation); - apply_rotate = true; - } - - if (args.degrees_snap != 0) { - snap = snapper(args.degrees_snap); - apply_snap = true; - } - - if (args.sens.x != 0) sensitivity.x = args.sens.x; - if (args.sens.y != 0) sensitivity.y = args.sens.y; + double ips_factor = dpi_norm_factor / time; + double reference_angle = 0; - directional_multipliers.x = fabs(args.dir_multipliers.x); - directional_multipliers.y = fabs(args.dir_multipliers.y); + if (apply_rotate) in = rotate(in, rot_vec); - apply_speed_clamp = speed_max > 0; - - if ((!by_component && args.argsv.x.mode == accel_mode::noaccel) || - (args.argsv.x.mode == accel_mode::noaccel && - args.argsv.y.mode == accel_mode::noaccel)) { - return; + if (compute_ref_angle && in.y != 0) { + if (in.x == 0) { + reference_angle = PI / 2; + } + else { + reference_angle = atan(fabs(in.y / in.x)); + + if (apply_snap) { + if (reference_angle > PI / 2 - snap) { + reference_angle = PI / 2; + in = { 0, _copysign(magnitude(in), in.y) }; + } + else if (reference_angle < snap) { + reference_angle = 0; + in = { _copysign(magnitude(in), in.x), 0 }; + } + } + } } - accels.x = accel_union(args.argsv.x); - accels.y = accel_union(args.argsv.y); - - distance = weighted_distance(args.dom_args); - - apply_directional_weight = range_weights.x != range_weights.y; - } - - void modify(vec2d& movement, const vec2& inv = {}, milliseconds time = 1) { - apply_rotation(movement); - apply_angle_snap(movement); - apply_acceleration(movement, inv, time); - apply_sensitivity(movement); - } - - inline void apply_rotation(vec2d& movement) { - if (apply_rotate) movement = rotate.apply(movement); - } - - inline void apply_angle_snap(vec2d& movement) { - if (apply_snap) movement = snap.apply(movement); - } - - inline void apply_acceleration(vec2d& movement, const vec2& inv, milliseconds time) { - double norm = dpi_factor / time; - - if (apply_speed_clamp) { - clamp_speed(movement, speed_min, speed_max, norm); + if (cap_speed) { + double speed = magnitude(in) * ips_factor; + double ratio = clampsd(speed, speed_min, speed_max) / speed; + in.x *= ratio; + in.y *= ratio; } - if (!by_component) { - double mag = distance.calculate(movement.x, movement.y); - double speed = mag * norm; + vec2d abs_weighted_vel = { + fabs(in.x * ips_factor * domain_weights.x), + fabs(in.y * ips_factor * domain_weights.y) + }; - double weight; + if (dist_mode == separate) { + in.x *= inv.x.invoke(accel.x, abs_weighted_vel.x, range_weights.x); + in.y *= inv.y.invoke(accel.y, abs_weighted_vel.y, range_weights.y); + } + else { + double speed; - if (apply_directional_weight) { - weight = directional_weight(movement, range_weights); + if (dist_mode == max) { + speed = maxsd(abs_weighted_vel.x, abs_weighted_vel.y); + } + else if (dist_mode == Lp) { + speed = lp_distance(abs_weighted_vel, p); } else { - weight = range_weights.x; + speed = magnitude(abs_weighted_vel); } - double scale = inv.x.invoke(accels.x, speed, weight); - movement.x *= scale; - movement.y *= scale; - } - else { - if (movement.x != 0) { - double x = fabs(movement.x) * norm * distance.sigma_x; - movement.x *= inv.x.invoke(accels.x, x, range_weights.x); - } - if (movement.y != 0) { - double y = fabs(movement.y) * norm * distance.sigma_y; - movement.y *= inv.y.invoke(accels.y, y, range_weights.y); + double weight = range_weights.x; + + if (apply_directional_weight) { + double diff = range_weights.y - range_weights.x; + weight += 2 / PI * reference_angle * diff; } - } - } - - inline void apply_sensitivity(vec2d& movement) { - movement.x *= sensitivity.x; - movement.y *= sensitivity.y; + double scale = inv.x.invoke(accel.x, speed, weight); + in.x *= scale; + in.y *= scale; + } - if (directional_multipliers.x > 0 && movement.x < 0) { - movement.x *= directional_multipliers.x; + if (apply_dir_mul_x && in.x < 0) { + in.x *= directional_multipliers.x; } - if (directional_multipliers.y > 0 && movement.y < 0) { - movement.y *= directional_multipliers.y; + + if (apply_dir_mul_y && in.y < 0) { + in.y *= directional_multipliers.y; } + + in.x *= sensitivity.x; + in.y *= sensitivity.y; + } + + mouse_modifier(const settings& args) : + rot_vec(direction(args.degrees_rotation)), + snap(args.degrees_snap * PI / 180), + dpi_norm_factor(1000 / args.dpi), + speed_min(args.speed_min), + speed_max(args.speed_max), + p(args.dom_args.lp_norm), + domain_weights(args.dom_args.domain_weights), + range_weights(args.range_weights), + directional_multipliers(args.dir_multipliers), + sensitivity(args.sens), + accel({ { args.argsv.x }, { args.argsv.y } }) + { + cap_speed = speed_max > 0 && speed_min <= speed_max; + apply_rotate = rot_vec.x != 1; + apply_snap = snap != 0; + apply_directional_weight = range_weights.x != range_weights.y; + compute_ref_angle = apply_snap || apply_directional_weight; + apply_dir_mul_x = directional_multipliers.x != 1; + apply_dir_mul_y = directional_multipliers.y != 1; + + if (!args.combine_mags) dist_mode = separate; + else if (p >= MAX_NORM) dist_mode = max; + else if (p > 2) dist_mode = Lp; + else dist_mode = euclidean; } mouse_modifier() = default; -- cgit v1.2.3