diff options
| author | Jacob Palecki <[email protected]> | 2020-07-28 01:53:32 -0700 |
|---|---|---|
| committer | Jacob Palecki <[email protected]> | 2020-07-28 01:53:32 -0700 |
| commit | 894a13926f79e209e3b619012cd2bb6961d959e2 (patch) | |
| tree | abee0d004e31ebec198d5f5055cdee4d5347e738 | |
| parent | skeleton (diff) | |
| download | rawaccel-894a13926f79e209e3b619012cd2bb6961d959e2.tar.xz rawaccel-894a13926f79e209e3b619012cd2bb6961d959e2.zip | |
Further refactoring and comments
| -rw-r--r-- | common/Error.hpp | 10 | ||||
| -rw-r--r-- | common/common.vcxitems | 1 | ||||
| -rw-r--r-- | common/rawaccel.hpp | 546 | ||||
| -rw-r--r-- | wrapper/wrapper.hpp | 2 |
4 files changed, 323 insertions, 236 deletions
diff --git a/common/Error.hpp b/common/Error.hpp new file mode 100644 index 0000000..ed87090 --- /dev/null +++ b/common/Error.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include <iostream> + + +namespace rawaccel { + void error(const char* s) { + throw std::domain_error(s); + } +} diff --git a/common/common.vcxitems b/common/common.vcxitems index f60f78a..224792c 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -14,6 +14,7 @@ <ProjectCapability Include="SourceItemsFromImports" /> </ItemGroup> <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)Error.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-userspace.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)x64-util.hpp" /> diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index f7f9df7..3380e4c 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -7,256 +7,332 @@ #include "x64-util.hpp" #include "external/tagged-union-single.h" -namespace rawaccel { +namespace rawaccel { -enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; + enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; -struct rotator { - vec2d rot_vec = { 1, 0 }; + struct rotator { + vec2d rot_vec = { 1, 0 }; - inline vec2d operator()(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 - }; - } + inline vec2d operator()(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(double degrees) { + double rads = degrees * M_PI / 180; + rot_vec = { cos(rads), sin(rads) }; + } - rotator() = default; -}; + rotator() = default; + }; -struct accel_scale_clamp { - double lo = 0; - double hi = 9; + struct accel_scale_clamp { + double lo = 0; + double hi = 9; - inline double operator()(double scale) const { - return clampsd(scale, lo, hi); - } + inline double operator()(double scale) const { + return clampsd(scale, lo, hi); + } - accel_scale_clamp(double cap) : accel_scale_clamp() { - if (cap <= 0) { - // use default, effectively uncapped accel - return; + accel_scale_clamp(double cap) : accel_scale_clamp() { + if (cap <= 0) { + // use default, effectively uncapped accel + return; + } + + if (cap < 1) { + // assume negative accel + lo = cap; + hi = 1; + } + else hi = cap; } - if (cap < 1) { - // assume negative accel - lo = cap; - hi = 1; + accel_scale_clamp() = default; + }; + +#ifdef _KERNEL_MODE + void error(const char*) {} +#else + void error(const char* s); +#endif + + using milliseconds = double; + + struct args_t { + mode accel_mode = mode::noaccel; + milliseconds time_min = 0.4; + double offset = 0; + double accel = 0; + double lim_exp = 2; + double midpoint = 0; + vec2d weight = { 1, 1 }; + vec2d cap = { 0, 0 }; + }; + + /// <summary> + /// Struct to hold acceleration implementation details. + /// </summary> + /// <typeparam name="T">Type of acceleration.</typeparam> + template <typename T> + struct accel_implentation { + + /// <summary> The acceleration ramp rate.</summary> + double b = 0; + + /// <summary> The limit or exponent for various modes. </summary> + double k = 0; + + /// <summary> The midpoint in sigmoid mode. </summary> + double m = 0; + + /// <summary> The offset past which acceleration is applied. Used in power mode. </summary> + double offset = 0; + + /// <summary> + /// Initializes a new instance of the <see cref="accel_implementation{T}"/> struct. + /// </summary> + /// <param name="args"></param> + /// <returns></returns> + accel_implentation(args_t args) + { + b = args.accel; + k = args.lim_exp - 1; + m = args.midpoint; + offset = args.offset; + } + + /// <summary> + /// Returns accelerated value of speed as a ratio of magnitude. + /// </summary> + /// <param name="speed">Mouse speed at which to calculate acceleration.</param> + /// <returns>Ratio of accelerated movement magnitude to input movement magnitude.</returns> + double accelerate(double speed) { return 0; } + + /// <summary> + /// Verifies arguments as valid. Errors if not. + /// </summary> + /// <param name="args">Arguments to verified.</param> + void verify(args_t args) { + if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); + if (args.time_min <= 0) error("min time must be positive"); } - else hi = cap; - } - - accel_scale_clamp() = default; -}; - -void error(const char*); - -using milliseconds = double; - -struct args_t { - mode accel_mode = mode::noaccel; - milliseconds time_min = 0.4; - double offset = 0; - double accel = 0; - double lim_exp = 2; - double midpoint = 0; - vec2d weight = { 1, 1 }; - vec2d cap = { 0, 0 }; -}; - -struct accel_implentation { - double b = 0; - double k = 0; - double m = 0; - double offset = 0; - - accel_implentation(args_t args) - { - b = args.accel; - k = args.lim_exp; - m = args.midpoint; - offset = args.offset; - } - - double virtual accelerate(double speed) { return 0; } - void virtual verify(args_t args) { - if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); - if (args.time_min <= 0) error("min time must be positive"); - } - - accel_implentation() = default; -}; - -struct accel_linear : accel_implentation { - accel_linear(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return b * speed; - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("limit must be greater than 1"); - } -}; - -struct accel_classic : accel_implentation { - accel_classic(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return pow(b * speed, k); - - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -struct accel_logarithmic : accel_implentation { - accel_logarithmic(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return log(speed * b + 1); - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -struct accel_sigmoid : accel_implentation { - accel_sigmoid(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return k / (exp(-b * (speed - m)) + 1); - - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -struct accel_power : accel_implentation { - accel_power(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return (offset > 0 && speed < 1) ? 0 : pow(speed*b, k) - 1; - - - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -using accel_implementation_t = tagged_union<accel_implentation, accel_linear, accel_classic, accel_logarithmic, accel_sigmoid, accel_power>; - -struct accel_function { - - /* - This value is ideally a few microseconds lower than - the user's mouse polling interval, though it should - not matter if the system is stable. - */ - milliseconds time_min = 0.4; - - double speed_offset = 0; - // speed midpoint in sigmoid mode - double m = 0; + /// <summary> + /// + /// </summary> + /// <returns></returns> + accel_implentation() = default; + }; + + /// <summary> Struct to hold linear acceleration implementation. </summary> + struct accel_linear : accel_implentation<accel_linear> { + + accel_linear(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + //f(x) = mx + return b * speed; + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("limit must be greater than 1"); + } + }; - // accel ramp rate - double b = 0; + /// <summary> Struct to hold "classic" (linear raised to power) acceleration implementation. </summary> + struct accel_classic : accel_implentation<accel_classic> { + accel_classic(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + //f(x) = (mx)^k + return pow(b * speed, k); + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// <summary> Struct to hold "natural" (vanishing difference) acceleration implementation. </summary> + struct accel_natural : accel_implentation<accel_natural> { + accel_natural(args_t args) + : accel_implentation(args) + { b /= k; } + + double accelerate(double speed) { + // f(x) = k(1-e^(-mx)) + return k - (k * exp(-b * speed));; + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// <summary> Struct to hold logarithmic acceleration implementation. </summary> + struct accel_logarithmic : accel_implentation<accel_logarithmic> { + accel_logarithmic(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + return log(speed * b + 1); + } - // the limit for natural and sigmoid modes - // or the exponent for classic and power modes - double k = 1; + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// <summary> Struct to hold sigmoid (s-shaped) acceleration implementation. </summary> + struct accel_sigmoid : accel_implentation<accel_sigmoid> { + accel_sigmoid(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + //f(x) = k/(1+e^(-m(c-x))) + return k / (exp(-b * (speed - m)) + 1); + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// <summary> Struct to hold power (non-additive) acceleration implementation. </summary> + struct accel_power : accel_implentation<accel_power> { + accel_power(args_t args) + : accel_implentation(args) + { k++; } + + double accelerate(double speed) { + //f(x) = (mx)^k - 1 + // The subtraction of 1 is with later addition of 1 in mind, + // so that the input vector is directly multiplied by (mx)^k (if unweighted) + return (offset > 0 && speed < 1) ? 0 : pow(speed * b, k) - 1; + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 0) error("exponent must be greater than 0"); + } + }; + + /// <summary> Struct to hold acceleration implementation which applies no acceleration. </summary> + struct accel_noaccel : accel_implentation<accel_noaccel> { + accel_noaccel(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { return 0; } + + void verify(args_t args) {} + }; - accel_implementation_t accel = accel_implentation{}; + using accel_implementation_t = tagged_union<accel_linear, accel_classic, accel_natural, accel_logarithmic, accel_sigmoid, accel_power, accel_noaccel>; + + struct accel_function { + + /* + This value is ideally a few microseconds lower than + the user's mouse polling interval, though it should + not matter if the system is stable. + */ + milliseconds time_min = 0.4; + + /// <summary> The offset past which acceleration is applied. </summary> + double speed_offset = 0; + + accel_implementation_t accel; + + vec2d weight = { 1, 1 }; + vec2<accel_scale_clamp> clamp; + + accel_function(args_t args) { + switch (args.accel_mode) + { + case mode::linear: accel = accel_linear(args); + break; + case mode::classic: accel = accel_classic(args); + break; + case mode::natural: accel = accel_natural(args); + break; + case mode::logarithmic: accel = accel_logarithmic(args); + break; + case mode::sigmoid: accel = accel_sigmoid(args); + break; + case mode::power: accel = accel_power(args); + } + + verify(args); + + time_min = args.time_min; + speed_offset = args.offset; + weight = args.weight; + clamp.x = accel_scale_clamp(args.cap.x); + clamp.y = accel_scale_clamp(args.cap.y); + } + + double apply(double speed) const { + return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); + } - vec2d weight = { 1, 1 }; - vec2<accel_scale_clamp> clamp; + void verify(args_t args) const { + return accel.visit([=](auto accel_t) { accel_t.verify(args); }); + } - accel_function(args_t args) { - accel = accel_linear(args); + inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { + double mag = sqrtsd(input.x * input.x + input.y * input.y); + double time_clamped = clampsd(time, time_min, 100); + double speed = maxsd(mag / time_clamped - speed_offset, 0); - time_min = args.time_min; - m = args.midpoint; - b = args.accel; - k = args.lim_exp - 1; - if (args.accel_mode == mode::natural) b /= k; - if (args.accel_mode == mode::power) k++; - - speed_offset = args.offset; - weight = args.weight; - clamp.x = accel_scale_clamp(args.cap.x); - clamp.y = accel_scale_clamp(args.cap.y); - } - - double apply(double speed) const { - return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); - } - - inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { - double mag = sqrtsd(input.x * input.x + input.y * input.y); - double time_clamped = clampsd(time, time_min, 100); - double speed = maxsd(mag / time_clamped - speed_offset, 0); - - double accel_val = apply(speed); - - double scale_x = weight.x * accel_val + 1; - double scale_y = weight.y * accel_val + 1; - - return { - input.x * clamp.x(scale_x), - input.y * clamp.y(scale_y) - }; - } - - accel_function() = default; -}; - -struct variables { - bool apply_rotate = false; - bool apply_accel = false; - mode accel_mode = mode::noaccel; - rotator rotate; - accel_function accel_fn; - vec2d sensitivity = { 1, 1 }; - - variables(double degrees, vec2d sens, args_t accel_args) - : accel_fn(accel_args) - { - apply_rotate = degrees != 0; - if (apply_rotate) rotate = rotator(degrees); - else rotate = rotator(); - - apply_accel = accel_args.accel_mode != mode::noaccel; - accel_mode = accel_args.accel_mode; - - if (sens.x == 0) sens.x = 1; - if (sens.y == 0) sens.y = 1; - sensitivity = sens; - } - - variables() = default; -}; - -} // rawaccel + double accel_val = apply(speed); + + double scale_x = weight.x * accel_val + 1; + double scale_y = weight.y * accel_val + 1; + + return { + input.x * clamp.x(scale_x), + input.y * clamp.y(scale_y) + }; + } + + accel_function() = default; + }; + + struct variables { + bool apply_rotate = false; + bool apply_accel = false; + mode accel_mode = mode::noaccel; + rotator rotate; + accel_function accel_fn; + vec2d sensitivity = { 1, 1 }; + + variables(double degrees, vec2d sens, args_t accel_args) + : accel_fn(accel_args) + { + apply_rotate = degrees != 0; + if (apply_rotate) rotate = rotator(degrees); + else rotate = rotator(); + + apply_accel = accel_args.accel_mode != mode::noaccel; + accel_mode = accel_args.accel_mode; + + if (sens.x == 0) sens.x = 1; + if (sens.y == 0) sens.y = 1; + sensitivity = sens; + } + + variables() = default; + }; + +} // rawaccel
\ No newline at end of file diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index a5699ac..e9bbf2e 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -1,7 +1,7 @@ #pragma once #include "..\common\rawaccel.hpp"; -#include "..\common\rawaccel-userspace.hpp"; +#include "..\common\error.hpp"; #include <iostream> using namespace rawaccel; using namespace System; |