summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorJacobPalecki <[email protected]>2020-08-31 23:03:46 -0700
committerGitHub <[email protected]>2020-08-31 23:03:46 -0700
commit471fe599bab6ba0632ddd1dacd20c7fc42db0eee (patch)
tree90a82ee14dbb112621657efbd2523ed35f59d154 /common
parentMerge pull request #16 from JacobPalecki/Misc (diff)
parentadd independent xy accel to driver (diff)
downloadrawaccel-471fe599bab6ba0632ddd1dacd20c7fc42db0eee.tar.xz
rawaccel-471fe599bab6ba0632ddd1dacd20c7fc42db0eee.zip
Merge pull request #17 from a1xd/indep
Indep
Diffstat (limited to 'common')
-rw-r--r--common/accel-base.hpp73
-rw-r--r--common/accel-classic.hpp25
-rw-r--r--common/accel-linear.hpp11
-rw-r--r--common/accel-logarithmic.hpp10
-rw-r--r--common/accel-natural.hpp26
-rw-r--r--common/accel-naturalgain.hpp23
-rw-r--r--common/accel-noaccel.hpp7
-rw-r--r--common/accel-power.hpp33
-rw-r--r--common/accel-sigmoid.hpp26
-rw-r--r--common/accel-sigmoidgain.hpp32
-rw-r--r--common/common.vcxitems2
-rw-r--r--common/rawaccel-io.hpp27
-rw-r--r--common/rawaccel-settings.h21
-rw-r--r--common/rawaccel.hpp266
-rw-r--r--common/tagged-union-single.h202
15 files changed, 260 insertions, 524 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...>;