diff options
| author | Jacob Palecki <[email protected]> | 2020-07-29 15:51:53 -0700 |
|---|---|---|
| committer | Jacob Palecki <[email protected]> | 2020-07-29 15:51:53 -0700 |
| commit | 0a91af55f79d9a9d5bda600e8eee7e17c65bd0b6 (patch) | |
| tree | 642659b6ed96b00bc4e9bf6d3152978889ea0079 | |
| parent | add sum types (diff) | |
| parent | Use modifier object in wrapper (diff) | |
| download | rawaccel-0a91af55f79d9a9d5bda600e8eee7e17c65bd0b6.tar.xz rawaccel-0a91af55f79d9a9d5bda600e8eee7e17c65bd0b6.zip | |
Merge remote-tracking branch 'downstream/Inheritance' into st-refactor
| -rw-r--r-- | common/Error.hpp | 10 | ||||
| -rw-r--r-- | common/accel_classic.cpp | 21 | ||||
| -rw-r--r-- | common/accel_linear.cpp | 21 | ||||
| -rw-r--r-- | common/accel_logarithmic.cpp | 21 | ||||
| -rw-r--r-- | common/accel_natural.cpp | 23 | ||||
| -rw-r--r-- | common/accel_noaccel.cpp | 15 | ||||
| -rw-r--r-- | common/accel_power.cpp | 24 | ||||
| -rw-r--r-- | common/accel_sigmoid.cpp | 21 | ||||
| -rw-r--r-- | common/accel_types.hpp | 130 | ||||
| -rw-r--r-- | common/common.vcxitems | 11 | ||||
| -rw-r--r-- | common/rawaccel-userspace.hpp | 46 | ||||
| -rw-r--r-- | common/rawaccel.hpp | 363 | ||||
| -rw-r--r-- | console/console.cpp | 4 | ||||
| -rw-r--r-- | driver/driver.cpp | 26 | ||||
| -rw-r--r-- | grapher/Form1.cs | 4 | ||||
| -rw-r--r-- | wrapper/wrapper.cpp | 4 | ||||
| -rw-r--r-- | wrapper/wrapper.hpp | 38 |
17 files changed, 570 insertions, 212 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/accel_classic.cpp b/common/accel_classic.cpp new file mode 100644 index 0000000..323cd3b --- /dev/null +++ b/common/accel_classic.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_classic::accel_classic(accel_args args) + : accel_implentation(args) {} + + inline double accel_classic::accelerate(double speed) { + //f(x) = (mx)^k + return pow(curve_constant_one * speed, curve_constant_two); + } + + inline void accel_classic::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_linear.cpp b/common/accel_linear.cpp new file mode 100644 index 0000000..307e33e --- /dev/null +++ b/common/accel_linear.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_linear::accel_linear(accel_args args) + : accel_implentation(args) {} + + inline double accel_linear::accelerate(double speed) { + //f(x) = mx + return curve_constant_one * speed; + } + + inline void accel_linear::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("limit must be greater than 1"); + } +} diff --git a/common/accel_logarithmic.cpp b/common/accel_logarithmic.cpp new file mode 100644 index 0000000..64808a1 --- /dev/null +++ b/common/accel_logarithmic.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_logarithmic::accel_logarithmic(accel_args args) + : accel_implentation(args) {} + + inline double accel_logarithmic::accelerate(double speed) { + //f(x) = log(m*x+1) + return log(speed * curve_constant_one + 1); + } + + inline void accel_logarithmic::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_natural.cpp b/common/accel_natural.cpp new file mode 100644 index 0000000..c6f14b4 --- /dev/null +++ b/common/accel_natural.cpp @@ -0,0 +1,23 @@ + +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_natural::accel_natural(accel_args args) + : accel_implentation(args) + { curve_constant_one /= curve_constant_two; } + + inline double accel_natural::accelerate(double speed) { + // f(x) = k(1-e^(-mx)) + return curve_constant_two - (curve_constant_two * exp(-curve_constant_one * speed));; + } + + inline void accel_natural::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_noaccel.cpp b/common/accel_noaccel.cpp new file mode 100644 index 0000000..fce5dd4 --- /dev/null +++ b/common/accel_noaccel.cpp @@ -0,0 +1,15 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_noaccel::accel_noaccel(accel_args args) + : accel_implentation(args) {} + + inline double accel_noaccel::accelerate(double speed) { return 0; } + + inline void accel_noaccel::verify(accel_args args) { } +} diff --git a/common/accel_power.cpp b/common/accel_power.cpp new file mode 100644 index 0000000..f104554 --- /dev/null +++ b/common/accel_power.cpp @@ -0,0 +1,24 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_power::accel_power(accel_args args) + : accel_implentation(args) + { curve_constant_two++; } + + inline double accel_power::accelerate(double speed) { + // f(x) = (mx)^k - 1 + // The subtraction of 1 occurs 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 * curve_constant_one, curve_constant_two) - 1; + } + + inline void accel_power::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 0) error("exponent must be greater than 0"); + } +} diff --git a/common/accel_sigmoid.cpp b/common/accel_sigmoid.cpp new file mode 100644 index 0000000..d3b8ab7 --- /dev/null +++ b/common/accel_sigmoid.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +#include "accel_types.hpp" + +namespace rawaccel { + inline accel_sigmoid::accel_sigmoid(accel_args args) + : accel_implentation(args) {} + + inline double accel_sigmoid::accelerate(double speed) { + //f(x) = k/(1+e^(-m(c-x))) + return curve_constant_two / (exp(-curve_constant_one * (speed - curve_constant_three)) + 1); + } + + inline void accel_sigmoid::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_types.hpp b/common/accel_types.hpp new file mode 100644 index 0000000..15f5a50 --- /dev/null +++ b/common/accel_types.hpp @@ -0,0 +1,130 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> + +namespace rawaccel { + +// Error throwing calls std libraries which are unavailable in kernel mode. +#ifdef _KERNEL_MODE + inline void error(const char*) {} +#else + void error(const char* s); +#endif + + using milliseconds = double; + + /// <summary> Struct to hold arguments for an acceleration function. </summary> + struct accel_args { + milliseconds time_min = 0.4; + double offset = 0; + double accel = 0; + double lim_exp = 2; + double midpoint = 0; + }; + + /// <summary> + /// Struct to hold acceleration curve implementation details. + /// </summary> + /// <typeparam name="T">Type of acceleration.</typeparam> + template <typename T> + struct accel_implentation { + + /// <summary> First constant for use in acceleration curves. Generally, the acceleration ramp rate.</summary> + double curve_constant_one = 0; + + /// <summary> Second constant for use in acceleration curves. Generally, the limit or exponent in the curve. </summary> + double curve_constant_two = 0; + + /// <summary> Third constant for use in acceleration curves. The midpoint in sigmoid mode. </summary> + double curve_constant_three = 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(accel_args args) + { + curve_constant_one = args.accel; + curve_constant_two = args.lim_exp - 1; + curve_constant_three = 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(accel_args 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"); + } + + /// <summary> + /// + /// </summary> + /// <returns></returns> + accel_implentation() = default; + }; + + /// <summary> Struct to hold linear acceleration implementation. </summary> + struct accel_linear : accel_implentation<accel_linear> { + accel_linear(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// <summary> Struct to hold "classic" (linear raised to power) acceleration implementation. </summary> + struct accel_classic : accel_implentation<accel_classic> { + accel_classic(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// <summary> Struct to hold "natural" (vanishing difference) acceleration implementation. </summary> + struct accel_natural : accel_implentation<accel_natural> { + accel_natural(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// <summary> Struct to hold logarithmic acceleration implementation. </summary> + struct accel_logarithmic : accel_implentation<accel_logarithmic> { + accel_logarithmic(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// <summary> Struct to hold sigmoid (s-shaped) acceleration implementation. </summary> + struct accel_sigmoid : accel_implentation<accel_sigmoid> { + accel_sigmoid(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// <summary> Struct to hold power (non-additive) acceleration implementation. </summary> + struct accel_power : accel_implentation<accel_power> { + accel_power(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// <summary> Struct to hold acceleration implementation which applies no acceleration. </summary> + struct accel_noaccel : accel_implentation<accel_noaccel> { + accel_noaccel(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + +} diff --git a/common/common.vcxitems b/common/common.vcxitems index f60f78a..f33d8e1 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -14,9 +14,20 @@ <ProjectCapability Include="SourceItemsFromImports" /> </ItemGroup> <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)accel_types.hpp" /> + <ClInclude Include="$(MSBuildThisFileDirectory)Error.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-userspace.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)x64-util.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)vec2.h" /> </ItemGroup> + <ItemGroup> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_classic.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_linear.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_logarithmic.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_natural.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_noaccel.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_power.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)accel_sigmoid.cpp" /> + </ItemGroup> </Project>
\ No newline at end of file diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index db50b35..3e8886f 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -16,10 +16,8 @@ void error(const char* s) { throw std::domain_error(s); } -variables parse(int argc, char** argv) { - double degrees = 0; - vec2d sens = { 1, 1 }; - accel_function::args_t accel_args{}; +mouse_modifier parse(int argc, char** argv) { + modifier_args modifier_args{}; auto make_opt_vec = [](vec2d& v, auto first_flag, auto... rest) { return clipp::option(first_flag, rest...) & ( @@ -40,64 +38,64 @@ variables parse(int argc, char** argv) { }; // default options - auto opt_sens = "sensitivity (default = 1)" % make_opt_vec(sens, "sens"); + auto opt_sens = "sensitivity (default = 1)" % make_opt_vec(modifier_args.sens, "sens"); auto opt_rot = "counter-clockwise rotation (default = 0)" % ( clipp::option("rotate") & - clipp::number("degrees", degrees) + clipp::number("degrees", modifier_args.degrees) ); // mode-independent accel options auto opt_weight = "accel multiplier (default = 1)" % - make_opt_vec(accel_args.weight, "weight"); + make_opt_vec(modifier_args.acc_fn_args.weight, "weight"); auto opt_offset = "speed (dots/ms) where accel kicks in (default = 0)" % ( - clipp::option("offset") & clipp::number("speed", accel_args.offset) + clipp::option("offset") & clipp::number("speed", modifier_args.acc_fn_args.acc_args.offset) ); auto opt_cap = "accel scale cap (default = 9)" % - make_opt_vec(accel_args.cap, "cap"); + make_opt_vec(modifier_args.acc_fn_args.cap, "cap"); auto opt_tmin = "minimum time between polls (default = 0.4)" % ( clipp::option("tmin") & - clipp::number("ms", accel_args.time_min) + clipp::number("ms", modifier_args.acc_fn_args.acc_args.time_min) ); - auto accel_var = (clipp::required("accel") & clipp::number("num", accel_args.accel)) % "ramp rate"; - auto limit_var = (clipp::required("limit") & clipp::number("scale", accel_args.lim_exp)) % "limit"; + auto accel_var = (clipp::required("accel") & clipp::number("num", modifier_args.acc_fn_args.acc_args.accel)) % "ramp rate"; + auto limit_var = (clipp::required("limit") & clipp::number("scale", modifier_args.acc_fn_args.acc_args.lim_exp)) % "limit"; // modes auto noaccel_mode = "no-accel mode" % ( - clipp::command("off", "noaccel").set(accel_args.accel_mode, mode::noaccel) + clipp::command("off", "noaccel").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_noaccel>) ); auto lin_mode = "linear accel mode:" % ( - clipp::command("linear").set(accel_args.accel_mode, mode::linear), + clipp::command("linear").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_linear>), accel_var ); auto classic_mode = "classic accel mode:" % ( - clipp::command("classic").set(accel_args.accel_mode, mode::classic), + clipp::command("classic").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_classic>), accel_var, - (clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent" + (clipp::required("exponent") & clipp::number("num", modifier_args.acc_fn_args.acc_args.lim_exp)) % "exponent" ); auto nat_mode = "natural accel mode:" % ( - clipp::command("natural").set(accel_args.accel_mode, mode::natural), + clipp::command("natural").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_natural>), accel_var, limit_var ); auto log_mode = "logarithmic accel mode:" % ( - clipp::command("logarithmic").set(accel_args.accel_mode, mode::logarithmic), + clipp::command("logarithmic").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_logarithmic>), accel_var ); auto sig_mode = "sigmoid accel mode:" % ( - clipp::command("sigmoid").set(accel_args.accel_mode, mode::sigmoid), + clipp::command("sigmoid").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_sigmoid>), accel_var, limit_var, - (clipp::required("midpoint") & clipp::number("speed", accel_args.midpoint)) % "midpoint" + (clipp::required("midpoint") & clipp::number("speed", modifier_args.acc_fn_args.acc_args.midpoint)) % "midpoint" ); auto pow_mode = "power accel mode:" % ( - clipp::command("power").set(accel_args.accel_mode, mode::power) >> [&] { accel_args.accel = 1; }, - (clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent", - (clipp::option("scale") & clipp::number("num", accel_args.accel)) % "scale factor" + clipp::command("power").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id<accel_power>) >> [&] { modifier_args.acc_fn_args.acc_args.accel = 1; }, + (clipp::required("exponent") & clipp::number("num", modifier_args.acc_fn_args.acc_args.lim_exp)) % "exponent", + (clipp::option("scale") & clipp::number("num", modifier_args.acc_fn_args.acc_args.accel)) % "scale factor" ); auto accel_mode_exclusive = (lin_mode | classic_mode | nat_mode | log_mode | sig_mode | pow_mode); @@ -121,7 +119,7 @@ variables parse(int argc, char** argv) { std::exit(0); } - return variables(-degrees, sens, accel_args); + return mouse_modifier(modifier_args); } } // rawaccel diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 095af76..b480e87 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -5,176 +5,239 @@ #include "vec2.h" #include "x64-util.hpp" +#include "external/tagged-union-single.h" + +#include "accel_linear.cpp" +#include "accel_classic.cpp" +#include "accel_natural.cpp" +#include "accel_logarithmic.cpp" +#include "accel_sigmoid.cpp" +#include "accel_power.cpp" +#include "accel_noaccel.cpp" + +namespace rawaccel { + + /// <summary> Struct to hold vector rotation details. </summary> + struct rotator { + + /// <summary> Rotational vector, which points in the direction of the post-rotation positive x axis. </summary> + vec2d rot_vec = { 1, 0 }; + + /// <summary> + /// Rotates given input vector according to struct's rotational vector. + /// </summary> + /// <param name="input">Input vector to be rotated</param> + /// <returns>2d vector of rotated input.</returns> + 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() = default; + }; + + /// <summary> Struct to hold clamp (min and max) details for acceleration application </summary> + struct accel_scale_clamp { + double lo = 0; + double hi = 9; + + /// <summary> + /// Clamps given input to min at lo, max at hi. + /// </summary> + /// <param name="scale">Double to be clamped</param> + /// <returns>Clamped input as double</returns> + 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; + } + + if (cap < 1) { + // assume negative accel + lo = cap; + hi = 1; + } + else hi = cap; + } -namespace rawaccel { + accel_scale_clamp() = default; + }; -enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; + /// <summary> Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. </summary> + using accel_implementation_t = tagged_union<accel_linear, accel_classic, accel_natural, accel_logarithmic, accel_sigmoid, accel_power, accel_noaccel>; -struct rotator { - vec2d rot_vec = { 1, 0 }; + struct accel_fn_args { + accel_args acc_args = accel_args{}; + int accel_mode = 0; + milliseconds time_min = 0.4; + vec2d weight = { 1, 1 }; + vec2d cap = { 0, 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 - }; - } + /// <summary> Struct for holding acceleration application details. </summary> + struct accel_function { - rotator(double degrees) { - double rads = degrees * M_PI / 180; - rot_vec = { cos(rads), sin(rads) }; - } + /* + 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. + */ + /// <summary> The minimum time period for one mouse movement. </summary> + milliseconds time_min = 0.4; - rotator() = default; -}; + /// <summary> The offset past which acceleration is applied. </summary> + double speed_offset = 0; -struct accel_scale_clamp { - double lo = 0; - double hi = 9; + /// <summary> The acceleration implementation (i.e. curve) </summary> + accel_implementation_t accel; - inline double operator()(double scale) const { - return clampsd(scale, lo, hi); - } + /// <summary> The weight of acceleration applied in {x, y} dimensions. </summary> + vec2d weight = { 1, 1 }; - accel_scale_clamp(double cap) : accel_scale_clamp() { - if (cap <= 0) { - // use default, effectively uncapped accel - return; + /// <summary> The object which sets a min and max for the acceleration scale. </summary> + vec2<accel_scale_clamp> clamp; + + accel_function(accel_fn_args args) { + accel.tag = args.accel_mode; + accel.visit([&](auto& a){ a = {args.acc_args}; }); + + // Verification is performed by the accel_implementation object + // and therefore must occur after the object has been instantiated + verify(args.acc_args); + + time_min = args.time_min; + speed_offset = args.acc_args.offset; + weight = args.weight; + clamp.x = accel_scale_clamp(args.cap.x); + clamp.y = accel_scale_clamp(args.cap.y); } - if (cap < 1) { - // assume negative accel - lo = cap; - hi = 1; + /// <summary> + /// Applies mouse acceleration to a given speed, via visitor function to accel_implementation_t + /// </summary> + /// <param name="speed">Speed from which to determine acceleration</param> + /// <returns>Acceleration as a ratio magnitudes, as a double</returns> + double apply(double speed) const { + return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); } - else hi = cap; - } - - accel_scale_clamp() = default; -}; - -void error(const char*); - -struct accel_function { - using milliseconds = double; - - /* - 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; - - // accel ramp rate - double b = 0; - - // the limit for natural and sigmoid modes - // or the exponent for classic and power modes - double k = 1; - - vec2d weight = { 1, 1 }; - vec2<accel_scale_clamp> clamp; - - 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 = 0; - - switch (accel_mode) { - case mode::linear: accel_val = b * speed; - break; - case mode::classic: accel_val = pow(b * speed, k); - break; - case mode::natural: accel_val = k - (k * exp(-b * speed)); - break; - case mode::logarithmic: accel_val = log(speed * b + 1); - break; - case mode::sigmoid: accel_val = k / (exp(-b * (speed - m)) + 1); - break; - case mode::power: accel_val = (speed_offset > 0 && speed < 1) ? 0 : pow(speed*b, k) - 1; - break; - default: - break; + + /// <summary> + /// Verifies acceleration arguments, via visitor function to accel_implementation_t + /// </summary> + /// <param name="args">Arguments to be verified</param> + void verify(accel_args args) const { + return accel.visit([=](auto accel_t) { accel_t.verify(args); }); } - double scale_x = weight.x * accel_val + 1; - double scale_y = weight.y * accel_val + 1; + /// <summary> + /// Applies weighted acceleration to given input for given time period. + /// </summary> + /// <param name="input">2d vector of {x, y} mouse movement to be accelerated</param> + /// <param name="time">Time period over which input movement was accumulated</param> + /// <returns></returns> + inline vec2d operator()(const vec2d& input, milliseconds time) 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) + }; + } - return { - input.x * clamp.x(scale_x), - input.y * clamp.y(scale_y) - }; - } + accel_function() = default; + }; - 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 modifier_args + { + double degrees = 0; + vec2d sens = { 1, 1 }; + accel_fn_args acc_fn_args = accel_fn_args{}; }; - accel_function(args_t args) { - // Preconditions to guard against division by zero and - // ensure the C math functions can not return NaN or -Inf. - 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"); - if (args.lim_exp <= 1) { - if (args.accel_mode == mode::classic) error("exponent must be greater than 1"); - if (args.accel_mode == mode::power) { if (args.lim_exp <=0 ) error("exponent must be greater than 0"); } - else error("limit must be greater than 1"); + /// <summary> Struct to hold variables and methods for modifying mouse input </summary> + struct mouse_modifier { + bool apply_rotate = false; + bool apply_accel = false; + rotator rotate; + accel_function accel_fn; + vec2d sensitivity = { 1, 1 }; + + mouse_modifier(modifier_args args) + : accel_fn(args.acc_fn_args) + { + apply_rotate = args.degrees != 0; + if (apply_rotate) rotate = rotator(args.degrees); + else rotate = rotator(); + + apply_accel = (args.acc_fn_args.accel_mode != 0 && + args.acc_fn_args.accel_mode != accel_implementation_t::id<accel_noaccel>); + + if (args.sens.x == 0) args.sens.x = 1; + if (args.sens.y == 0) args.sens.y = 1; + sensitivity = args.sens; } - 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); - } - - 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, accel_function::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; + /// <summary> + /// Applies modification without acceleration. + /// </summary> + /// <param name="input">Input to be modified.</param> + /// <returns>2d vector of modified input.</returns> + inline vec2d modify_without_accel(vec2d input) + { + if (apply_rotate) + { + input = rotate(input); + } + + input.x *= sensitivity.x; + input.y *= sensitivity.y; + + return input; + } - if (sens.x == 0) sens.x = 1; - if (sens.y == 0) sens.y = 1; - sensitivity = sens; - } + /// <summary> + /// Applies modification, including acceleration. + /// </summary> + /// <param name="input">Input to be modified</param> + /// <param name="time">Time period for determining acceleration.</param> + /// <returns>2d vector with modified input.</returns> + inline vec2d modify_with_accel(vec2d input, milliseconds time) + { + if (apply_rotate) + { + input = rotate(input); + } + + if (apply_accel) + { + input = accel_fn(input, time); + } + + input.x *= sensitivity.x; + input.y *= sensitivity.y; + + return input; + } - variables() = default; -}; + mouse_modifier() = default; + }; -} // rawaccel +} // rawaccel
\ No newline at end of file diff --git a/console/console.cpp b/console/console.cpp index 6606cac..490051c 100644 --- a/console/console.cpp +++ b/console/console.cpp @@ -9,7 +9,7 @@ namespace ra = rawaccel; -void write(ra::variables vars) { +void write(ra::mouse_modifier vars) { HANDLE ra_handle = INVALID_HANDLE_VALUE; ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0); @@ -24,7 +24,7 @@ void write(ra::variables vars) { ra_handle, RA_WRITE, &vars, - sizeof(ra::variables), + sizeof(ra::mouse_modifier), NULL, // output buffer 0, // output buffer size &dummy, // bytes returned diff --git a/driver/driver.cpp b/driver/driver.cpp index e77ac5f..1f9cebd 100644 --- a/driver/driver.cpp +++ b/driver/driver.cpp @@ -15,7 +15,7 @@ using milliseconds = double; struct { milliseconds tick_interval = 0; // set in DriverEntry - ra::variables vars; + ra::mouse_modifier modifier; } global; VOID @@ -69,25 +69,25 @@ Arguments: static_cast<double>(it->LastY) }; - if (global.vars.apply_rotate) { - input = global.vars.rotate(input); - } - - if (global.vars.apply_accel && local_apply_accel) { + if (global.modifier.apply_accel && local_apply_accel) { auto now = KeQueryPerformanceCounter(NULL).QuadPart; auto ticks = now - devExt->counter.QuadPart; devExt->counter.QuadPart = now; milliseconds time = ticks * global.tick_interval; - if (time < global.vars.accel_fn.time_min) { + if (time < global.modifier.accel_fn.time_min) { DebugPrint(("RA time < min with %d ticks\n", ticks)); } - input = global.vars.accel_fn(input, time, global.vars.accel_mode); + input = global.modifier.modify_with_accel(input, time); + } + else + { + input = global.modifier.modify_without_accel(input); } - double result_x = input.x * global.vars.sensitivity.x + local_carry.x; - double result_y = input.y * global.vars.sensitivity.y + local_carry.y; + double result_x = input.x + local_carry.x; + double result_y = input.y + local_carry.y; LONG out_x = static_cast<LONG>(result_x); LONG out_y = static_cast<LONG>(result_y); @@ -154,7 +154,7 @@ Return Value: DebugPrint(("Ioctl received into filter control object.\n")); - if (InputBufferLength != sizeof(ra::variables)) { + if (InputBufferLength != sizeof(ra::mouse_modifier)) { DebugPrint(("Received unknown request of %u bytes\n", InputBufferLength)); // status maps to win32 error code 1784: ERROR_INVALID_USER_BUFFER WdfRequestComplete(Request, STATUS_INVALID_BUFFER_SIZE); @@ -163,7 +163,7 @@ Return Value: status = WdfRequestRetrieveInputBuffer( Request, - sizeof(ra::variables), + sizeof(ra::mouse_modifier), &input_buffer, &input_size ); @@ -175,7 +175,7 @@ Return Value: return; } - global.vars = *reinterpret_cast<ra::variables*>(input_buffer); + global.modifier = *reinterpret_cast<ra::mouse_modifier*>(input_buffer); WdfRequestComplete(Request, STATUS_SUCCESS); } diff --git a/grapher/Form1.cs b/grapher/Form1.cs index 1915b01..495640e 100644 --- a/grapher/Form1.cs +++ b/grapher/Form1.cs @@ -15,14 +15,14 @@ namespace grapher public RawAcceleration() { InitializeComponent(); - var managedAccel = new ManagedAccel(6, 0, 1, 0.025, 0); + var managedAccel = new ManagedAccel(5, 0, 0.3, 1.25, 15); var orderedPoints = new SortedDictionary<double, double>(); for (int i = 0; i < 100; i++) { for (int j = 0; j <= i; j++) { - var output = managedAccel.Accelerate(i, j, 1, 6); + var output = managedAccel.Accelerate(i, j, 1); var inMagnitude = Magnitude(i,j); var outMagnitude = Magnitude(output.Item1, output.Item2); diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index df3f796..c1cc570 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -5,10 +5,10 @@ using namespace rawaccel; using namespace System; -Tuple<double, double>^ ManagedAccel::Accelerate(int x, int y, double time, double mode) +Tuple<double, double>^ ManagedAccel::Accelerate(int x, int y, double time) { vec2d input_vec2d = {x, y}; - vec2d output = (*accel_instance)(input_vec2d, (accel_function::milliseconds)time, (rawaccel::mode)mode); + vec2d output = (*modifier_instance).modify_with_accel(input_vec2d, (milliseconds)time); return gcnew Tuple<double, double>(output.x, output.y); }
\ No newline at end of file diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 24bcadb..19b0987 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; @@ -9,44 +9,44 @@ using namespace System; public ref class ManagedAccel { protected: - accel_function* accel_instance; + mouse_modifier* modifier_instance; public: - ManagedAccel(accel_function* accel) - : accel_instance(accel) + ManagedAccel(mouse_modifier* accel) + : modifier_instance(accel) { } - ManagedAccel(double mode, double offset, double accel, double lim_exp, double midpoint) + ManagedAccel(int mode, double offset, double accel, double lim_exp, double midpoint) { - accel_function::args_t args{}; - args.accel = accel; - args.lim_exp = lim_exp; - args.midpoint = midpoint; - args.accel_mode = (rawaccel::mode)mode; - args.offset = offset; + modifier_args args{}; + args.acc_fn_args.acc_args.accel = accel; + args.acc_fn_args.acc_args.lim_exp = lim_exp; + args.acc_fn_args.acc_args.midpoint = midpoint; + args.acc_fn_args.accel_mode = mode; + args.acc_fn_args.acc_args.offset = offset; - accel_instance = new accel_function(args); + modifier_instance = new mouse_modifier(args); } virtual ~ManagedAccel() { - if (accel_instance != nullptr) + if (modifier_instance!= nullptr) { - delete accel_instance; + delete modifier_instance; } } !ManagedAccel() { - if (accel_instance != nullptr) + if (modifier_instance!= nullptr) { - delete accel_instance; + delete modifier_instance; } } - accel_function* GetInstance() + mouse_modifier* GetInstance() { - return accel_instance; + return modifier_instance; } - Tuple<double, double>^ Accelerate(int x, int y, double time, double mode); + Tuple<double, double>^ Accelerate(int x, int y, double time); };
\ No newline at end of file |