diff options
43 files changed, 654 insertions, 1122 deletions
diff --git a/common/accel-base.hpp b/common/accel-base.hpp index f280e3e..560c0b5 100644 --- a/common/accel-base.hpp +++ b/common/accel-base.hpp @@ -1,19 +1,5 @@ #pragma once -#include "vec2.h" - -void bad_arg(const char*); - -#ifndef _KERNEL_MODE - -#include "rawaccel-error.hpp" - -inline void bad_arg(const char* s) { - throw rawaccel::invalid_argument(s); -} - -#endif - namespace rawaccel { /// <summary> Struct to hold arguments for an acceleration function. </summary> @@ -24,55 +10,48 @@ namespace rawaccel { double exponent = 2; double midpoint = 0; double power_scale = 1; + double power_exp = 0.05; + double weight = 1; + double rate = 0; + double scale_cap = 0; double gain_cap = 0; - vec2d weight = { 1, 1 }; }; - /// <summary> - /// Struct to hold common acceleration curve implementation details. - /// </summary> - struct accel_base { + template <typename Func> + struct accel_val_base { + double offset = 0; + double weight = 1; + Func fn; - /// <summary> Coefficients applied to acceleration per axis.</summary> - vec2d weight = { 1, 1 }; + accel_val_base(const accel_args& args) : fn(args) {} - /// <summary> Generally, the acceleration ramp rate.</summary> - double speed_coeff = 0; + }; - accel_base(const accel_args& args) { - verify(args); + template <typename Func> + struct additive_accel : accel_val_base<Func> { - speed_coeff = args.accel; + additive_accel(const accel_args& args) : accel_val_base(args) { + offset = args.offset; weight = args.weight; } - /// <summary> - /// Default transformation of speed -> acceleration. - /// </summary> - inline double accelerate(double speed) const { - return speed_coeff * speed; + inline double operator()(double speed) const { + return 1 + fn(maxsd(speed - offset, 0)) * weight; } - /// <summary> - /// Default transformation of acceleration -> mouse input multipliers. - /// </summary> - inline vec2d scale(double accel_val) const { - return { - weight.x * accel_val + 1, - weight.y * accel_val + 1 - }; + }; + + template <typename Func> + struct nonadditive_accel : accel_val_base<Func> { + + nonadditive_accel(const accel_args& args) : accel_val_base(args) { + if (args.weight != 0) weight = args.weight; } - /// <summary> - /// Verifies arguments as valid. Errors if not. - /// </summary> - /// <param name="args">Arguments to verified.</param> - void verify(const accel_args& args) const { - if (args.accel < 0) bad_arg("accel can not be negative, use a negative weight to compensate"); - if (args.gain_cap > 0 && weight.x != weight.y) bad_arg("weight x and y values must be equal with a gain cap"); + inline double operator()(double speed) const { + return fn(speed) * weight; } - accel_base() = default; }; } diff --git a/common/accel-classic.hpp b/common/accel-classic.hpp index 0a380dd..4cc52ca 100644 --- a/common/accel-classic.hpp +++ b/common/accel-classic.hpp @@ -7,23 +7,20 @@ namespace rawaccel { /// <summary> Struct to hold "classic" (linear raised to power) acceleration implementation. </summary> - struct accel_classic : accel_base { - double exponent; + struct classic_impl { + double accel; + double power; - accel_classic(const accel_args& args) : accel_base(args) { - verify(args); + classic_impl(const accel_args& args) : + accel(args.accel), power(args.exponent - 1) + {} - exponent = args.exponent - 1; - } - - inline double accelerate(double speed) const { - //f(x) = (mx)^k - return pow(speed_coeff * speed, exponent); - } - - void verify(const accel_args& args) const { - if (args.exponent <= 1) bad_arg("exponent must be greater than 1"); + inline double operator()(double speed) const { + //f(x) = (mx)^(k-1) + return pow(accel * speed, power); } }; + + using accel_classic = additive_accel<classic_impl>; } diff --git a/common/accel-linear.hpp b/common/accel-linear.hpp index 5cbb7c6..a943594 100644 --- a/common/accel-linear.hpp +++ b/common/accel-linear.hpp @@ -5,10 +5,17 @@ namespace rawaccel { /// <summary> Struct to hold linear acceleration implementation. </summary> - struct accel_linear : accel_base { + struct linear_impl { + double accel; + + linear_impl(const accel_args& args) : accel(args.accel) {} - using accel_base::accel_base; + inline double operator()(double speed) const { + return accel * speed; + } }; + using accel_linear = additive_accel<linear_impl>; + } diff --git a/common/accel-logarithmic.hpp b/common/accel-logarithmic.hpp index 928eda9..c7991c7 100644 --- a/common/accel-logarithmic.hpp +++ b/common/accel-logarithmic.hpp @@ -7,14 +7,16 @@ namespace rawaccel { /// <summary> Struct to hold logarithmic acceleration implementation. </summary> - struct accel_logarithmic : accel_base { + struct logarithmic_impl { + double accel; - using accel_base::accel_base; + logarithmic_impl(const accel_args& args) : accel(args.accel) {} - inline double accelerate(double speed) const { + inline double operator()(double speed) const { //f(x) = log(m*x+1) - return log(speed_coeff * speed + 1); + return log(accel * speed + 1); } }; + using accel_logarithmic = additive_accel<logarithmic_impl>; } diff --git a/common/accel-natural.hpp b/common/accel-natural.hpp index 8f002e4..c7d0dcd 100644 --- a/common/accel-natural.hpp +++ b/common/accel-natural.hpp @@ -7,25 +7,23 @@ namespace rawaccel { /// <summary> Struct to hold "natural" (vanishing difference) acceleration implementation. </summary> - struct accel_natural : accel_base { - double limit = 1; - double midpoint = 0; - - accel_natural(const accel_args& args) : accel_base(args) { - verify(args); - - limit = args.limit - 1; - speed_coeff /= limit; + struct natural_impl { + double rate; + double limit; + + natural_impl(const accel_args& args) : + rate(args.accel), limit(args.limit - 1) + { + rate /= limit; } - inline double accelerate(double speed) const { + inline double operator()(double speed) const { // f(x) = k(1-e^(-mx)) - return limit - (limit * exp(-speed_coeff * speed)); + return limit - (limit * exp(-rate * speed)); } - void verify(const accel_args& args) const { - if (args.limit <= 1) bad_arg("limit must be greater than 1"); - } }; + using accel_natural = additive_accel<natural_impl>; + } diff --git a/common/accel-naturalgain.hpp b/common/accel-naturalgain.hpp index 95c0be2..646b2bb 100644 --- a/common/accel-naturalgain.hpp +++ b/common/accel-naturalgain.hpp @@ -2,31 +2,22 @@ #include <math.h> -#include "accel-base.hpp" +#include "accel-natural.hpp" namespace rawaccel { /// <summary> Struct to hold "natural" (vanishing difference) gain implementation. </summary> - struct accel_naturalgain : accel_base { - double limit = 1; - double midpoint = 0; + struct naturalgain_impl : natural_impl { - accel_naturalgain(const accel_args& args) : accel_base(args) { - verify(args); + using natural_impl::natural_impl; - limit = args.limit - 1; - speed_coeff /= limit; - } - - inline double accelerate(double speed) const { + inline double operator()(double speed) const { // f(x) = k((e^(-mx)-1)/mx + 1) - double scaled_speed = speed_coeff * speed; + double scaled_speed = rate * speed; return limit * (((exp(-scaled_speed) - 1) / scaled_speed) + 1); } - - void verify(const accel_args& args) const { - if (args.limit <= 1) bad_arg("limit must be greater than 1"); - } + }; + using accel_naturalgain = additive_accel<naturalgain_impl>; } diff --git a/common/accel-noaccel.hpp b/common/accel-noaccel.hpp index b7f730b..ae6f5f8 100644 --- a/common/accel-noaccel.hpp +++ b/common/accel-noaccel.hpp @@ -5,10 +5,13 @@ namespace rawaccel { /// <summary> Struct to hold acceleration implementation which applies no acceleration. </summary> - struct accel_noaccel : accel_base { + struct accel_noaccel { - accel_noaccel(const accel_args&) : accel_base() {} + accel_noaccel(const accel_args&) {} + accel_noaccel() = default; + inline double operator()(double) const { return 1; } + }; } diff --git a/common/accel-power.hpp b/common/accel-power.hpp index 0d5e265..1abfdd1 100644 --- a/common/accel-power.hpp +++ b/common/accel-power.hpp @@ -7,35 +7,20 @@ namespace rawaccel { /// <summary> Struct to hold power (non-additive) acceleration implementation. </summary> - struct accel_power : accel_base { + struct power_impl { + double scale; double exponent; - double offset; - accel_power(const accel_args& args) { - verify(args); + power_impl(const accel_args& args) : + scale(args.power_scale), exponent(args.power_exp) + {} - weight = args.weight; - speed_coeff = args.power_scale; - exponent = args.exponent; - offset = args.offset; - } - - inline double accelerate(double speed) const { + inline double operator()(double speed) const { // f(x) = (mx)^k - return (offset > 0 && speed < 1) ? 1 : pow(speed * speed_coeff, exponent); - } - - inline vec2d scale(double accel_val) const { - return { - weight.x * accel_val, - weight.y * accel_val - }; - } - - void verify(const accel_args& args) const { - if (args.power_scale <= 0) bad_arg("scale must be positive"); - if (args.exponent <= 0) bad_arg("exponent must be greater than 0"); + return pow(speed * scale, exponent); } }; + using accel_power = nonadditive_accel<power_impl>; + } diff --git a/common/accel-sigmoid.hpp b/common/accel-sigmoid.hpp index dc2066d..c8112ee 100644 --- a/common/accel-sigmoid.hpp +++ b/common/accel-sigmoid.hpp @@ -7,26 +7,22 @@ namespace rawaccel { /// <summary> Struct to hold sigmoid (s-shaped) acceleration implementation. </summary> - struct accel_sigmoid : accel_base { - double limit = 1; - double midpoint = 0; + struct sigmoid_impl { + double rate; + double limit; + double midpoint; - accel_sigmoid(const accel_args& args) : accel_base(args) { - verify(args); + sigmoid_impl(const accel_args& args) : + rate(args.accel), limit(args.limit - 1), midpoint(args.midpoint) + {} - limit = args.limit - 1; - midpoint = args.midpoint; - } - - inline double accelerate(double speed) const { + inline double operator()(double speed) const { //f(x) = k/(1+e^(-m(x-c))) - return limit / (exp(-speed_coeff * (speed - midpoint)) + 1); + return limit / (exp(-rate * (speed - midpoint)) + 1); } - void verify(const accel_args& args) const { - if (args.limit <= 1) bad_arg("exponent must be greater than 1"); - if (args.midpoint < 0) bad_arg("midpoint must not be negative"); - } }; + using accel_sigmoid = additive_accel<sigmoid_impl>; + } diff --git a/common/accel-sigmoidgain.hpp b/common/accel-sigmoidgain.hpp index 0a2e54d..99bb146 100644 --- a/common/accel-sigmoidgain.hpp +++ b/common/accel-sigmoidgain.hpp @@ -7,31 +7,27 @@ namespace rawaccel { /// <summary> Struct to hold sigmoid (s-shaped) gain implementation. </summary> - struct accel_sigmoidgain : accel_base { - double limit = 1; - double midpoint = 0; - double additive_constant = 0; - double integration_constant = 0; - - accel_sigmoidgain(const accel_args& args) : accel_base(args) { - verify(args); - - limit = args.limit - 1; - midpoint = args.midpoint; - additive_constant = exp(speed_coeff*midpoint); + struct sigmoidgain_impl { + double rate; + double limit; + double additive_constant; + double integration_constant; + + sigmoidgain_impl(const accel_args& args) : + rate(args.rate), limit(args.limit - 1) + { + additive_constant = exp(rate * args.midpoint); integration_constant = log(1 + additive_constant); } - inline double accelerate(double speed) const { + inline double operator()(double speed) const { //f(x) = k/(1+e^(-m(c-x))) - double scaled_speed = speed_coeff * speed; + double scaled_speed = rate * speed; return limit * ((log(additive_constant+exp(scaled_speed)) - integration_constant)/scaled_speed); } - void verify(const accel_args& args) const { - if (args.limit <= 1) bad_arg("exponent must be greater than 1"); - if (args.midpoint < 0) bad_arg("midpoint must not be negative"); - } }; + using accel_sigmoidgain = additive_accel<sigmoidgain_impl>; + } diff --git a/common/common.vcxitems b/common/common.vcxitems index 2e9265c..52d4f8a 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -26,8 +26,8 @@ <ClInclude Include="$(MSBuildThisFileDirectory)accel-sigmoidgain.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-error.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io.hpp" /> + <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-settings.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" /> - <ClInclude Include="$(MSBuildThisFileDirectory)tagged-union-single.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)x64-util.hpp" /> <ClInclude Include="$(MSBuildThisFileDirectory)vec2.h" /> </ItemGroup> diff --git a/common/rawaccel-io.hpp b/common/rawaccel-io.hpp index 7f55392..74e2d1e 100644 --- a/common/rawaccel-io.hpp +++ b/common/rawaccel-io.hpp @@ -5,7 +5,8 @@ #define NOMINMAX #include <Windows.h> -#include "rawaccel.hpp" +#include "rawaccel-settings.h" +#include "rawaccel-error.hpp" #define RA_READ CTL_CODE(0x8888, 0x888, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define RA_WRITE CTL_CODE(0x8888, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS) @@ -15,7 +16,7 @@ namespace rawaccel { - mouse_modifier read() { + settings read() { HANDLE ra_handle = INVALID_HANDLE_VALUE; ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0); @@ -24,7 +25,7 @@ namespace rawaccel { throw install_error(); } - mouse_modifier mod; + settings args; DWORD dummy; BOOL success = DeviceIoControl( @@ -32,8 +33,8 @@ namespace rawaccel { RA_READ, NULL, // input buffer 0, // input buffer size - &mod, // output buffer - sizeof(mouse_modifier), // output buffer size + &args, // output buffer + sizeof(settings), // output buffer size &dummy, // bytes returned NULL // overlapped structure ); @@ -44,11 +45,11 @@ namespace rawaccel { throw std::system_error(GetLastError(), std::system_category(), "DeviceIoControl failed"); } - return mod; + return args; } - void write(mouse_modifier mod) { + void write(const settings& args) { HANDLE ra_handle = INVALID_HANDLE_VALUE; ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0); @@ -62,12 +63,12 @@ namespace rawaccel { BOOL success = DeviceIoControl( ra_handle, RA_WRITE, - &mod, // input buffer - sizeof(mouse_modifier), // input buffer size - NULL, // output buffer - 0, // output buffer size - &dummy, // bytes returned - NULL // overlapped structure + const_cast<settings*>(&args), // input buffer + sizeof(settings), // input buffer size + NULL, // output buffer + 0, // output buffer size + &dummy, // bytes returned + NULL // overlapped structure ); CloseHandle(ra_handle); diff --git a/common/rawaccel-settings.h b/common/rawaccel-settings.h new file mode 100644 index 0000000..b9ff946 --- /dev/null +++ b/common/rawaccel-settings.h @@ -0,0 +1,21 @@ +#pragma once + +#include "vec2.h" +#include "accel-base.hpp" + +namespace rawaccel { + + enum class accel_mode { + linear, classic, natural, logarithmic, sigmoid, naturalgain, sigmoidgain, power, noaccel + }; + + struct settings { + double degrees_rotation = 0; + bool combine_mags = true; + vec2<accel_mode> modes = { accel_mode::noaccel, accel_mode::noaccel }; + vec2<accel_args> argsv; + vec2d sens = { 1, 1 }; + double time_min = 0.4; + }; + +} diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 23a8214..d3a2a03 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -3,8 +3,8 @@ #define _USE_MATH_DEFINES #include <math.h> +#include "rawaccel-settings.h" #include "x64-util.hpp" -#include "tagged-union-single.h" #include "accel-linear.hpp" #include "accel-classic.hpp" @@ -31,7 +31,7 @@ namespace rawaccel { /// </summary> /// <param name="input">Input vector to be rotated</param> /// <returns>2d vector of rotated input.</returns> - inline vec2d operator()(const vec2d& input) const { + 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 @@ -60,7 +60,7 @@ namespace rawaccel { return clampsd(scale, lo, hi); } - accel_scale_clamp(double cap) : accel_scale_clamp() { + accel_scale_clamp(double cap) { if (cap <= 0) { // use default, effectively uncapped accel return; @@ -76,9 +76,53 @@ namespace rawaccel { accel_scale_clamp() = default; }; + + template <typename Visitor, typename Variant> + 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::logarithmic: return vis(var.u.logarithmic); + case accel_mode::sigmoid: return vis(var.u.sigmoid); + case accel_mode::naturalgain: return vis(var.u.naturalgain); + case accel_mode::sigmoidgain: return vis(var.u.sigmoidgain); + case accel_mode::power: return vis(var.u.power); + default: return vis(var.u.noaccel); + } + } + + struct accel_variant { + accel_mode tag = accel_mode::noaccel; + + union union_t { + accel_linear linear; + accel_classic classic; + accel_natural natural; + accel_logarithmic logarithmic; + accel_sigmoid sigmoid; + accel_naturalgain naturalgain; + accel_sigmoidgain sigmoidgain; + accel_power power; + accel_noaccel noaccel = {}; + } u = {}; + + accel_variant(const accel_args& args, accel_mode mode) : + tag(mode) + { + visit_accel([&](auto& impl) { + impl = { args }; + }, *this); + } - /// <summary> Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. </summary> - using accel_impl_t = tagged_union<accel_linear, accel_classic, accel_natural, accel_logarithmic, accel_sigmoid, accel_power, accel_naturalgain, accel_sigmoidgain, accel_noaccel>; + inline double apply(double speed) const { + return visit_accel([=](auto&& impl) { + return impl(speed); + }, *this); + } + + accel_variant() = default; + }; /// <summary> Struct to hold information about applying a gain cap. </summary> struct velocity_gain_cap { @@ -92,18 +136,14 @@ namespace rawaccel { // <summary> The intercept for the line with above slope to give continuous velocity function </summary> double intercept = 0; - // <summary> Whether or not velocity gain cap is enabled </summary> - bool cap_gain_enabled = false; - /// <summary> /// 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. /// </summary> /// <param name="speed"> The speed at which velocity gain cap will kick in </param> - /// <param name="offset"> The offset applied in accel calculations </param> - /// <param name="accel"> The accel implementation used in the containing accel_fn </param> - velocity_gain_cap(double speed, double offset, accel_impl_t accel) + /// <param name="accel"> The accel implementation used in the containing accel_variant </param> + velocity_gain_cap(double speed, const accel_variant& accel) { if (speed <= 0) return; @@ -115,18 +155,9 @@ namespace rawaccel { // Return if by glitch or strange values the difference in points is 0. if (speed_diff == 0) return; - cap_gain_enabled = true; - // Find the corresponding output velocities for the two points. - // Subtract offset for acceleration, like in accel_fn() - double out_first = accel.visit([=](auto&& impl) { - double accel_val = impl.accelerate(speed-offset); - return impl.scale(accel_val); - }).x * speed; - double out_second = accel.visit([=](auto&& impl) { - double accel_val = impl.accelerate(speed_second-offset); - return impl.scale(accel_val); - }).x * speed_second; + 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; @@ -141,7 +172,7 @@ namespace rawaccel { /// </summary> /// <param name="speed"> Speed to be capped </param> /// <returns> Scale multiplier for input </returns> - inline double operator()(double speed) const { + inline double apply(double speed) const { return slope + intercept / speed; } @@ -151,166 +182,97 @@ namespace rawaccel { /// <param name="speed"> Speed to check against threshold. </param> /// <returns> Whether gain cap should be applied. </returns> inline bool should_apply(double speed) const { - return cap_gain_enabled && speed > threshold; + return threshold > 0 && speed > threshold; } velocity_gain_cap() = default; }; - struct accel_fn_args { - accel_args acc_args; - int accel_mode = accel_impl_t::id<accel_noaccel>; - milliseconds time_min = 0.4; - vec2d cap = { 0, 0 }; - }; - - /// <summary> Struct for holding acceleration application details. </summary> - 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. - */ - /// <summary> The minimum time period for one mouse movement. </summary> - milliseconds time_min = 0.4; - - /// <summary> The offset past which acceleration is applied. </summary> - double speed_offset = 0; + struct accelerator { + accel_variant accel; + velocity_gain_cap gain_cap; + accel_scale_clamp clamp; - /// <summary> The acceleration implementation (i.e. curve) </summary> - accel_impl_t accel; + accelerator(const accel_args& args, accel_mode mode) : + accel(args, mode), gain_cap(args.gain_cap, accel), clamp(args.scale_cap) + {} - /// <summary> The object which sets a min and max for the acceleration scale. </summary> - vec2<accel_scale_clamp> clamp; - - velocity_gain_cap gain_cap = velocity_gain_cap(); - - accel_args impl_args; - - accel_function(const accel_fn_args& args) { - if (args.time_min <= 0) bad_arg("min time must be positive"); - if (args.acc_args.offset < 0) bad_arg("offset must not be negative"); - - accel.tag = args.accel_mode; - accel.visit([&](auto& impl) { impl = { args.acc_args }; }); - impl_args = args.acc_args; - - time_min = args.time_min; - speed_offset = args.acc_args.offset; - clamp.x = accel_scale_clamp(args.cap.x); - clamp.y = accel_scale_clamp(args.cap.y); - gain_cap = velocity_gain_cap(args.acc_args.gain_cap, speed_offset, accel); - } - - /// <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 raw_speed = mag / time_clamped; - - vec2d scale; - - // gain_cap needs raw speed for velocity line calculation - if (gain_cap.should_apply(raw_speed)) - { - double gain_cap_scale = gain_cap(raw_speed); - scale = { gain_cap_scale, gain_cap_scale }; + inline double apply(double speed) const { + if (gain_cap.should_apply(speed)) { + return clamp(gain_cap.apply(speed)); } - else - { - scale = accel.visit([=](auto&& impl) { - double accel_val = impl.accelerate(maxsd(mag / time_clamped - speed_offset, 0)); - return impl.scale(accel_val); - }); - } - - return { - input.x * clamp.x(scale.x), - input.y * clamp.y(scale.y) - }; + else return clamp(accel.apply(speed)); } - accel_function() = default; - }; - - struct modifier_args { - double degrees = 0; - vec2d sens = { 1, 1 }; - accel_fn_args acc_fn_args; + accelerator() = default; }; /// <summary> Struct to hold variables and methods for modifying mouse input </summary> struct mouse_modifier { bool apply_rotate = false; bool apply_accel = false; + bool combine_magnitudes = true; rotator rotate; - accel_function accel_fn; + vec2<accelerator> accels; vec2d sensitivity = { 1, 1 }; - mouse_modifier(const modifier_args& args) - : accel_fn(args.acc_fn_args) + mouse_modifier(const settings& args) : + combine_magnitudes(args.combine_mags) { - 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_impl_t::id<accel_noaccel>; + if (args.degrees_rotation != 0) { + rotate = rotator(args.degrees_rotation); + apply_rotate = true; + } + + if (args.sens.x != 0) sensitivity.x = args.sens.x; + if (args.sens.y != 0) sensitivity.y = args.sens.y; - if (args.sens.x == 0) sensitivity.x = 1; - else sensitivity.x = args.sens.x; + if ((combine_magnitudes && args.modes.x == accel_mode::noaccel) || + (args.modes.x == accel_mode::noaccel && + args.modes.y == accel_mode::noaccel)) { + return; + } - if (args.sens.y == 0) sensitivity.y = 1; - else sensitivity.y = args.sens.y; + accels.x = accelerator(args.argsv.x, args.modes.x); + accels.y = accelerator(args.argsv.y, args.modes.y); + apply_accel = true; } - /// <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; + void modify(vec2d& movement, milliseconds time) { + apply_rotation(movement); + apply_acceleration(movement, [=] { return time; }); + apply_sensitivity(movement); + } - return input; + inline void apply_rotation(vec2d& movement) { + if (apply_rotate) movement = rotate.apply(movement); } - /// <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); + template <typename TimeSupplier> + inline void apply_acceleration(vec2d& movement, TimeSupplier time_supp) { + if (apply_accel) { + milliseconds time = time_supp(); + + if (combine_magnitudes) { + double mag = sqrtsd(movement.x * movement.x + movement.y * movement.y); + double speed = mag / time; + double scale = accels.x.apply(speed); + movement.x *= scale; + movement.y *= scale; + } + else { + movement.x *= accels.x.apply(fabs(movement.x) / time); + movement.y *= accels.y.apply(fabs(movement.y) / time); + } } + } - input = accel_fn(input, time); - - input.x *= sensitivity.x; - input.y *= sensitivity.y; - - return input; + inline void apply_sensitivity(vec2d& movement) { + movement.x *= sensitivity.x; + movement.y *= sensitivity.y; } mouse_modifier() = default; }; -} // rawaccel
\ No newline at end of file +} // rawaccel diff --git a/common/tagged-union-single.h b/common/tagged-union-single.h deleted file mode 100644 index f0de097..0000000 --- a/common/tagged-union-single.h +++ /dev/null @@ -1,202 +0,0 @@ -#pragma once - -using size_t = decltype(alignof(char)); - -namespace type_traits { - -template< class T > struct remove_cv { typedef T type; }; -template< class T > struct remove_cv<const T> { typedef T type; }; -template< class T > struct remove_cv<volatile T> { typedef T type; }; -template< class T > struct remove_cv<const volatile T> { typedef T type; }; -template< class T > using remove_cv_t = typename remove_cv<T>::type; - -template< class T > struct remove_reference { typedef T type; }; -template< class T > struct remove_reference<T&> { typedef T type; }; -template< class T > struct remove_reference<T&&> { typedef T type; }; -template< class T > using remove_reference_t = typename remove_reference<T>::type; - -template< class T > -struct remove_cvref { - using type = remove_cv_t<remove_reference_t<T>>; -}; -template< class T > using remove_cvref_t = typename remove_cvref<T>::type; - -namespace detail { - -template <class T> struct type_identity { using type = T; }; - -template <class T> -auto try_add_lvalue_reference(int)->type_identity<T&>; -template <class T> -auto try_add_lvalue_reference(...)->type_identity<T>; - -template <class T> -auto try_add_rvalue_reference(int)->type_identity<T&&>; -template <class T> -auto try_add_rvalue_reference(...)->type_identity<T>; - -} // type_traits::detail - -template <class T> struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) {}; -template< class T > using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; - -template <class T> struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) {}; -template< class T > using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; - -template <typename T, typename U> inline constexpr bool is_same_v = false; -template <typename T> inline constexpr bool is_same_v<T, T> = true; -template <typename T> inline constexpr bool is_void_v = is_same_v<remove_cv_t<T>, void>; - -} // type_traits - -template<class T> type_traits::add_rvalue_reference_t<T> declval() noexcept; - -template <typename T> -inline constexpr T maxv(const T& a, const T& b) { - return (b < a) ? a : b; -} - -template <typename T> -inline constexpr T minv(const T& a, const T& b) { - return (a < b) ? a : b; -} - -template <typename T> -inline constexpr T clampv(const T& v, const T& lo, const T& hi) { - return minv(maxv(v, lo), hi); -} - -template <typename T> -inline constexpr const T& select_ref(bool pred, const T& t, const T& f) { - return pred ? t : f; -} - -template <typename First, typename... Rest> -inline constexpr size_t max_size_of = maxv(sizeof(First), max_size_of<Rest...>); - -template <typename T> -inline constexpr size_t max_size_of<T> = sizeof(T); - -template <typename First, typename... Rest> -inline constexpr size_t max_align_of = maxv(alignof(First), max_align_of<Rest...>); - -template <typename T> -inline constexpr size_t max_align_of<T> = alignof(T); - -namespace detail { - -template <typename... Ts> -struct b1_index_of_impl { - - template <typename...> - struct idx { - static constexpr size_t value = 0; - }; - - template <typename T, typename First, typename... Rest> - struct idx <T, First, Rest...> { - static constexpr size_t value = []() { - if constexpr (type_traits::is_same_v<T, First>) { - return sizeof...(Ts) - sizeof...(Rest); - } - return idx<T, Rest...>::value; - }(); - }; -}; - -} // detail - -template <typename T, typename First, typename... Rest> -inline constexpr int base1_index_of = -detail::b1_index_of_impl<First, Rest...>::template idx<T, First, Rest...>::value; - -/* -Requirements: Every type is trivially-copyable and is not an array type - -Can be initialized to an empty state as if by using -std::variant<std::monostate, First, Rest...> -*/ -template <typename First, typename... Rest> -struct tagged_union { - - // Requirements: The return type of Visitor is default-constructible (or void) - // Returns a value-initialized object when in an empty or invalid state - template<typename Visitor> - inline constexpr auto visit(Visitor vis) { - return visit_impl<Visitor, First, Rest...>(vis); - } - - template<typename Visitor> - inline constexpr auto visit(Visitor vis) const { - return visit_impl<Visitor, First, Rest...>(vis); - } - - template<typename T> - static constexpr int id = base1_index_of<T, First, Rest...>; - - int tag = 0; - - struct storage_t { - alignas(max_align_of<First, Rest...>) char bytes[max_size_of<First, Rest...>] = {}; - - template <typename T> - inline constexpr T& as() { - static_assert(id<T> != 0, "tagged_union can not hold T"); - return reinterpret_cast<T&>(bytes); - } - - template <typename T> - inline constexpr const T& as() const { - static_assert(id<T> != 0, "tagged_union can not hold T"); - return reinterpret_cast<const T&>(bytes); - } - - } storage; - - constexpr tagged_union() noexcept = default; - - template<typename T> - inline constexpr tagged_union(const T& val) noexcept { - tag = id<T>; - storage.template as<T>() = val; - } - - template<typename T> - inline constexpr tagged_union& operator=(const T& val) noexcept { - tag = id<T>; - storage.template as<T>() = val; - return *this; - } - -private: - template<typename Visitor, typename T1, typename... TRest> - inline constexpr auto visit_impl(Visitor vis) const { - if (tag == id<T1>) { - return vis(storage.template as<T1>()); - } - if constexpr (sizeof...(TRest) > 0) { - return visit_impl<Visitor, TRest...>(vis); - } - else { - using ReturnType = decltype(vis(declval<First&>())); - if constexpr (!type_traits::is_void_v<ReturnType>) return ReturnType{}; - } - } - - template<typename Visitor, typename T1, typename... TRest> - inline constexpr auto visit_impl(Visitor vis) { - if (tag == id<T1>) { - return vis(storage.template as<T1>()); - } - if constexpr (sizeof...(TRest) > 0) { - return visit_impl<Visitor, TRest...>(vis); - } - else { - using ReturnType = decltype(vis(declval<First&>())); - if constexpr (!type_traits::is_void_v<ReturnType>) return ReturnType{}; - } - } -}; - -template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; -template<class... Ts> overloaded(Ts...)->overloaded<Ts...>; diff --git a/driver/driver.cpp b/driver/driver.cpp index 3e67539..57b3c8a 100644 --- a/driver/driver.cpp +++ b/driver/driver.cpp @@ -14,9 +14,10 @@ namespace ra = rawaccel; using milliseconds = double; struct { + counter_t last_write = 0; + ra::settings args; milliseconds tick_interval = 0; // set in DriverEntry ra::mouse_modifier modifier; - counter_t last_write = 0; } global; VOID @@ -52,16 +53,12 @@ Arguments: if (!(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE)) { auto num_packets = InputDataEnd - InputDataStart; - + // if IO is backed up to the point where we get more than 1 packet here // then applying accel is pointless as we can't get an accurate timing - - bool local_apply_accel = num_packets == 1; - if (num_packets != 1) { - DebugPrint(("RA received %d packets\n", num_packets)); - } - - vec2d local_carry = devExt->carry; + bool enable_accel = num_packets == 1; + + vec2d carry = devExt->carry; auto it = InputDataStart; do { @@ -70,39 +67,37 @@ Arguments: static_cast<double>(it->LastY) }; - if (global.modifier.apply_accel && local_apply_accel) { - counter_t now = KeQueryPerformanceCounter(NULL).QuadPart; - counter_t ticks = now - devExt->counter; - devExt->counter = now; + global.modifier.apply_rotation(input); - milliseconds time = ticks * global.tick_interval; - if (time < global.modifier.accel_fn.time_min) { - DebugPrint(("RA time < min with %d ticks\n", ticks)); - } + if (enable_accel) { + auto time_supplier = [=] { + counter_t now = KeQueryPerformanceCounter(NULL).QuadPart; + counter_t ticks = now - devExt->counter; + devExt->counter = now; + milliseconds time = ticks * global.tick_interval; + return clampsd(time, global.args.time_min, 100); + }; - input = global.modifier.modify_with_accel(input, time); - } - else - { - input = global.modifier.modify_without_accel(input); + global.modifier.apply_acceleration(input, time_supplier); } - double result_x = input.x + local_carry.x; - double result_y = input.y + local_carry.y; + global.modifier.apply_sensitivity(input); + + double carried_result_x = input.x + carry.x; + double carried_result_y = input.y + carry.y; - LONG out_x = static_cast<LONG>(result_x); - LONG out_y = static_cast<LONG>(result_y); + LONG out_x = static_cast<LONG>(carried_result_x); + LONG out_y = static_cast<LONG>(carried_result_y); - local_carry.x = result_x - out_x; - local_carry.y = result_y - out_y; + carry.x = carried_result_x - out_x; + carry.y = carried_result_y - out_y; it->LastX = out_x; it->LastY = out_y; - ++it; - } while (it < InputDataEnd); + } while (++it != InputDataEnd); - devExt->carry = local_carry; + devExt->carry = carry; } (*(PSERVICE_CALLBACK_ROUTINE)devExt->UpperConnectData.ClassService)( @@ -154,7 +149,7 @@ Return Value: DebugPrint(("Ioctl received into filter control object.\n")); - if (InputBufferLength == sizeof(ra::mouse_modifier)) { + if (InputBufferLength == sizeof(ra::settings)) { constexpr milliseconds WRITE_COOLDOWN_TIME = 1000; counter_t now = KeQueryPerformanceCounter(NULL).QuadPart; @@ -170,7 +165,7 @@ Return Value: status = WdfRequestRetrieveInputBuffer( Request, - sizeof(ra::mouse_modifier), + sizeof(ra::settings), &buffer, &size ); @@ -182,15 +177,16 @@ Return Value: return; } - global.modifier = *reinterpret_cast<ra::mouse_modifier*>(buffer); + global.args = *reinterpret_cast<ra::settings*>(buffer); + global.modifier = { global.args }; global.last_write = now; WdfRequestComplete(Request, STATUS_SUCCESS); } - else if (OutputBufferLength == sizeof(ra::mouse_modifier)) { + else if (OutputBufferLength == sizeof(ra::settings)) { status = WdfRequestRetrieveOutputBuffer( Request, - sizeof(ra::mouse_modifier), + sizeof(ra::settings), &buffer, &size ); @@ -202,7 +198,7 @@ Return Value: return; } - *reinterpret_cast<ra::mouse_modifier*>(buffer) = global.modifier; + *reinterpret_cast<ra::settings*>(buffer) = global.args; WdfRequestComplete(Request, STATUS_SUCCESS); } diff --git a/grapher/Form1.cs b/grapher/Form1.cs index d6f7990..37f67f8 100644 --- a/grapher/Form1.cs +++ b/grapher/Form1.cs @@ -15,48 +15,6 @@ using grapher.Models.Serialized; namespace grapher { - public enum accel_mode - { - linear=1, classic, natural, logarithmic, sigmoid, power, naturalgain, sigmoidgain, noaccel - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct vec2d - { - public double x; - public double y; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct accel_args - { - public double offset; - public double accel; - public double limit; - public double exponent; - public double midpoint; - public double power_scale; - public double gain_cap; - public vec2d weight; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct accel_fn_args - { - public accel_args acc_args; - public int accel_mode; - public double time_min; - public vec2d cap; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct modifier_args - { - public double degrees; - public vec2d sens; - public accel_fn_args acc_fn_args; - } - public partial class RawAcceleration : Form { @@ -66,32 +24,17 @@ namespace grapher public RawAcceleration() { InitializeComponent(); - modifier_args args; - - args.degrees = 0; - args.sens.x = 1; - args.sens.y = 1; - args.acc_fn_args.acc_args.offset = 0; - args.acc_fn_args.acc_args.accel = 0.01; - args.acc_fn_args.acc_args.limit = 2; - args.acc_fn_args.acc_args.exponent = 1; - args.acc_fn_args.acc_args.midpoint = 0; - args.acc_fn_args.acc_args.power_scale = 1; - args.acc_fn_args.acc_args.weight.x = 1; - args.acc_fn_args.acc_args.weight.y = 1; - args.acc_fn_args.acc_args.gain_cap = 0; - args.acc_fn_args.accel_mode = (int)accel_mode.natural; - args.acc_fn_args.time_min = 0.4; - args.acc_fn_args.cap.x = 0; - args.acc_fn_args.cap.y = 0; - - IntPtr args_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(args)); - Marshal.StructureToPtr(args, args_ptr, false); - var managedAcceleration = new ManagedAccel(args_ptr); - - Marshal.FreeHGlobal(args_ptr); + ManagedAccel activeAccel = null; + try + { + activeAccel = ManagedAccel.GetActiveAccel(); + } + catch (DriverNotInstalledException) + { + throw; + } var accelCharts = new AccelCharts( this, @@ -205,7 +148,7 @@ namespace grapher new Field(PollRateTextBox.TextBox, this, AccelCalculator.DefaultPollRate)); var settings = new SettingsManager( - managedAcceleration, + activeAccel, accelCalculator.DPI, accelCalculator.PollRate, AutoWriteMenuItem); diff --git a/grapher/Layouts/ClassicLayout.cs b/grapher/Layouts/ClassicLayout.cs index 093f7fa..05f6c82 100644 --- a/grapher/Layouts/ClassicLayout.cs +++ b/grapher/Layouts/ClassicLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Classic"; - Index = 2; + Index = (int)AccelMode.classic; ShowOptions = new bool[] { true, true, true, false }; OptionNames = new string[] { Offset, Acceleration, Exponent, string.Empty }; } diff --git a/grapher/Layouts/DefaultLayout.cs b/grapher/Layouts/DefaultLayout.cs index 095afdf..42841d5 100644 --- a/grapher/Layouts/DefaultLayout.cs +++ b/grapher/Layouts/DefaultLayout.cs @@ -1,10 +1,12 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; + namespace grapher.Layouts { public class DefaultLayout : LayoutBase @@ -13,7 +15,7 @@ namespace grapher.Layouts : base() { Name = "Default"; - Index = 0; + Index = (int)AccelMode.noaccel; ShowOptions = new bool[] { true, true, true, true }; OptionNames = new string[] { Offset, Acceleration, $"{Limit}\\{Exponent}", Midpoint }; ButtonEnabled = false; diff --git a/grapher/Layouts/LayoutBase.cs b/grapher/Layouts/LayoutBase.cs index a4d0827..3ae2e90 100644 --- a/grapher/Layouts/LayoutBase.cs +++ b/grapher/Layouts/LayoutBase.cs @@ -26,7 +26,7 @@ namespace grapher.Layouts /// <summary> /// Gets or sets mapping from acceleration type to identifying integer. - /// Must match order in tagged_union in rawaccel.hpp (which is 1-indexed, meaning 0 is off.) + /// Must match accel_mode defined in rawaccel-settings.h /// </summary> public int Index { get; internal set; } diff --git a/grapher/Layouts/LinearLayout.cs b/grapher/Layouts/LinearLayout.cs index 2a0358e..0a79a64 100644 --- a/grapher/Layouts/LinearLayout.cs +++ b/grapher/Layouts/LinearLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Linear"; - Index = 1; + Index = (int)AccelMode.linear; ShowOptions = new bool[] { true, true, false, false }; OptionNames = new string[] { Offset, Acceleration, string.Empty, string.Empty }; } diff --git a/grapher/Layouts/LogLayout.cs b/grapher/Layouts/LogLayout.cs index ae1a8f5..1206fb3 100644 --- a/grapher/Layouts/LogLayout.cs +++ b/grapher/Layouts/LogLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Logarithmic"; - Index = 4; + Index = (int)AccelMode.logarithmic; ShowOptions = new bool[] { true, true, false, false }; OptionNames = new string[] { Offset, Acceleration, string.Empty, string.Empty }; } diff --git a/grapher/Layouts/NaturalGainLayout.cs b/grapher/Layouts/NaturalGainLayout.cs index e062850..9bb1ec8 100644 --- a/grapher/Layouts/NaturalGainLayout.cs +++ b/grapher/Layouts/NaturalGainLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "NaturalGain"; - Index = 7; + Index = (int)AccelMode.naturalgain; ShowOptions = new bool[] { true, true, true, false }; OptionNames = new string[] { Offset, Acceleration, Limit, string.Empty }; } diff --git a/grapher/Layouts/NaturalLayout.cs b/grapher/Layouts/NaturalLayout.cs index 743135c..44c6c18 100644 --- a/grapher/Layouts/NaturalLayout.cs +++ b/grapher/Layouts/NaturalLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Natural"; - Index = 3; + Index = (int)AccelMode.natural; ShowOptions = new bool[] { true, true, true, false }; OptionNames = new string[] { Offset, Acceleration, Limit, string.Empty }; } diff --git a/grapher/Layouts/OffLayout.cs b/grapher/Layouts/OffLayout.cs index 087885f..ce7c149 100644 --- a/grapher/Layouts/OffLayout.cs +++ b/grapher/Layouts/OffLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Off"; - Index = 9; + Index = (int)AccelMode.noaccel; ShowOptions = new bool[] { false, false, false, false }; OptionNames = new string[] { string.Empty, string.Empty, string.Empty, string.Empty }; ShowOptionsXY = new bool[] { false, false }; diff --git a/grapher/Layouts/PowerLayout.cs b/grapher/Layouts/PowerLayout.cs index da02cf5..c14083a 100644 --- a/grapher/Layouts/PowerLayout.cs +++ b/grapher/Layouts/PowerLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Power"; - Index = 6; + Index = (int)AccelMode.power; ShowOptions = new bool[] { true, true, true, false }; OptionNames = new string[] { Offset, Scale, Exponent, string.Empty }; } diff --git a/grapher/Layouts/SigmoidGainLayout.cs b/grapher/Layouts/SigmoidGainLayout.cs index c620925..93214ec 100644 --- a/grapher/Layouts/SigmoidGainLayout.cs +++ b/grapher/Layouts/SigmoidGainLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "SigmoidGain"; - Index = 8; + Index = (int)AccelMode.sigmoidgain; ShowOptions = new bool[] { true, true, true, true }; OptionNames = new string[] { Offset, Acceleration, Limit, Midpoint }; } diff --git a/grapher/Layouts/SigmoidLayout.cs b/grapher/Layouts/SigmoidLayout.cs index 0dec3bf..1c7f0b9 100644 --- a/grapher/Layouts/SigmoidLayout.cs +++ b/grapher/Layouts/SigmoidLayout.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,7 @@ namespace grapher.Layouts : base() { Name = "Sigmoid"; - Index = 5; + Index = (int)AccelMode.sigmoid; ShowOptions = new bool[] { true, true, true, true }; OptionNames = new string[] { Offset, Acceleration, Limit, Midpoint }; } diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs index e0dcc03..a15dba8 100644 --- a/grapher/Models/AccelGUI.cs +++ b/grapher/Models/AccelGUI.cs @@ -2,6 +2,7 @@ using grapher.Models.Mouse; using grapher.Models.Serialized; using System; +using System.CodeDom; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -101,41 +102,64 @@ namespace grapher public void UpdateActiveSettingsFromFields() { - Settings.UpdateActiveSettings( - AccelerationOptions.AccelerationIndex, - Rotation.Field.Data, - Sensitivity.Fields.X, - Sensitivity.Fields.Y, - Weight.Fields.X, - Weight.Fields.Y, - Cap.SensitivityCapX, - Cap.SensitivityCapY, - Offset.Field.Data, - Acceleration.Field.Data, - LimitOrExponent.Field.Data, - Midpoint.Field.Data, - Cap.VelocityGainCap); + Settings.UpdateActiveSettings(new DriverSettings + { + rotation = Rotation.Field.Data, + sensitivity = new Vec2<double> + { + x = Sensitivity.Fields.X, + y = Sensitivity.Fields.Y + }, + combineMagnitudes = true, + modes = new Vec2<AccelMode> + { + x = (AccelMode)AccelerationOptions.AccelerationIndex + }, + args = new Vec2<AccelArgs> + { + x = new AccelArgs + { + offset = Offset.Field.Data, + weight = Weight.Fields.X, + gainCap = Cap.VelocityGainCap, + scaleCap = Cap.SensitivityCapX, + accel = Acceleration.Field.Data, + rate = Acceleration.Field.Data, + powerScale = Acceleration.Field.Data, + limit = LimitOrExponent.Field.Data, + exponent = LimitOrExponent.Field.Data, + powerExponent = LimitOrExponent.Field.Data, + midpoint = Midpoint.Field.Data + } + }, + minimumTime = .4 + }); UpdateGraph(); } public void UpdateGraph() { - AccelCalculator.Calculate(AccelCharts.AccelData, Settings.ActiveAccel); + AccelCalculator.Calculate( + AccelCharts.AccelData, + Settings.ActiveAccel, + Settings.RawAccelSettings.AccelerationSettings); AccelCharts.Bind(); UpdateActiveValueLabels(); } public void UpdateActiveValueLabels() { - Sensitivity.SetActiveValues(Settings.ActiveAccel.SensitivityX, Settings.ActiveAccel.SensitivityY); - Rotation.SetActiveValue(Settings.ActiveAccel.Rotation); - AccelerationOptions.SetActiveValue(Settings.ActiveAccel.Type); - Offset.SetActiveValue(Settings.ActiveAccel.Offset); - Acceleration.SetActiveValue(Settings.ActiveAccel.Acceleration); - Cap.SetActiveValues(Settings.ActiveAccel.GainCap, Settings.ActiveAccel.CapX, Settings.ActiveAccel.CapY, Settings.ActiveAccel.GainCapEnabled); - Weight.SetActiveValues(Settings.ActiveAccel.WeightX, Settings.ActiveAccel.WeightY); - LimitOrExponent.SetActiveValue(Settings.ActiveAccel.LimitExp); - Midpoint.SetActiveValue(Settings.ActiveAccel.Midpoint); + var settings = Settings.RawAccelSettings.AccelerationSettings; + + Sensitivity.SetActiveValues(settings.sensitivity.x, settings.sensitivity.y); + Rotation.SetActiveValue(settings.rotation); + AccelerationOptions.SetActiveValue((int)settings.modes.x); + Offset.SetActiveValue(settings.args.x.offset); + Weight.SetActiveValues(settings.args.x.weight, settings.args.x.weight); + Acceleration.SetActiveValue(settings.args.x.accel); // rate, powerscale + LimitOrExponent.SetActiveValue(settings.args.x.limit); //exp, powerexp + Midpoint.SetActiveValue(settings.args.x.midpoint); + //Cap.SetActiveValues(Settings.ActiveAccel.GainCap, Settings.ActiveAccel.CapX, Settings.ActiveAccel.CapY, Settings.ActiveAccel.GainCapEnabled); } private void OnScaleMenuItemClick(object sender, EventArgs e) diff --git a/grapher/Models/Calculations/AccelCalculator.cs b/grapher/Models/Calculations/AccelCalculator.cs index 63ed281..102de8d 100644 --- a/grapher/Models/Calculations/AccelCalculator.cs +++ b/grapher/Models/Calculations/AccelCalculator.cs @@ -1,4 +1,5 @@ -using System; +using grapher.Models.Serialized; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -46,15 +47,15 @@ namespace grapher.Models.Calculations private int Increment { get; set; } - public void Calculate(AccelData data, ManagedAccel accel) + public void Calculate(AccelData data, ManagedAccel accel, DriverSettings settings) { ScaleByMouseSettings(); data.Clear(); - Calculate(data.Combined, accel, accel.SensitivityX, MagnitudesCombined); - Calculate(data.X, accel, accel.SensitivityX, MagnitudesX); - Calculate(data.Y, accel, accel.SensitivityY, MagnitudesY); + Calculate(data.Combined, accel, settings.sensitivity.x, MagnitudesCombined); + Calculate(data.X, accel, settings.sensitivity.x, MagnitudesX); + Calculate(data.Y, accel, settings.sensitivity.y, MagnitudesY); } public static void Calculate(AccelChartData data, ManagedAccel accel, double starter, ICollection<MagnitudeData> magnitudeData) diff --git a/grapher/Models/Options/AccelOptions.cs b/grapher/Models/Options/AccelOptions.cs index cd7c4e5..6b98274 100644 --- a/grapher/Models/Options/AccelOptions.cs +++ b/grapher/Models/Options/AccelOptions.cs @@ -16,7 +16,6 @@ namespace grapher public static readonly Dictionary<string, LayoutBase> AccelerationTypes = new List<LayoutBase> { - new DefaultLayout(), new LinearLayout(), new ClassicLayout(), new NaturalLayout(), @@ -37,7 +36,7 @@ namespace grapher { AccelDropdown = accelDropdown; AccelDropdown.Items.Clear(); - AccelDropdown.Items.AddRange(AccelerationTypes.Keys.Skip(1).ToArray()); + AccelDropdown.Items.AddRange(AccelerationTypes.Keys.ToArray()); AccelDropdown.SelectedIndexChanged += new System.EventHandler(OnIndexChanged); if (options.Length > PossibleOptionsCount) @@ -55,7 +54,7 @@ namespace grapher WriteButton = writeButton; ActiveValueLabel = activeValueLabel; - Layout("Default"); + Layout("Off"); } public Button WriteButton { get; } diff --git a/grapher/Models/Serialized/DriverSettings.cs b/grapher/Models/Serialized/DriverSettings.cs new file mode 100644 index 0000000..91d7e9f --- /dev/null +++ b/grapher/Models/Serialized/DriverSettings.cs @@ -0,0 +1,87 @@ +using System; +using System.Runtime.InteropServices; + +namespace grapher.Models.Serialized +{ + public enum AccelMode + { + linear, classic, natural, logarithmic, sigmoid, naturalgain, sigmoidgain, power, noaccel + } + + [StructLayout(LayoutKind.Sequential)] + public struct AccelArgs + { + public double offset; + public double accel; + public double limit; + public double exponent; + public double midpoint; + public double powerScale; + public double powerExponent; + public double weight; + public double rate; + public double scaleCap; + public double gainCap; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct Vec2 <T> + { + public T x; + public T y; + } + + [StructLayout(LayoutKind.Sequential)] + [Serializable] + public class DriverSettings + { + private static readonly IntPtr UnmanagedSettingsHandle = + Marshal.AllocHGlobal(Marshal.SizeOf<DriverSettings>()); + + public double rotation; + public bool combineMagnitudes; + public Vec2<AccelMode> modes; + public Vec2<AccelArgs> args; + public Vec2<double> sensitivity; + public double minimumTime; + + public static DriverSettings GetActive() + { + DriverInterop.GetActiveSettings(UnmanagedSettingsHandle); + return Marshal.PtrToStructure<DriverSettings>(UnmanagedSettingsHandle); + } + + public static void SetActive(DriverSettings settings) + { + Marshal.StructureToPtr(settings, UnmanagedSettingsHandle, false); + DriverInterop.SetActiveSettings(UnmanagedSettingsHandle); + } + + public void SendToDriver() + { + SetActive(this); + } + + public void SendToDriverAndUpdate(ManagedAccel accel) + { + SendToDriver(); + accel.UpdateFromSettings(UnmanagedSettingsHandle); + } + + public bool verify() + { + /* + if (args.accel < 0 || args.rate < 0) + bad_arg("accel can not be negative, use a negative weight to compensate"); + if (args.rate > 1) bad_arg("rate can not be greater than 1"); + if (args.exponent <= 1) bad_arg("exponent must be greater than 1"); + if (args.limit <= 1) bad_arg("limit must be greater than 1"); + if (args.power_scale <= 0) bad_arg("scale must be positive"); + if (args.power_exp <= 0) bad_arg("exponent must be positive"); + if (args.midpoint < 0) bad_arg("midpoint must not be negative"); + if (args.time_min <= 0) bad_arg("min time must be positive"); + */ + return true; + } + } +} diff --git a/grapher/Models/Serialized/ModifierArgs.cs b/grapher/Models/Serialized/ModifierArgs.cs deleted file mode 100644 index 206a3c9..0000000 --- a/grapher/Models/Serialized/ModifierArgs.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace grapher.Models.Serialized -{ - public enum accel_mode - { - linear=1, classic, natural, logarithmic, sigmoid, power, naturalgain, sigmoidgain, noaccel - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - [Serializable] - public struct vec2d - { - public double x; - public double y; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - [Serializable] - public struct accel_args - { - public double offset; - public double accel; - public double limit; - public double exponent; - public double midpoint; - public double power_scale; - public double gain_cap; - public vec2d weight; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - [Serializable] - public struct accel_fn_args - { - public accel_args acc_args; - public int accel_mode; - public double time_min; - public vec2d cap; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - [Serializable] - public struct modifier_args - { - public double degrees; - public vec2d sens; - public accel_fn_args acc_fn_args; - - public modifier_args(ManagedAccel managedAccel) - { - degrees = managedAccel.Rotation; - sens.x = managedAccel.SensitivityX; - sens.y = managedAccel.SensitivityY; - acc_fn_args.accel_mode = managedAccel.Type; - acc_fn_args.time_min = managedAccel.MinimumTime; - acc_fn_args.cap.x = managedAccel.CapX; - acc_fn_args.cap.y = managedAccel.CapY; - acc_fn_args.acc_args.accel = managedAccel.Acceleration; - acc_fn_args.acc_args.exponent = managedAccel.LimitExp; - acc_fn_args.acc_args.gain_cap = managedAccel.GainCap; - acc_fn_args.acc_args.limit = managedAccel.LimitExp; - acc_fn_args.acc_args.midpoint = managedAccel.Midpoint; - acc_fn_args.acc_args.offset = managedAccel.Offset; - acc_fn_args.acc_args.power_scale = managedAccel.PowerScale; - acc_fn_args.acc_args.weight.x = managedAccel.WeightX; - acc_fn_args.acc_args.weight.y = managedAccel.WeightY; - } - } -} diff --git a/grapher/Models/Serialized/RawAccelSettings.cs b/grapher/Models/Serialized/RawAccelSettings.cs index 21a7f0c..7aed917 100644 --- a/grapher/Models/Serialized/RawAccelSettings.cs +++ b/grapher/Models/Serialized/RawAccelSettings.cs @@ -24,17 +24,16 @@ namespace grapher.Models.Serialized public RawAccelSettings() { } public RawAccelSettings( - ManagedAccel managedAccel, + DriverSettings accelSettings, GUISettings guiSettings) { - AccelerationSettings = new modifier_args(managedAccel); + AccelerationSettings = accelSettings; GUISettings = guiSettings; } - public GUISettings GUISettings { get; set; } - public modifier_args AccelerationSettings { get; set; } + public DriverSettings AccelerationSettings { get; set; } public static RawAccelSettings Load() { @@ -42,23 +41,19 @@ namespace grapher.Models.Serialized } public static RawAccelSettings Load(string file) - { - if (!Exists(file)) + { + try { - throw new Exception($"Settings file does not exist at {file}"); + return JsonConvert.DeserializeObject<RawAccelSettings>(File.ReadAllText(file), SerializerSettings); } - - RawAccelSettings deserializedSettings; - try + catch (FileNotFoundException e) { - deserializedSettings = JsonConvert.DeserializeObject<RawAccelSettings>(File.ReadAllText(file), SerializerSettings); + throw new FileNotFoundException($"Settings file does not exist at {file}", e); } - catch(Exception e) + catch (JsonSerializationException e) { - throw new Exception($"Settings file at {file} does not contain valid Raw Accel Settings.", e); + throw new JsonSerializationException($"Settings file at {file} does not contain valid Raw Accel Settings.", e); } - - return deserializedSettings; } public static bool Exists() diff --git a/grapher/Models/Serialized/SettingsManager.cs b/grapher/Models/Serialized/SettingsManager.cs index 848606d..fc58387 100644 --- a/grapher/Models/Serialized/SettingsManager.cs +++ b/grapher/Models/Serialized/SettingsManager.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +using Newtonsoft.Json; +using System; using System.Windows.Forms; namespace grapher.Models.Serialized @@ -32,63 +28,38 @@ namespace grapher.Models.Serialized private ToolStripMenuItem AutoWriteMenuItem { get; set; } - public void UpdateActiveSettings( - int mode, - double degrees, - double sensitivityX, - double sensitivityY, - double weightX, - double weightY, - double capX, - double capY, - double offset, - double accel, - double limitOrExp, - double midpoint, - double gainCap) + public void UpdateActiveSettings(DriverSettings settings) { - ActiveAccel.UpdateAccel( - mode, - degrees, - sensitivityX, - sensitivityY, - weightX, - weightY, - capX, - capY, - offset, - accel, - limitOrExp, - midpoint, - gainCap); + try + { + settings.SendToDriverAndUpdate(ActiveAccel); - RawAccelSettings.AccelerationSettings = new modifier_args(ActiveAccel); - RawAccelSettings.GUISettings = new GUISettings + RawAccelSettings.AccelerationSettings = settings; + RawAccelSettings.GUISettings = new GUISettings { AutoWriteToDriverOnStartup = AutoWriteMenuItem.Checked, DPI = (int)DpiField.Data, PollRate = (int)PollRateField.Data }; - RawAccelSettings.Save(); + RawAccelSettings.Save(); + } + catch (DriverWriteCDException) + { + Console.WriteLine("write on cooldown"); + } } - public void UpdateActiveAccelFromFileSettings() + public void UpdateActiveAccelFromFileSettings(DriverSettings settings) { - ActiveAccel.UpdateAccel( - RawAccelSettings.AccelerationSettings.acc_fn_args.accel_mode, - RawAccelSettings.AccelerationSettings.degrees, - RawAccelSettings.AccelerationSettings.sens.x, - RawAccelSettings.AccelerationSettings.sens.y, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.weight.x, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.weight.y, - RawAccelSettings.AccelerationSettings.acc_fn_args.cap.x, - RawAccelSettings.AccelerationSettings.acc_fn_args.cap.y, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.offset, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.accel, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.exponent, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.midpoint, - RawAccelSettings.AccelerationSettings.acc_fn_args.acc_args.gain_cap); + try + { + settings.SendToDriverAndUpdate(ActiveAccel); + } + catch (DriverWriteCDException) + { + Console.WriteLine("write on cd during file init"); + } DpiField.SetToEntered(RawAccelSettings.GUISettings.DPI); PollRateField.SetToEntered(RawAccelSettings.GUISettings.PollRate); AutoWriteMenuItem.Checked = RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup; @@ -96,28 +67,32 @@ namespace grapher.Models.Serialized public void Startup() { - ActiveAccel.ReadFromDriver(); - - if(RawAccelSettings.Exists()) + if (RawAccelSettings.Exists()) { - RawAccelSettings = RawAccelSettings.Load(); - if (RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup) + try { - UpdateActiveAccelFromFileSettings(); - } - } - else - { - RawAccelSettings = new RawAccelSettings( - ActiveAccel, - new GUISettings + RawAccelSettings = RawAccelSettings.Load(); + if (RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup) { - AutoWriteToDriverOnStartup = AutoWriteMenuItem.Checked, - DPI = (int)DpiField.Data, - PollRate = (int)PollRateField.Data - }); - RawAccelSettings.Save(); + UpdateActiveAccelFromFileSettings(RawAccelSettings.AccelerationSettings); + } + return; + } + catch (JsonSerializationException e) + { + Console.WriteLine($"bad settings: {e}"); + } } + + RawAccelSettings = new RawAccelSettings( + DriverSettings.GetActive(), + new GUISettings + { + AutoWriteToDriverOnStartup = AutoWriteMenuItem.Checked, + DPI = (int)DpiField.Data, + PollRate = (int)PollRateField.Data + }); + RawAccelSettings.Save(); } } } diff --git a/grapher/grapher.csproj b/grapher/grapher.csproj index 6e03ae0..d34e678 100644 --- a/grapher/grapher.csproj +++ b/grapher/grapher.csproj @@ -13,24 +13,27 @@ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <Deterministic>true</Deterministic> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <PlatformTarget>x64</PlatformTarget> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> + <OutputPath>bin\x64\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x64</PlatformTarget> + <LangVersion>7.3</LangVersion> <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PlatformTarget>x64</PlatformTarget> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <OutputPath>bin\x64\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>x64</PlatformTarget> + <LangVersion>7.3</LangVersion> <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> </PropertyGroup> <ItemGroup> <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> @@ -85,7 +88,7 @@ <Compile Include="Models\Options\Option.cs" /> <Compile Include="Models\Options\OptionXY.cs" /> <Compile Include="Models\Serialized\GUISettings.cs" /> - <Compile Include="Models\Serialized\ModifierArgs.cs" /> + <Compile Include="Models\Serialized\DriverSettings.cs" /> <Compile Include="Models\Serialized\RawAccelSettings.cs" /> <Compile Include="Models\Serialized\SettingsManager.cs" /> <Compile Include="Program.cs" /> diff --git a/rawaccel.sln b/rawaccel.sln index 33735fd..9eb1101 100644 --- a/rawaccel.sln +++ b/rawaccel.sln @@ -30,69 +30,34 @@ Global common\common.vcxitems*{ab7b3759-b85f-4067-8935-fb4539b41869}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|Any CPU.ActiveCfg = Debug|x64 {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x64.ActiveCfg = Debug|x64 {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x64.Build.0 = Debug|x64 {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x64.Deploy.0 = Debug|x64 - {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x86.ActiveCfg = Debug|x64 - {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Release|Any CPU.ActiveCfg = Release|x64 {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Release|x64.ActiveCfg = Release|x64 {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Release|x64.Build.0 = Release|x64 - {60D6C942-AC20-4C05-A2BE-54B5C966534D}.Release|x86.ActiveCfg = Release|x64 - {896950D1-520A-420A-B6B1-73014B92A68C}.Debug|Any CPU.ActiveCfg = Debug|x64 {896950D1-520A-420A-B6B1-73014B92A68C}.Debug|x64.ActiveCfg = Debug|x64 {896950D1-520A-420A-B6B1-73014B92A68C}.Debug|x64.Build.0 = Debug|x64 - {896950D1-520A-420A-B6B1-73014B92A68C}.Debug|x86.ActiveCfg = Debug|x64 - {896950D1-520A-420A-B6B1-73014B92A68C}.Release|Any CPU.ActiveCfg = Release|x64 {896950D1-520A-420A-B6B1-73014B92A68C}.Release|x64.ActiveCfg = Release|x64 {896950D1-520A-420A-B6B1-73014B92A68C}.Release|x64.Build.0 = Release|x64 - {896950D1-520A-420A-B6B1-73014B92A68C}.Release|x86.ActiveCfg = Release|x64 - {AB7B3759-B85F-4067-8935-FB4539B41869}.Debug|Any CPU.ActiveCfg = Debug|x64 {AB7B3759-B85F-4067-8935-FB4539B41869}.Debug|x64.ActiveCfg = Debug|x64 {AB7B3759-B85F-4067-8935-FB4539B41869}.Debug|x64.Build.0 = Debug|x64 - {AB7B3759-B85F-4067-8935-FB4539B41869}.Debug|x86.ActiveCfg = Debug|x64 - {AB7B3759-B85F-4067-8935-FB4539B41869}.Release|Any CPU.ActiveCfg = Release|x64 {AB7B3759-B85F-4067-8935-FB4539B41869}.Release|x64.ActiveCfg = Release|x64 {AB7B3759-B85F-4067-8935-FB4539B41869}.Release|x64.Build.0 = Release|x64 - {AB7B3759-B85F-4067-8935-FB4539B41869}.Release|x86.ActiveCfg = Release|x64 - {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Debug|Any CPU.ActiveCfg = Debug|x64 {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Debug|x64.ActiveCfg = Debug|x64 {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Debug|x64.Build.0 = Debug|x64 - {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Debug|x86.ActiveCfg = Debug|x64 - {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Release|Any CPU.ActiveCfg = Release|x64 {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Release|x64.ActiveCfg = Release|x64 {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Release|x64.Build.0 = Release|x64 - {A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Release|x86.ActiveCfg = Release|x64 - {28A3656F-A1DE-405C-B547-191C32EC555F}.Debug|Any CPU.ActiveCfg = Debug|Win32 {28A3656F-A1DE-405C-B547-191C32EC555F}.Debug|x64.ActiveCfg = Debug|x64 {28A3656F-A1DE-405C-B547-191C32EC555F}.Debug|x64.Build.0 = Debug|x64 - {28A3656F-A1DE-405C-B547-191C32EC555F}.Debug|x86.ActiveCfg = Debug|Win32 - {28A3656F-A1DE-405C-B547-191C32EC555F}.Debug|x86.Build.0 = Debug|Win32 - {28A3656F-A1DE-405C-B547-191C32EC555F}.Release|Any CPU.ActiveCfg = Release|Win32 {28A3656F-A1DE-405C-B547-191C32EC555F}.Release|x64.ActiveCfg = Release|x64 {28A3656F-A1DE-405C-B547-191C32EC555F}.Release|x64.Build.0 = Release|x64 - {28A3656F-A1DE-405C-B547-191C32EC555F}.Release|x86.ActiveCfg = Release|Win32 - {28A3656F-A1DE-405C-B547-191C32EC555F}.Release|x86.Build.0 = Release|Win32 - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|x64.ActiveCfg = Debug|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|x64.Build.0 = Debug|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|x86.ActiveCfg = Debug|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|x86.Build.0 = Debug|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|Any CPU.Build.0 = Release|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|x64.ActiveCfg = Release|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|x64.Build.0 = Release|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|x86.ActiveCfg = Release|Any CPU - {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|x86.Build.0 = Release|Any CPU + {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Debug|x64.ActiveCfg = Debug|x64 + {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|x64.ActiveCfg = Release|x64 + {EF67F71F-ABF5-4760-B50D-D1B9836DF01C}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index dcc9606..757d3f1 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -1,84 +1,62 @@ #pragma once -#include "wrapper.hpp" +#include <rawaccel.hpp> -using namespace rawaccel; -using namespace System; - -Tuple<double, double>^ ManagedAccel::Accelerate(int x, int y, double time) -{ - vec2d input_vec2d = { - (double)x, - (double)y - }; - vec2d output = (*modifier_instance).modify_with_accel(input_vec2d, (milliseconds)time); - - return gcnew Tuple<double, double>(output.x, output.y); -} - -void ManagedAccel::UpdateAccel( - int mode, - double rotation, - double sensitivityX, - double sensitivityY, - double weightX, - double weightY, - double capX, - double capY, - double offset, - double accel, - double lim_exp, - double midpoint, - double gain_cap) -{ - modifier_args args = modifier_args{}; - args.acc_fn_args.accel_mode = mode; - args.degrees = rotation; - args.sens.x = sensitivityX; - args.sens.y = sensitivityY; - args.acc_fn_args.acc_args.weight.x = weightX; - args.acc_fn_args.acc_args.weight.y = weightY; - args.acc_fn_args.cap.x = capX; - args.acc_fn_args.cap.y = capY; - args.acc_fn_args.acc_args.offset = offset; - args.acc_fn_args.acc_args.accel = accel; - args.acc_fn_args.acc_args.limit = lim_exp; - args.acc_fn_args.acc_args.exponent = lim_exp; - args.acc_fn_args.acc_args.midpoint = midpoint; - args.acc_fn_args.acc_args.gain_cap = gain_cap; - - mouse_modifier* temp_modifier = new mouse_modifier(args); - driverWriter->writeToDriver(temp_modifier); - delete temp_modifier; - - ReadFromDriver(); - -} +#include "wrapper_io.hpp" -double ManagedAccel::SensitivityX::get() { return modifier_instance->sensitivity.x; } -double ManagedAccel::SensitivityY::get() { return modifier_instance->sensitivity.y; } -double ManagedAccel::Rotation::get() { return atan(modifier_instance->rotate.rot_vec.y / modifier_instance->rotate.rot_vec.x) * 180 / M_PI; } -int ManagedAccel::Type::get() { return modifier_instance->accel_fn.accel.tag; } -double ManagedAccel::Acceleration::get() { return modifier_instance->accel_fn.impl_args.accel; } -double ManagedAccel::CapX::get() { return modifier_instance->accel_fn.clamp.x.hi; } -double ManagedAccel::CapY::get() { return modifier_instance->accel_fn.clamp.y.hi; } -double ManagedAccel::GainCap::get() { return modifier_instance->accel_fn.gain_cap.threshold; } -bool ManagedAccel::GainCapEnabled::get() { return modifier_instance->accel_fn.gain_cap.cap_gain_enabled; } -double ManagedAccel::WeightX::get() { return modifier_instance->accel_fn.impl_args.weight.x; } -double ManagedAccel::WeightY::get() { return modifier_instance->accel_fn.impl_args.weight.y; } -double ManagedAccel::Offset::get() { return modifier_instance->accel_fn.speed_offset; } -double ManagedAccel::LimitExp::get() { return modifier_instance->accel_fn.impl_args.limit; } -double ManagedAccel::Midpoint::get() { return modifier_instance->accel_fn.impl_args.midpoint; } -double ManagedAccel::MinimumTime::get() { return modifier_instance->accel_fn.time_min; } -double ManagedAccel::PowerScale::get() { return modifier_instance->accel_fn.impl_args.power_scale; } +using namespace System; -void ManagedAccel::WriteToDriver() +public ref struct DriverInterop { - driverWriter->writeToDriver(modifier_instance); -} - -void ManagedAccel::ReadFromDriver() + static void GetActiveSettings(IntPtr argsOut) + { + wrapper_io::readFromDriver(*reinterpret_cast<settings*>(argsOut.ToPointer())); + } + + static void SetActiveSettings(IntPtr argsIn) + { + wrapper_io::writeToDriver(*reinterpret_cast<settings*>(argsIn.ToPointer())); + } +}; + +public ref class ManagedAccel { - delete modifier_instance; - modifier_instance = driverWriter->readFromDriver(); -} + mouse_modifier* const modifier_instance = new mouse_modifier(); + +public: + virtual ~ManagedAccel() + { + delete modifier_instance; + } + + !ManagedAccel() + { + delete modifier_instance; + } + + Tuple<double, double>^ Accelerate(int x, int y, double time) + { + vec2d in_out_vec = { + (double)x, + (double)y + }; + modifier_instance->modify(in_out_vec, time); + + return gcnew Tuple<double, double>(in_out_vec.x, in_out_vec.y); + } + + void UpdateFromSettings(IntPtr argsIn) + { + *modifier_instance = { *reinterpret_cast<settings*>(argsIn.ToPointer()) }; + } + + static ManagedAccel^ GetActiveAccel() + { + settings args; + wrapper_io::readFromDriver(args); + + auto active = gcnew ManagedAccel(); + *active->modifier_instance = { args }; + return active; + } +}; diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp deleted file mode 100644 index 3643eb5..0000000 --- a/wrapper/wrapper.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include <iostream> - -#include "wrapper_io.hpp" - -using namespace rawaccel; -using namespace System; - -public ref class ManagedAccel -{ -protected: - mouse_modifier* modifier_instance; - wrapper_io* driverWriter; -public: - ManagedAccel(mouse_modifier* accel) - : modifier_instance(accel) - { - driverWriter = new wrapper_io(); - } - - ManagedAccel(System::IntPtr args) - { - modifier_instance = new mouse_modifier(*reinterpret_cast<modifier_args*>(args.ToPointer())); - driverWriter = new wrapper_io(); - } - - // Empty constructor needed for serialization - ManagedAccel() {} - - virtual ~ManagedAccel() - { - if (modifier_instance!= nullptr) - { - delete modifier_instance; - } - } - !ManagedAccel() - { - if (modifier_instance!= nullptr) - { - delete modifier_instance; - } - } - - // Duplicate all relevant rawaccel struct members here for access and display in GUI - property double SensitivityX { double get(); } - property double SensitivityY { double get(); } - property double Rotation { double get(); } - property int Type { int get(); } - property double Acceleration { double get(); } - property bool GainCapEnabled { bool get(); } - property double CapX { double get(); } - property double CapY { double get(); } - property double GainCap { double get(); } - property double WeightX { double get(); } - property double WeightY { double get(); } - property double Offset { double get(); } - property double LimitExp { double get(); } - property double Midpoint { double get(); } - property double MinimumTime { double get(); } - property double PowerScale { double get(); } - mouse_modifier* GetInstance() - { - return modifier_instance; - } - - Tuple<double, double>^ Accelerate(int x, int y, double time); - - void UpdateAccel( - int mode, - double rotation, - double sensitivityX, - double sensitivityY, - double weightX, - double weightY, - double capX, - double capY, - double offset, - double accel, - double lim_exp, - double midpoint, - double gain_cap); - - - void WriteToDriver(); - - void ReadFromDriver(); -};
\ No newline at end of file diff --git a/wrapper/wrapper.vcxproj b/wrapper/wrapper.vcxproj index 3407d6d..8484c22 100644 --- a/wrapper/wrapper.vcxproj +++ b/wrapper/wrapper.vcxproj @@ -1,14 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -27,20 +19,6 @@ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v142</PlatformToolset> - <CLRSupport>true</CLRSupport> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v142</PlatformToolset> - <CLRSupport>true</CLRSupport> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <ConfigurationType>DynamicLibrary</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> @@ -61,12 +39,6 @@ <ImportGroup Label="Shared"> <Import Project="..\common\common.vcxitems" Label="Shared" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> @@ -85,26 +57,6 @@ <AdditionalDependencies /> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <LanguageStandard>stdcpp17</LanguageStandard> - </ClCompile> - <Link> - <AdditionalDependencies /> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <LanguageStandard>stdcpp17</LanguageStandard> - </ClCompile> - <Link> - <AdditionalDependencies /> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <WarningLevel>Level3</WarningLevel> @@ -116,7 +68,6 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClInclude Include="wrapper.hpp" /> <ClInclude Include="wrapper_io.hpp" /> </ItemGroup> <ItemGroup> diff --git a/wrapper/wrapper.vcxproj.filters b/wrapper/wrapper.vcxproj.filters index 60fcc9c..88e539f 100644 --- a/wrapper/wrapper.vcxproj.filters +++ b/wrapper/wrapper.vcxproj.filters @@ -15,9 +15,6 @@ </Filter> </ItemGroup> <ItemGroup> - <ClInclude Include="wrapper.hpp"> - <Filter>Header Files</Filter> - </ClInclude> <ClInclude Include="wrapper_io.hpp"> <Filter>Header Files</Filter> </ClInclude> diff --git a/wrapper/wrapper_io.cpp b/wrapper/wrapper_io.cpp index 4284d60..3f5673a 100644 --- a/wrapper/wrapper_io.cpp +++ b/wrapper/wrapper_io.cpp @@ -3,16 +3,38 @@ #include <rawaccel-io.hpp> #include "wrapper_io.hpp" -void wrapper_io::writeToDriver(rawaccel::mouse_modifier* modifier) +void wrapper_io::writeToDriver(const settings& args) { - rawaccel::write(*modifier); + try + { + write(args); + } + catch (const cooldown_error&) + { + throw gcnew DriverWriteCDException(); + } + catch (const install_error&) + { + throw gcnew DriverNotInstalledException(); + } + catch (const std::system_error& e) + { + throw gcnew DriverIOException(gcnew String(e.what())); + } } -rawaccel::mouse_modifier* wrapper_io::readFromDriver() +void wrapper_io::readFromDriver(settings& args) { - rawaccel::mouse_modifier modifier = rawaccel::read(); - rawaccel::mouse_modifier* mod_pnt = (rawaccel::mouse_modifier*)malloc(sizeof(rawaccel::mouse_modifier)); - memcpy(mod_pnt, &modifier, sizeof(rawaccel::mouse_modifier)); - - return mod_pnt; + try + { + args = read(); + } + catch (const install_error&) + { + throw gcnew DriverNotInstalledException(); + } + catch (const std::system_error& e) + { + throw gcnew DriverIOException(gcnew String(e.what())); + } } diff --git a/wrapper/wrapper_io.hpp b/wrapper/wrapper_io.hpp index 3427e3f..aff572b 100644 --- a/wrapper/wrapper_io.hpp +++ b/wrapper/wrapper_io.hpp @@ -1,8 +1,21 @@ #pragma once -#include <rawaccel.hpp> +#include <rawaccel-settings.h> + +using namespace rawaccel; +using namespace System; struct wrapper_io { - void writeToDriver(rawaccel::mouse_modifier* modifier); - rawaccel::mouse_modifier* readFromDriver(); -};
\ No newline at end of file + static void writeToDriver(const settings&); + static void readFromDriver(settings&); +}; + +public ref struct DriverIOException : public IO::IOException { +public: + DriverIOException() {} + DriverIOException(String^ what) : IO::IOException(what) {} +}; + +public ref struct DriverNotInstalledException : public DriverIOException {}; + +public ref struct DriverWriteCDException : public DriverIOException {}; |