From 3226272a2d49bcbaec72ec735c22b4e0cc2a5c57 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Mon, 27 Jul 2020 19:31:09 -0700 Subject: skeleton --- common/external/tagged-union-single.h | 202 ++++++++++++++++++++++++++++++++++ common/rawaccel-userspace.hpp | 2 +- common/rawaccel.hpp | 192 +++++++++++++++++++++++--------- wrapper/wrapper.cpp | 2 +- wrapper/wrapper.hpp | 2 +- 5 files changed, 342 insertions(+), 58 deletions(-) create mode 100644 common/external/tagged-union-single.h diff --git a/common/external/tagged-union-single.h b/common/external/tagged-union-single.h new file mode 100644 index 0000000..bcfc1cf --- /dev/null +++ b/common/external/tagged-union-single.h @@ -0,0 +1,202 @@ +#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 { typedef T type; }; +template< class T > struct remove_cv { typedef T type; }; +template< class T > struct remove_cv { typedef T type; }; +template< class T > using remove_cv_t = typename remove_cv::type; + +template< class T > struct remove_reference { typedef T type; }; +template< class T > struct remove_reference { typedef T type; }; +template< class T > struct remove_reference { typedef T type; }; +template< class T > using remove_reference_t = typename remove_reference::type; + +template< class T > +struct remove_cvref { + using type = remove_cv_t>; +}; +template< class T > using remove_cvref_t = typename remove_cvref::type; + +namespace detail { + +template struct type_identity { using type = T; }; + +template +auto try_add_lvalue_reference(int)->type_identity; +template +auto try_add_lvalue_reference(...)->type_identity; + +template +auto try_add_rvalue_reference(int)->type_identity; +template +auto try_add_rvalue_reference(...)->type_identity; + +} // type_traits::detail + +template struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference(0)) {}; +template< class T > using add_lvalue_reference_t = typename add_lvalue_reference::type; + +template struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {}; +template< class T > using add_rvalue_reference_t = typename add_rvalue_reference::type; + +template inline constexpr bool is_same_v = false; +template inline constexpr bool is_same_v = true; +template inline constexpr bool is_void_v = is_same_v, void>; + +} // type_traits + +template type_traits::add_rvalue_reference_t declval() noexcept; + +template +inline constexpr T maxv(const T& a, const T& b) { + return (b < a) ? a : b; +} + +template +inline constexpr T minv(const T& a, const T& b) { + return (a < b) ? a : b; +} + +template +inline constexpr T clampv(const T& v, const T& lo, const T& hi) { + return minv(maxv(v, lo), hi); +} + +template +inline constexpr const T& select_ref(bool pred, const T& t, const T& f) { + return pred ? t : f; +} + +template +inline constexpr size_t max_size_of = maxv(sizeof(First), max_size_of); + +template +inline constexpr size_t max_size_of = sizeof(T); + +template +inline constexpr size_t max_align_of = maxv(alignof(First), max_align_of); + +template +inline constexpr size_t max_align_of = alignof(T); + +namespace detail { + +template +struct b1_index_of_impl { + + template + struct idx { + static constexpr size_t value = 0; + }; + + template + struct idx { + static constexpr size_t value = []() { + if constexpr (type_traits::is_same_v) { + return sizeof...(Ts) - sizeof...(Rest); + } + return idx::value; + }(); + }; +}; + +} // detail + +template +inline constexpr int base1_index_of = +detail::b1_index_of_impl::template idx::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 +*/ +template +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 + inline constexpr auto visit(Visitor vis) { + return visit_impl(vis); + } + + template + inline constexpr auto visit(Visitor vis) const { + return visit_impl(vis); + } + + template + static constexpr int id = base1_index_of; + + int tag = 0; + + struct storage_t { + alignas(max_align_of) char bytes[max_size_of]; + + template + inline constexpr T& as() { + static_assert(id != 0, "tagged_union can not hold T"); + return reinterpret_cast(bytes); + } + + template + inline constexpr const T& as() const { + static_assert(id != 0, "tagged_union can not hold T"); + return reinterpret_cast(bytes); + } + + } storage; + + constexpr tagged_union() noexcept = default; + + template + inline constexpr tagged_union(const T& val) noexcept { + tag = id; + storage.template as() = val; + } + + template + inline constexpr tagged_union& operator=(const T& val) noexcept { + tag = id; + storage.template as() = val; + return *this; + } + +private: + template + inline constexpr auto visit_impl(Visitor vis) const { + if (tag == id) { + return vis(storage.template as()); + } + if constexpr (sizeof...(TRest) > 0) { + return visit_impl(vis); + } + else { + using ReturnType = decltype(vis(declval())); + if constexpr (!type_traits::is_void_v) return ReturnType{}; + } + } + + template + inline constexpr auto visit_impl(Visitor vis) { + if (tag == id) { + return vis(storage.template as()); + } + if constexpr (sizeof...(TRest) > 0) { + return visit_impl(vis); + } + else { + using ReturnType = decltype(vis(declval())); + if constexpr (!type_traits::is_void_v) return ReturnType{}; + } + } +}; + +template struct overloaded : Ts... { using Ts::operator()...; }; +template overloaded(Ts...)->overloaded; diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index db50b35..bca6997 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -19,7 +19,7 @@ void error(const char* s) { variables parse(int argc, char** argv) { double degrees = 0; vec2d sens = { 1, 1 }; - accel_function::args_t accel_args{}; + args_t accel_args{}; auto make_opt_vec = [](vec2d& v, auto first_flag, auto... rest) { return clipp::option(first_flag, rest...) & ( diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 095af76..f7f9df7 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -5,6 +5,7 @@ #include "vec2.h" #include "x64-util.hpp" +#include "external/tagged-union-single.h" namespace rawaccel { @@ -55,8 +56,119 @@ struct accel_scale_clamp { void error(const char*); +using milliseconds = double; + +struct args_t { + mode accel_mode = mode::noaccel; + milliseconds time_min = 0.4; + double offset = 0; + double accel = 0; + double lim_exp = 2; + double midpoint = 0; + vec2d weight = { 1, 1 }; + vec2d cap = { 0, 0 }; +}; + +struct accel_implentation { + double b = 0; + double k = 0; + double m = 0; + double offset = 0; + + accel_implentation(args_t args) + { + b = args.accel; + k = args.lim_exp; + m = args.midpoint; + offset = args.offset; + } + + double virtual accelerate(double speed) { return 0; } + void virtual verify(args_t args) { + if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); + if (args.time_min <= 0) error("min time must be positive"); + } + + accel_implentation() = default; +}; + +struct accel_linear : accel_implentation { + accel_linear(args_t args) + : accel_implentation(args) {} + + double virtual accelerate(double speed) override { + return b * speed; + } + + void virtual verify(args_t args) override { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("limit must be greater than 1"); + } +}; + +struct accel_classic : accel_implentation { + accel_classic(args_t args) + : accel_implentation(args) {} + + double virtual accelerate(double speed) override { + return pow(b * speed, k); + + } + + void virtual verify(args_t args) override { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +}; + +struct accel_logarithmic : accel_implentation { + accel_logarithmic(args_t args) + : accel_implentation(args) {} + + double virtual accelerate(double speed) override { + return log(speed * b + 1); + } + + void virtual verify(args_t args) override { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +}; + +struct accel_sigmoid : accel_implentation { + accel_sigmoid(args_t args) + : accel_implentation(args) {} + + double virtual accelerate(double speed) override { + return k / (exp(-b * (speed - m)) + 1); + + } + + void virtual verify(args_t args) override { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +}; + +struct accel_power : accel_implentation { + accel_power(args_t args) + : accel_implentation(args) {} + + double virtual accelerate(double speed) override { + return (offset > 0 && speed < 1) ? 0 : pow(speed*b, k) - 1; + + + } + + void virtual verify(args_t args) override { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +}; + +using accel_implementation_t = tagged_union; + struct accel_function { - using milliseconds = double; /* This value is ideally a few microseconds lower than @@ -77,63 +189,13 @@ struct accel_function { // or the exponent for classic and power modes double k = 1; + accel_implementation_t accel = accel_implentation{}; + vec2d weight = { 1, 1 }; vec2 clamp; - inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { - double mag = sqrtsd(input.x * input.x + input.y * input.y); - double time_clamped = clampsd(time, time_min, 100); - double speed = maxsd(mag / time_clamped - speed_offset, 0); - - double accel_val = 0; - - switch (accel_mode) { - case mode::linear: accel_val = b * speed; - break; - case mode::classic: accel_val = pow(b * speed, k); - break; - case mode::natural: accel_val = k - (k * exp(-b * speed)); - break; - case mode::logarithmic: accel_val = log(speed * b + 1); - break; - case mode::sigmoid: accel_val = k / (exp(-b * (speed - m)) + 1); - break; - case mode::power: accel_val = (speed_offset > 0 && speed < 1) ? 0 : pow(speed*b, k) - 1; - break; - default: - break; - } - - double scale_x = weight.x * accel_val + 1; - double scale_y = weight.y * accel_val + 1; - - return { - input.x * clamp.x(scale_x), - input.y * clamp.y(scale_y) - }; - } - - struct args_t { - mode accel_mode = mode::noaccel; - milliseconds time_min = 0.4; - double offset = 0; - double accel = 0; - double lim_exp = 2; - double midpoint = 0; - vec2d weight = { 1, 1 }; - vec2d cap = { 0, 0 }; - }; - accel_function(args_t args) { - // Preconditions to guard against division by zero and - // ensure the C math functions can not return NaN or -Inf. - if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); - if (args.time_min <= 0) error("min time must be positive"); - if (args.lim_exp <= 1) { - if (args.accel_mode == mode::classic) error("exponent must be greater than 1"); - if (args.accel_mode == mode::power) { if (args.lim_exp <=0 ) error("exponent must be greater than 0"); } - else error("limit must be greater than 1"); - } + accel = accel_linear(args); time_min = args.time_min; m = args.midpoint; @@ -148,6 +210,26 @@ struct accel_function { clamp.y = accel_scale_clamp(args.cap.y); } + double apply(double speed) const { + return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); + } + + inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { + double mag = sqrtsd(input.x * input.x + input.y * input.y); + double time_clamped = clampsd(time, time_min, 100); + double speed = maxsd(mag / time_clamped - speed_offset, 0); + + double accel_val = apply(speed); + + double scale_x = weight.x * accel_val + 1; + double scale_y = weight.y * accel_val + 1; + + return { + input.x * clamp.x(scale_x), + input.y * clamp.y(scale_y) + }; + } + accel_function() = default; }; @@ -159,7 +241,7 @@ struct variables { accel_function accel_fn; vec2d sensitivity = { 1, 1 }; - variables(double degrees, vec2d sens, accel_function::args_t accel_args) + variables(double degrees, vec2d sens, args_t accel_args) : accel_fn(accel_args) { apply_rotate = degrees != 0; diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index df3f796..f3d069a 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -8,7 +8,7 @@ using namespace System; Tuple^ ManagedAccel::Accelerate(int x, int y, double time, double mode) { vec2d input_vec2d = {x, y}; - vec2d output = (*accel_instance)(input_vec2d, (accel_function::milliseconds)time, (rawaccel::mode)mode); + vec2d output = (*accel_instance)(input_vec2d, (milliseconds)time, (rawaccel::mode)mode); return gcnew Tuple(output.x, output.y); } \ No newline at end of file diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 24bcadb..a5699ac 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -18,7 +18,7 @@ public: ManagedAccel(double mode, double offset, double accel, double lim_exp, double midpoint) { - accel_function::args_t args{}; + args_t args{}; args.accel = accel; args.lim_exp = lim_exp; args.midpoint = midpoint; -- cgit v1.2.3 From 894a13926f79e209e3b619012cd2bb6961d959e2 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 01:53:32 -0700 Subject: Further refactoring and comments --- common/Error.hpp | 10 + common/common.vcxitems | 1 + common/rawaccel.hpp | 546 ++++++++++++++++++++++++++++--------------------- wrapper/wrapper.hpp | 2 +- 4 files changed, 323 insertions(+), 236 deletions(-) create mode 100644 common/Error.hpp diff --git a/common/Error.hpp b/common/Error.hpp new file mode 100644 index 0000000..ed87090 --- /dev/null +++ b/common/Error.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + + +namespace rawaccel { + void error(const char* s) { + throw std::domain_error(s); + } +} diff --git a/common/common.vcxitems b/common/common.vcxitems index f60f78a..224792c 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -14,6 +14,7 @@ + diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index f7f9df7..3380e4c 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -7,256 +7,332 @@ #include "x64-util.hpp" #include "external/tagged-union-single.h" -namespace rawaccel { +namespace rawaccel { -enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; + enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; -struct rotator { - vec2d rot_vec = { 1, 0 }; + struct rotator { + vec2d rot_vec = { 1, 0 }; - inline vec2d operator()(const vec2d& input) const { - return { - input.x * rot_vec.x - input.y * rot_vec.y, - input.x * rot_vec.y + input.y * rot_vec.x - }; - } + inline vec2d operator()(const vec2d& input) const { + return { + input.x * rot_vec.x - input.y * rot_vec.y, + input.x * rot_vec.y + input.y * rot_vec.x + }; + } - rotator(double degrees) { - double rads = degrees * M_PI / 180; - rot_vec = { cos(rads), sin(rads) }; - } + rotator(double degrees) { + double rads = degrees * M_PI / 180; + rot_vec = { cos(rads), sin(rads) }; + } - rotator() = default; -}; + rotator() = default; + }; -struct accel_scale_clamp { - double lo = 0; - double hi = 9; + struct accel_scale_clamp { + double lo = 0; + double hi = 9; - inline double operator()(double scale) const { - return clampsd(scale, lo, hi); - } + inline double operator()(double scale) const { + return clampsd(scale, lo, hi); + } - accel_scale_clamp(double cap) : accel_scale_clamp() { - if (cap <= 0) { - // use default, effectively uncapped accel - return; + accel_scale_clamp(double cap) : accel_scale_clamp() { + if (cap <= 0) { + // use default, effectively uncapped accel + return; + } + + if (cap < 1) { + // assume negative accel + lo = cap; + hi = 1; + } + else hi = cap; } - if (cap < 1) { - // assume negative accel - lo = cap; - hi = 1; + accel_scale_clamp() = default; + }; + +#ifdef _KERNEL_MODE + void error(const char*) {} +#else + void error(const char* s); +#endif + + using milliseconds = double; + + struct args_t { + mode accel_mode = mode::noaccel; + milliseconds time_min = 0.4; + double offset = 0; + double accel = 0; + double lim_exp = 2; + double midpoint = 0; + vec2d weight = { 1, 1 }; + vec2d cap = { 0, 0 }; + }; + + /// + /// Struct to hold acceleration implementation details. + /// + /// Type of acceleration. + template + struct accel_implentation { + + /// The acceleration ramp rate. + double b = 0; + + /// The limit or exponent for various modes. + double k = 0; + + /// The midpoint in sigmoid mode. + double m = 0; + + /// The offset past which acceleration is applied. Used in power mode. + double offset = 0; + + /// + /// Initializes a new instance of the struct. + /// + /// + /// + accel_implentation(args_t args) + { + b = args.accel; + k = args.lim_exp - 1; + m = args.midpoint; + offset = args.offset; + } + + /// + /// Returns accelerated value of speed as a ratio of magnitude. + /// + /// Mouse speed at which to calculate acceleration. + /// Ratio of accelerated movement magnitude to input movement magnitude. + double accelerate(double speed) { return 0; } + + /// + /// Verifies arguments as valid. Errors if not. + /// + /// Arguments to verified. + void verify(args_t args) { + if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); + if (args.time_min <= 0) error("min time must be positive"); } - else hi = cap; - } - - accel_scale_clamp() = default; -}; - -void error(const char*); - -using milliseconds = double; - -struct args_t { - mode accel_mode = mode::noaccel; - milliseconds time_min = 0.4; - double offset = 0; - double accel = 0; - double lim_exp = 2; - double midpoint = 0; - vec2d weight = { 1, 1 }; - vec2d cap = { 0, 0 }; -}; - -struct accel_implentation { - double b = 0; - double k = 0; - double m = 0; - double offset = 0; - - accel_implentation(args_t args) - { - b = args.accel; - k = args.lim_exp; - m = args.midpoint; - offset = args.offset; - } - - double virtual accelerate(double speed) { return 0; } - void virtual verify(args_t args) { - if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); - if (args.time_min <= 0) error("min time must be positive"); - } - - accel_implentation() = default; -}; - -struct accel_linear : accel_implentation { - accel_linear(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return b * speed; - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("limit must be greater than 1"); - } -}; - -struct accel_classic : accel_implentation { - accel_classic(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return pow(b * speed, k); - - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -struct accel_logarithmic : accel_implentation { - accel_logarithmic(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return log(speed * b + 1); - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -struct accel_sigmoid : accel_implentation { - accel_sigmoid(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return k / (exp(-b * (speed - m)) + 1); - - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -struct accel_power : accel_implentation { - accel_power(args_t args) - : accel_implentation(args) {} - - double virtual accelerate(double speed) override { - return (offset > 0 && speed < 1) ? 0 : pow(speed*b, k) - 1; - - - } - - void virtual verify(args_t args) override { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -}; - -using accel_implementation_t = tagged_union; - -struct accel_function { - - /* - This value is ideally a few microseconds lower than - the user's mouse polling interval, though it should - not matter if the system is stable. - */ - milliseconds time_min = 0.4; - - double speed_offset = 0; - // speed midpoint in sigmoid mode - double m = 0; + /// + /// + /// + /// + accel_implentation() = default; + }; + + /// Struct to hold linear acceleration implementation. + struct accel_linear : accel_implentation { + + accel_linear(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + //f(x) = mx + return b * speed; + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("limit must be greater than 1"); + } + }; - // accel ramp rate - double b = 0; + /// Struct to hold "classic" (linear raised to power) acceleration implementation. + struct accel_classic : accel_implentation { + accel_classic(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + //f(x) = (mx)^k + return pow(b * speed, k); + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// Struct to hold "natural" (vanishing difference) acceleration implementation. + struct accel_natural : accel_implentation { + accel_natural(args_t args) + : accel_implentation(args) + { b /= k; } + + double accelerate(double speed) { + // f(x) = k(1-e^(-mx)) + return k - (k * exp(-b * speed));; + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// Struct to hold logarithmic acceleration implementation. + struct accel_logarithmic : accel_implentation { + accel_logarithmic(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + return log(speed * b + 1); + } - // the limit for natural and sigmoid modes - // or the exponent for classic and power modes - double k = 1; + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// Struct to hold sigmoid (s-shaped) acceleration implementation. + struct accel_sigmoid : accel_implentation { + accel_sigmoid(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { + //f(x) = k/(1+e^(-m(c-x))) + return k / (exp(-b * (speed - m)) + 1); + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } + }; + + /// Struct to hold power (non-additive) acceleration implementation. + struct accel_power : accel_implentation { + accel_power(args_t args) + : accel_implentation(args) + { k++; } + + double accelerate(double speed) { + //f(x) = (mx)^k - 1 + // The subtraction of 1 is with later addition of 1 in mind, + // so that the input vector is directly multiplied by (mx)^k (if unweighted) + return (offset > 0 && speed < 1) ? 0 : pow(speed * b, k) - 1; + } + + void verify(args_t args) { + accel_implentation::verify(args); + if (args.lim_exp <= 0) error("exponent must be greater than 0"); + } + }; + + /// Struct to hold acceleration implementation which applies no acceleration. + struct accel_noaccel : accel_implentation { + accel_noaccel(args_t args) + : accel_implentation(args) {} + + double accelerate(double speed) { return 0; } + + void verify(args_t args) {} + }; - accel_implementation_t accel = accel_implentation{}; + using accel_implementation_t = tagged_union; + + struct accel_function { + + /* + This value is ideally a few microseconds lower than + the user's mouse polling interval, though it should + not matter if the system is stable. + */ + milliseconds time_min = 0.4; + + /// The offset past which acceleration is applied. + double speed_offset = 0; + + accel_implementation_t accel; + + vec2d weight = { 1, 1 }; + vec2 clamp; + + accel_function(args_t args) { + switch (args.accel_mode) + { + case mode::linear: accel = accel_linear(args); + break; + case mode::classic: accel = accel_classic(args); + break; + case mode::natural: accel = accel_natural(args); + break; + case mode::logarithmic: accel = accel_logarithmic(args); + break; + case mode::sigmoid: accel = accel_sigmoid(args); + break; + case mode::power: accel = accel_power(args); + } + + verify(args); + + time_min = args.time_min; + speed_offset = args.offset; + weight = args.weight; + clamp.x = accel_scale_clamp(args.cap.x); + clamp.y = accel_scale_clamp(args.cap.y); + } + + double apply(double speed) const { + return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); + } - vec2d weight = { 1, 1 }; - vec2 clamp; + void verify(args_t args) const { + return accel.visit([=](auto accel_t) { accel_t.verify(args); }); + } - accel_function(args_t args) { - accel = accel_linear(args); + inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { + double mag = sqrtsd(input.x * input.x + input.y * input.y); + double time_clamped = clampsd(time, time_min, 100); + double speed = maxsd(mag / time_clamped - speed_offset, 0); - time_min = args.time_min; - m = args.midpoint; - b = args.accel; - k = args.lim_exp - 1; - if (args.accel_mode == mode::natural) b /= k; - if (args.accel_mode == mode::power) k++; - - speed_offset = args.offset; - weight = args.weight; - clamp.x = accel_scale_clamp(args.cap.x); - clamp.y = accel_scale_clamp(args.cap.y); - } - - double apply(double speed) const { - return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); - } - - inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { - double mag = sqrtsd(input.x * input.x + input.y * input.y); - double time_clamped = clampsd(time, time_min, 100); - double speed = maxsd(mag / time_clamped - speed_offset, 0); - - double accel_val = apply(speed); - - double scale_x = weight.x * accel_val + 1; - double scale_y = weight.y * accel_val + 1; - - return { - input.x * clamp.x(scale_x), - input.y * clamp.y(scale_y) - }; - } - - accel_function() = default; -}; - -struct variables { - bool apply_rotate = false; - bool apply_accel = false; - mode accel_mode = mode::noaccel; - rotator rotate; - accel_function accel_fn; - vec2d sensitivity = { 1, 1 }; - - variables(double degrees, vec2d sens, args_t accel_args) - : accel_fn(accel_args) - { - apply_rotate = degrees != 0; - if (apply_rotate) rotate = rotator(degrees); - else rotate = rotator(); - - apply_accel = accel_args.accel_mode != mode::noaccel; - accel_mode = accel_args.accel_mode; - - if (sens.x == 0) sens.x = 1; - if (sens.y == 0) sens.y = 1; - sensitivity = sens; - } - - variables() = default; -}; - -} // rawaccel + double accel_val = apply(speed); + + double scale_x = weight.x * accel_val + 1; + double scale_y = weight.y * accel_val + 1; + + return { + input.x * clamp.x(scale_x), + input.y * clamp.y(scale_y) + }; + } + + accel_function() = default; + }; + + struct variables { + bool apply_rotate = false; + bool apply_accel = false; + mode accel_mode = mode::noaccel; + rotator rotate; + accel_function accel_fn; + vec2d sensitivity = { 1, 1 }; + + variables(double degrees, vec2d sens, args_t accel_args) + : accel_fn(accel_args) + { + apply_rotate = degrees != 0; + if (apply_rotate) rotate = rotator(degrees); + else rotate = rotator(); + + apply_accel = accel_args.accel_mode != mode::noaccel; + accel_mode = accel_args.accel_mode; + + if (sens.x == 0) sens.x = 1; + if (sens.y == 0) sens.y = 1; + sensitivity = sens; + } + + variables() = default; + }; + +} // rawaccel \ No newline at end of file diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index a5699ac..e9bbf2e 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -1,7 +1,7 @@ #pragma once #include "..\common\rawaccel.hpp"; -#include "..\common\rawaccel-userspace.hpp"; +#include "..\common\error.hpp"; #include using namespace rawaccel; using namespace System; -- cgit v1.2.3 From f7a1883e4d26ebb2904518236656d53d8b5645b7 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 02:09:21 -0700 Subject: Remove extra mode from variables --- common/rawaccel.hpp | 4 +--- driver/driver.cpp | 2 +- wrapper/wrapper.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 3380e4c..28d9ee2 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -290,7 +290,7 @@ namespace rawaccel { return accel.visit([=](auto accel_t) { accel_t.verify(args); }); } - inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const { + inline vec2d operator()(const vec2d& input, milliseconds time) const { double mag = sqrtsd(input.x * input.x + input.y * input.y); double time_clamped = clampsd(time, time_min, 100); double speed = maxsd(mag / time_clamped - speed_offset, 0); @@ -312,7 +312,6 @@ namespace rawaccel { struct variables { bool apply_rotate = false; bool apply_accel = false; - mode accel_mode = mode::noaccel; rotator rotate; accel_function accel_fn; vec2d sensitivity = { 1, 1 }; @@ -325,7 +324,6 @@ namespace rawaccel { else rotate = rotator(); apply_accel = accel_args.accel_mode != mode::noaccel; - accel_mode = accel_args.accel_mode; if (sens.x == 0) sens.x = 1; if (sens.y == 0) sens.y = 1; diff --git a/driver/driver.cpp b/driver/driver.cpp index e77ac5f..5523f28 100644 --- a/driver/driver.cpp +++ b/driver/driver.cpp @@ -83,7 +83,7 @@ Arguments: DebugPrint(("RA time < min with %d ticks\n", ticks)); } - input = global.vars.accel_fn(input, time, global.vars.accel_mode); + input = global.vars.accel_fn(input, time); } double result_x = input.x * global.vars.sensitivity.x + local_carry.x; diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index f3d069a..2c004e4 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -8,7 +8,7 @@ using namespace System; Tuple^ ManagedAccel::Accelerate(int x, int y, double time, double mode) { vec2d input_vec2d = {x, y}; - vec2d output = (*accel_instance)(input_vec2d, (milliseconds)time, (rawaccel::mode)mode); + vec2d output = (*accel_instance)(input_vec2d, (milliseconds)time); return gcnew Tuple(output.x, output.y); } \ No newline at end of file -- cgit v1.2.3 From b1ef35050600978318581586691f5a8f119abf5b Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 02:44:09 -0700 Subject: Rename variables and add modify functions --- common/rawaccel-userspace.hpp | 4 ++-- common/rawaccel.hpp | 19 ++++++++++++++++--- console/console.cpp | 4 ++-- driver/driver.cpp | 26 +++++++++++++------------- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index bca6997..d0722b6 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -16,7 +16,7 @@ void error(const char* s) { throw std::domain_error(s); } -variables parse(int argc, char** argv) { +mouse_modifier parse(int argc, char** argv) { double degrees = 0; vec2d sens = { 1, 1 }; args_t accel_args{}; @@ -121,7 +121,7 @@ variables parse(int argc, char** argv) { std::exit(0); } - return variables(-degrees, sens, accel_args); + return mouse_modifier(-degrees, sens, accel_args); } } // rawaccel diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 28d9ee2..9b35568 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -309,14 +309,14 @@ namespace rawaccel { accel_function() = default; }; - struct variables { + struct mouse_modifier { bool apply_rotate = false; bool apply_accel = false; rotator rotate; accel_function accel_fn; vec2d sensitivity = { 1, 1 }; - variables(double degrees, vec2d sens, args_t accel_args) + mouse_modifier(double degrees, vec2d sens, args_t accel_args) : accel_fn(accel_args) { apply_rotate = degrees != 0; @@ -330,7 +330,20 @@ namespace rawaccel { sensitivity = sens; } - variables() = default; + vec2d modify(vec2d input) + { + if (apply_rotate) + { + return rotate(input); + } + } + + vec2d modify(vec2d input, milliseconds time) + { + return accel_fn(modify(input), time); + } + + mouse_modifier() = default; }; } // rawaccel \ No newline at end of file diff --git a/console/console.cpp b/console/console.cpp index 6606cac..490051c 100644 --- a/console/console.cpp +++ b/console/console.cpp @@ -9,7 +9,7 @@ namespace ra = rawaccel; -void write(ra::variables vars) { +void write(ra::mouse_modifier vars) { HANDLE ra_handle = INVALID_HANDLE_VALUE; ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0); @@ -24,7 +24,7 @@ void write(ra::variables vars) { ra_handle, RA_WRITE, &vars, - sizeof(ra::variables), + sizeof(ra::mouse_modifier), NULL, // output buffer 0, // output buffer size &dummy, // bytes returned diff --git a/driver/driver.cpp b/driver/driver.cpp index 5523f28..9704b21 100644 --- a/driver/driver.cpp +++ b/driver/driver.cpp @@ -15,7 +15,7 @@ using milliseconds = double; struct { milliseconds tick_interval = 0; // set in DriverEntry - ra::variables vars; + ra::mouse_modifier modifier; } global; VOID @@ -69,25 +69,25 @@ Arguments: static_cast(it->LastY) }; - if (global.vars.apply_rotate) { - input = global.vars.rotate(input); - } - - if (global.vars.apply_accel && local_apply_accel) { + if (global.modifier.apply_accel && local_apply_accel) { auto now = KeQueryPerformanceCounter(NULL).QuadPart; auto ticks = now - devExt->counter.QuadPart; devExt->counter.QuadPart = now; milliseconds time = ticks * global.tick_interval; - if (time < global.vars.accel_fn.time_min) { + if (time < global.modifier.accel_fn.time_min) { DebugPrint(("RA time < min with %d ticks\n", ticks)); } - input = global.vars.accel_fn(input, time); + input = global.modifier.modify(input, time); + } + else + { + input = global.modifier.modify(input); } - double result_x = input.x * global.vars.sensitivity.x + local_carry.x; - double result_y = input.y * global.vars.sensitivity.y + local_carry.y; + double result_x = input.x * global.modifier.sensitivity.x + local_carry.x; + double result_y = input.y * global.modifier.sensitivity.y + local_carry.y; LONG out_x = static_cast(result_x); LONG out_y = static_cast(result_y); @@ -154,7 +154,7 @@ Return Value: DebugPrint(("Ioctl received into filter control object.\n")); - if (InputBufferLength != sizeof(ra::variables)) { + if (InputBufferLength != sizeof(ra::mouse_modifier)) { DebugPrint(("Received unknown request of %u bytes\n", InputBufferLength)); // status maps to win32 error code 1784: ERROR_INVALID_USER_BUFFER WdfRequestComplete(Request, STATUS_INVALID_BUFFER_SIZE); @@ -163,7 +163,7 @@ Return Value: status = WdfRequestRetrieveInputBuffer( Request, - sizeof(ra::variables), + sizeof(ra::mouse_modifier), &input_buffer, &input_size ); @@ -175,7 +175,7 @@ Return Value: return; } - global.vars = *reinterpret_cast(input_buffer); + global.modifier = *reinterpret_cast(input_buffer); WdfRequestComplete(Request, STATUS_SUCCESS); } -- cgit v1.2.3 From 41a2448dc9a76b7d39e86cc5ee3b1d6a1583ba72 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 13:25:53 -0700 Subject: Fix not all paths returning value --- common/rawaccel.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 9b35568..9d4b5e3 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -330,15 +330,17 @@ namespace rawaccel { sensitivity = sens; } - vec2d modify(vec2d input) + inline vec2d modify(vec2d input) { if (apply_rotate) { return rotate(input); } + + return input; } - vec2d modify(vec2d input, milliseconds time) + inline vec2d modify(vec2d input, milliseconds time) { return accel_fn(modify(input), time); } -- cgit v1.2.3 From 9e55978ad8b8da90bb30407047b399e9c430c070 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 14:54:31 -0700 Subject: More comments and light refactoring --- common/rawaccel.hpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++--- grapher/Form1.cs | 4 ++-- wrapper/wrapper.cpp | 2 +- wrapper/wrapper.hpp | 2 +- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 9d4b5e3..2b45c06 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -9,11 +9,20 @@ namespace rawaccel { + /// Enum to hold acceleration implementation types (i.e. types of curves.) enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; + /// Struct to hold vector rotation details. struct rotator { + + /// Rotational vector, which points in the direction of the post-rotation positive y axis. vec2d rot_vec = { 1, 0 }; + /// + /// Rotates given input vector according to struct's rotational vector. + /// + /// Input vector to be rotated + /// 2d vector of rotated input. inline vec2d operator()(const vec2d& input) const { return { input.x * rot_vec.x - input.y * rot_vec.y, @@ -29,10 +38,16 @@ namespace rawaccel { rotator() = default; }; + /// Struct to hold clamp (min and max) details for acceleration application struct accel_scale_clamp { double lo = 0; double hi = 9; + /// + /// Clamps given input to min at lo, max at hi. + /// + /// Double to be clamped + /// Clamped input as double inline double operator()(double scale) const { return clampsd(scale, lo, hi); } @@ -54,6 +69,7 @@ namespace rawaccel { accel_scale_clamp() = default; }; +// Error throwing calls std libraries which are unavailable in kernel mode. #ifdef _KERNEL_MODE void error(const char*) {} #else @@ -62,6 +78,7 @@ namespace rawaccel { using milliseconds = double; + /// Struct to hold arguments for an acceleration function. struct args_t { mode accel_mode = mode::noaccel; milliseconds time_min = 0.4; @@ -74,7 +91,7 @@ namespace rawaccel { }; /// - /// Struct to hold acceleration implementation details. + /// Struct to hold acceleration curve implementation details. /// /// Type of acceleration. template @@ -216,8 +233,8 @@ namespace rawaccel { { k++; } double accelerate(double speed) { - //f(x) = (mx)^k - 1 - // The subtraction of 1 is with later addition of 1 in mind, + // f(x) = (mx)^k - 1 + // The subtraction of 1 occurs with later addition of 1 in mind, // so that the input vector is directly multiplied by (mx)^k (if unweighted) return (offset > 0 && speed < 1) ? 0 : pow(speed * b, k) - 1; } @@ -238,8 +255,10 @@ namespace rawaccel { void verify(args_t args) {} }; + /// Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. using accel_implementation_t = tagged_union; + /// Struct for holding acceleration application details. struct accel_function { /* @@ -247,14 +266,19 @@ namespace rawaccel { the user's mouse polling interval, though it should not matter if the system is stable. */ + /// The minimum time period for one mouse movement. milliseconds time_min = 0.4; /// The offset past which acceleration is applied. double speed_offset = 0; + /// The acceleration implementation (i.e. curve) accel_implementation_t accel; + /// The weight of acceleration applied in {x, y} dimensions. vec2d weight = { 1, 1 }; + + /// The object which sets a min and max for the acceleration scale. vec2 clamp; accel_function(args_t args) { @@ -273,6 +297,8 @@ namespace rawaccel { case mode::power: accel = accel_power(args); } + // Verification is performed by the accel_implementation object + // and therefore must occur after the object has been instantiated verify(args); time_min = args.time_min; @@ -282,14 +308,29 @@ namespace rawaccel { clamp.y = accel_scale_clamp(args.cap.y); } + /// + /// Applies mouse acceleration to a given speed, via visitor function to accel_implementation_t + /// + /// Speed from which to determine acceleration + /// Acceleration as a ratio magnitudes, as a double double apply(double speed) const { return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); } + /// + /// Verifies acceleration arguments, via visitor function to accel_implementation_t + /// + /// Arguments to be verified void verify(args_t args) const { return accel.visit([=](auto accel_t) { accel_t.verify(args); }); } + /// + /// Applies weighted acceleration to given input for given time period. + /// + /// 2d vector of {x, y} mouse movement to be accelerated + /// Time period over which input movement was accumulated + /// 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); @@ -309,6 +350,7 @@ namespace rawaccel { accel_function() = default; }; + /// Struct to hold variables and methods for modifying mouse input struct mouse_modifier { bool apply_rotate = false; bool apply_accel = false; @@ -330,6 +372,12 @@ namespace rawaccel { sensitivity = sens; } + /// + /// Applies modification without acceleration. Rotation is the only + /// modification currently implemented. + /// + /// Input to be modified. + /// 2d vector of modified input. inline vec2d modify(vec2d input) { if (apply_rotate) @@ -340,6 +388,12 @@ namespace rawaccel { return input; } + /// + /// Applies modification, including acceleration. + /// + /// Input to be modified + /// Time period for determining acceleration. + /// 2d vector with modified input. inline vec2d modify(vec2d input, milliseconds time) { return accel_fn(modify(input), time); diff --git a/grapher/Form1.cs b/grapher/Form1.cs index 1915b01..4165b0f 100644 --- a/grapher/Form1.cs +++ b/grapher/Form1.cs @@ -15,14 +15,14 @@ namespace grapher public RawAcceleration() { InitializeComponent(); - var managedAccel = new ManagedAccel(6, 0, 1, 0.025, 0); + var managedAccel = new ManagedAccel(6, 0, 1.333, 0.05, 0); var orderedPoints = new SortedDictionary(); for (int i = 0; i < 100; i++) { for (int j = 0; j <= i; j++) { - var output = managedAccel.Accelerate(i, j, 1, 6); + var output = managedAccel.Accelerate(i, j, 1); var inMagnitude = Magnitude(i,j); var outMagnitude = Magnitude(output.Item1, output.Item2); diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 2c004e4..1adafba 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -5,7 +5,7 @@ using namespace rawaccel; using namespace System; -Tuple^ ManagedAccel::Accelerate(int x, int y, double time, double mode) +Tuple^ ManagedAccel::Accelerate(int x, int y, double time) { vec2d input_vec2d = {x, y}; vec2d output = (*accel_instance)(input_vec2d, (milliseconds)time); diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index e9bbf2e..0307b4c 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -48,5 +48,5 @@ public: return accel_instance; } - Tuple^ Accelerate(int x, int y, double time, double mode); + Tuple^ Accelerate(int x, int y, double time); }; \ No newline at end of file -- cgit v1.2.3 From 06d6d8d3e3cb5186daab029f2d7c7fa3ea0438d2 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 15:25:41 -0700 Subject: Rename acceleration constants, arguments --- common/rawaccel-userspace.hpp | 2 +- common/rawaccel.hpp | 74 +++++++++++++++++++++---------------------- wrapper/wrapper.hpp | 2 +- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index d0722b6..5996364 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -19,7 +19,7 @@ void error(const char* s) { mouse_modifier parse(int argc, char** argv) { double degrees = 0; vec2d sens = { 1, 1 }; - args_t accel_args{}; + accel_args accel_args{}; auto make_opt_vec = [](vec2d& v, auto first_flag, auto... rest) { return clipp::option(first_flag, rest...) & ( diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 2b45c06..e904350 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -79,7 +79,7 @@ namespace rawaccel { using milliseconds = double; /// Struct to hold arguments for an acceleration function. - struct args_t { + struct accel_args { mode accel_mode = mode::noaccel; milliseconds time_min = 0.4; double offset = 0; @@ -97,14 +97,14 @@ namespace rawaccel { template struct accel_implentation { - /// The acceleration ramp rate. - double b = 0; + /// First constant for use in acceleration curves. Generally, the acceleration ramp rate. + double curve_constant_one = 0; - /// The limit or exponent for various modes. - double k = 0; + /// Second constant for use in acceleration curves. Generally, the limit or exponent in the curve. + double curve_constant_two = 0; - /// The midpoint in sigmoid mode. - double m = 0; + /// Third constant for use in acceleration curves. The midpoint in sigmoid mode. + double curve_constant_three = 0; /// The offset past which acceleration is applied. Used in power mode. double offset = 0; @@ -114,11 +114,11 @@ namespace rawaccel { /// /// /// - accel_implentation(args_t args) + accel_implentation(accel_args args) { - b = args.accel; - k = args.lim_exp - 1; - m = args.midpoint; + curve_constant_one = args.accel; + curve_constant_two = args.lim_exp - 1; + curve_constant_three = args.midpoint; offset = args.offset; } @@ -133,7 +133,7 @@ namespace rawaccel { /// Verifies arguments as valid. Errors if not. /// /// Arguments to verified. - void verify(args_t args) { + void verify(accel_args args) { if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); if (args.time_min <= 0) error("min time must be positive"); } @@ -148,15 +148,15 @@ namespace rawaccel { /// Struct to hold linear acceleration implementation. struct accel_linear : accel_implentation { - accel_linear(args_t args) + accel_linear(accel_args args) : accel_implentation(args) {} double accelerate(double speed) { //f(x) = mx - return b * speed; + return curve_constant_one * speed; } - void verify(args_t args) { + void verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("limit must be greater than 1"); } @@ -164,15 +164,15 @@ namespace rawaccel { /// Struct to hold "classic" (linear raised to power) acceleration implementation. struct accel_classic : accel_implentation { - accel_classic(args_t args) + accel_classic(accel_args args) : accel_implentation(args) {} double accelerate(double speed) { //f(x) = (mx)^k - return pow(b * speed, k); + return pow(curve_constant_one * speed, curve_constant_two); } - void verify(args_t args) { + void verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } @@ -180,16 +180,16 @@ namespace rawaccel { /// Struct to hold "natural" (vanishing difference) acceleration implementation. struct accel_natural : accel_implentation { - accel_natural(args_t args) + accel_natural(accel_args args) : accel_implentation(args) - { b /= k; } + { curve_constant_one /= curve_constant_two; } double accelerate(double speed) { // f(x) = k(1-e^(-mx)) - return k - (k * exp(-b * speed));; + return curve_constant_two - (curve_constant_two * exp(-curve_constant_one * speed));; } - void verify(args_t args) { + void verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } @@ -197,14 +197,14 @@ namespace rawaccel { /// Struct to hold logarithmic acceleration implementation. struct accel_logarithmic : accel_implentation { - accel_logarithmic(args_t args) + accel_logarithmic(accel_args args) : accel_implentation(args) {} double accelerate(double speed) { - return log(speed * b + 1); + return log(speed * curve_constant_one + 1); } - void verify(args_t args) { + void verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } @@ -212,15 +212,15 @@ namespace rawaccel { /// Struct to hold sigmoid (s-shaped) acceleration implementation. struct accel_sigmoid : accel_implentation { - accel_sigmoid(args_t args) + accel_sigmoid(accel_args args) : accel_implentation(args) {} double accelerate(double speed) { //f(x) = k/(1+e^(-m(c-x))) - return k / (exp(-b * (speed - m)) + 1); + return curve_constant_two / (exp(-curve_constant_one * (speed - curve_constant_three)) + 1); } - void verify(args_t args) { + void verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } @@ -228,18 +228,18 @@ namespace rawaccel { /// Struct to hold power (non-additive) acceleration implementation. struct accel_power : accel_implentation { - accel_power(args_t args) + accel_power(accel_args args) : accel_implentation(args) - { k++; } + { curve_constant_two++; } double accelerate(double speed) { // f(x) = (mx)^k - 1 // The subtraction of 1 occurs with later addition of 1 in mind, // so that the input vector is directly multiplied by (mx)^k (if unweighted) - return (offset > 0 && speed < 1) ? 0 : pow(speed * b, k) - 1; + return (offset > 0 && speed < 1) ? 0 : pow(speed * curve_constant_one, curve_constant_two) - 1; } - void verify(args_t args) { + void verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 0) error("exponent must be greater than 0"); } @@ -247,12 +247,12 @@ namespace rawaccel { /// Struct to hold acceleration implementation which applies no acceleration. struct accel_noaccel : accel_implentation { - accel_noaccel(args_t args) + accel_noaccel(accel_args args) : accel_implentation(args) {} double accelerate(double speed) { return 0; } - void verify(args_t args) {} + void verify(accel_args args) {} }; /// Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. @@ -281,7 +281,7 @@ namespace rawaccel { /// The object which sets a min and max for the acceleration scale. vec2 clamp; - accel_function(args_t args) { + accel_function(accel_args args) { switch (args.accel_mode) { case mode::linear: accel = accel_linear(args); @@ -321,7 +321,7 @@ namespace rawaccel { /// Verifies acceleration arguments, via visitor function to accel_implementation_t /// /// Arguments to be verified - void verify(args_t args) const { + void verify(accel_args args) const { return accel.visit([=](auto accel_t) { accel_t.verify(args); }); } @@ -358,7 +358,7 @@ namespace rawaccel { accel_function accel_fn; vec2d sensitivity = { 1, 1 }; - mouse_modifier(double degrees, vec2d sens, args_t accel_args) + mouse_modifier(double degrees, vec2d sens, accel_args accel_args) : accel_fn(accel_args) { apply_rotate = degrees != 0; diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 0307b4c..271b61b 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -18,7 +18,7 @@ public: ManagedAccel(double mode, double offset, double accel, double lim_exp, double midpoint) { - args_t args{}; + accel_args args{}; args.accel = accel; args.lim_exp = lim_exp; args.midpoint = midpoint; -- cgit v1.2.3 From cdd82efdfdd7c2e9b4c2ed9777792f9921eedb9e Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 17:21:39 -0700 Subject: Get rid of enum and use types\tags directly --- common/rawaccel-userspace.hpp | 14 +++++++------- common/rawaccel.hpp | 24 +++++------------------- grapher/Form1.cs | 2 +- wrapper/wrapper.hpp | 4 ++-- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index 5996364..82a9e98 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -68,34 +68,34 @@ mouse_modifier parse(int argc, char** argv) { // modes auto noaccel_mode = "no-accel mode" % ( - clipp::command("off", "noaccel").set(accel_args.accel_mode, mode::noaccel) + clipp::command("off", "noaccel").set(accel_args.accel_mode, accel_implementation_t::id) ); auto lin_mode = "linear accel mode:" % ( - clipp::command("linear").set(accel_args.accel_mode, mode::linear), + clipp::command("linear").set(accel_args.accel_mode, accel_implementation_t::id), accel_var ); auto classic_mode = "classic accel mode:" % ( - clipp::command("classic").set(accel_args.accel_mode, mode::classic), + clipp::command("classic").set(accel_args.accel_mode, accel_implementation_t::id), accel_var, (clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent" ); auto nat_mode = "natural accel mode:" % ( - clipp::command("natural").set(accel_args.accel_mode, mode::natural), + clipp::command("natural").set(accel_args.accel_mode, accel_implementation_t::id), accel_var, limit_var ); auto log_mode = "logarithmic accel mode:" % ( - clipp::command("logarithmic").set(accel_args.accel_mode, mode::logarithmic), + clipp::command("logarithmic").set(accel_args.accel_mode, accel_implementation_t::id), accel_var ); auto sig_mode = "sigmoid accel mode:" % ( - clipp::command("sigmoid").set(accel_args.accel_mode, mode::sigmoid), + clipp::command("sigmoid").set(accel_args.accel_mode, accel_implementation_t::id), accel_var, limit_var, (clipp::required("midpoint") & clipp::number("speed", accel_args.midpoint)) % "midpoint" ); auto pow_mode = "power accel mode:" % ( - clipp::command("power").set(accel_args.accel_mode, mode::power) >> [&] { accel_args.accel = 1; }, + clipp::command("power").set(accel_args.accel_mode, accel_implementation_t::id) >> [&] { accel_args.accel = 1; }, (clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent", (clipp::option("scale") & clipp::number("num", accel_args.accel)) % "scale factor" ); diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index e904350..08829dd 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -9,9 +9,6 @@ namespace rawaccel { - /// Enum to hold acceleration implementation types (i.e. types of curves.) - enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid, power }; - /// Struct to hold vector rotation details. struct rotator { @@ -80,7 +77,7 @@ namespace rawaccel { /// Struct to hold arguments for an acceleration function. struct accel_args { - mode accel_mode = mode::noaccel; + int accel_mode = 0; milliseconds time_min = 0.4; double offset = 0; double accel = 0; @@ -282,20 +279,8 @@ namespace rawaccel { vec2 clamp; accel_function(accel_args args) { - switch (args.accel_mode) - { - case mode::linear: accel = accel_linear(args); - break; - case mode::classic: accel = accel_classic(args); - break; - case mode::natural: accel = accel_natural(args); - break; - case mode::logarithmic: accel = accel_logarithmic(args); - break; - case mode::sigmoid: accel = accel_sigmoid(args); - break; - case mode::power: accel = accel_power(args); - } + accel.tag = args.accel_mode; + accel.visit([&](auto& a){ a = {args}; }); // Verification is performed by the accel_implementation object // and therefore must occur after the object has been instantiated @@ -365,7 +350,8 @@ namespace rawaccel { if (apply_rotate) rotate = rotator(degrees); else rotate = rotator(); - apply_accel = accel_args.accel_mode != mode::noaccel; + apply_accel = (accel_args.accel_mode != 0 && + accel_args.accel_mode != accel_implementation_t::id); if (sens.x == 0) sens.x = 1; if (sens.y == 0) sens.y = 1; diff --git a/grapher/Form1.cs b/grapher/Form1.cs index 4165b0f..495640e 100644 --- a/grapher/Form1.cs +++ b/grapher/Form1.cs @@ -15,7 +15,7 @@ namespace grapher public RawAcceleration() { InitializeComponent(); - var managedAccel = new ManagedAccel(6, 0, 1.333, 0.05, 0); + var managedAccel = new ManagedAccel(5, 0, 0.3, 1.25, 15); var orderedPoints = new SortedDictionary(); for (int i = 0; i < 100; i++) diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 271b61b..727bfcc 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -16,13 +16,13 @@ public: { } - ManagedAccel(double mode, double offset, double accel, double lim_exp, double midpoint) + ManagedAccel(int mode, double offset, double accel, double lim_exp, double midpoint) { accel_args args{}; args.accel = accel; args.lim_exp = lim_exp; args.midpoint = midpoint; - args.accel_mode = (rawaccel::mode)mode; + args.accel_mode = mode; args.offset = offset; accel_instance = new accel_function(args); -- cgit v1.2.3 From 344f759dad28c8b3866d7942bd8927ef1caaf6ab Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 28 Jul 2020 18:16:12 -0700 Subject: add per-class args structs --- common/rawaccel-userspace.hpp | 44 ++++++++++++++++---------------- common/rawaccel.hpp | 58 ++++++++++++++++++++++++++----------------- wrapper/wrapper.hpp | 10 ++++---- 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index 82a9e98..3e8886f 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -17,9 +17,7 @@ void error(const char* s) { } mouse_modifier parse(int argc, char** argv) { - double degrees = 0; - vec2d sens = { 1, 1 }; - accel_args accel_args{}; + modifier_args modifier_args{}; auto make_opt_vec = [](vec2d& v, auto first_flag, auto... rest) { return clipp::option(first_flag, rest...) & ( @@ -40,64 +38,64 @@ mouse_modifier parse(int argc, char** argv) { }; // default options - auto opt_sens = "sensitivity (default = 1)" % make_opt_vec(sens, "sens"); + auto opt_sens = "sensitivity (default = 1)" % make_opt_vec(modifier_args.sens, "sens"); auto opt_rot = "counter-clockwise rotation (default = 0)" % ( clipp::option("rotate") & - clipp::number("degrees", degrees) + clipp::number("degrees", modifier_args.degrees) ); // mode-independent accel options auto opt_weight = "accel multiplier (default = 1)" % - make_opt_vec(accel_args.weight, "weight"); + make_opt_vec(modifier_args.acc_fn_args.weight, "weight"); auto opt_offset = "speed (dots/ms) where accel kicks in (default = 0)" % ( - clipp::option("offset") & clipp::number("speed", accel_args.offset) + clipp::option("offset") & clipp::number("speed", modifier_args.acc_fn_args.acc_args.offset) ); auto opt_cap = "accel scale cap (default = 9)" % - make_opt_vec(accel_args.cap, "cap"); + make_opt_vec(modifier_args.acc_fn_args.cap, "cap"); auto opt_tmin = "minimum time between polls (default = 0.4)" % ( clipp::option("tmin") & - clipp::number("ms", accel_args.time_min) + clipp::number("ms", modifier_args.acc_fn_args.acc_args.time_min) ); - auto accel_var = (clipp::required("accel") & clipp::number("num", accel_args.accel)) % "ramp rate"; - auto limit_var = (clipp::required("limit") & clipp::number("scale", accel_args.lim_exp)) % "limit"; + auto accel_var = (clipp::required("accel") & clipp::number("num", modifier_args.acc_fn_args.acc_args.accel)) % "ramp rate"; + auto limit_var = (clipp::required("limit") & clipp::number("scale", modifier_args.acc_fn_args.acc_args.lim_exp)) % "limit"; // modes auto noaccel_mode = "no-accel mode" % ( - clipp::command("off", "noaccel").set(accel_args.accel_mode, accel_implementation_t::id) + clipp::command("off", "noaccel").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id) ); auto lin_mode = "linear accel mode:" % ( - clipp::command("linear").set(accel_args.accel_mode, accel_implementation_t::id), + clipp::command("linear").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), accel_var ); auto classic_mode = "classic accel mode:" % ( - clipp::command("classic").set(accel_args.accel_mode, accel_implementation_t::id), + clipp::command("classic").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), accel_var, - (clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent" + (clipp::required("exponent") & clipp::number("num", modifier_args.acc_fn_args.acc_args.lim_exp)) % "exponent" ); auto nat_mode = "natural accel mode:" % ( - clipp::command("natural").set(accel_args.accel_mode, accel_implementation_t::id), + clipp::command("natural").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), accel_var, limit_var ); auto log_mode = "logarithmic accel mode:" % ( - clipp::command("logarithmic").set(accel_args.accel_mode, accel_implementation_t::id), + clipp::command("logarithmic").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), accel_var ); auto sig_mode = "sigmoid accel mode:" % ( - clipp::command("sigmoid").set(accel_args.accel_mode, accel_implementation_t::id), + clipp::command("sigmoid").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), accel_var, limit_var, - (clipp::required("midpoint") & clipp::number("speed", accel_args.midpoint)) % "midpoint" + (clipp::required("midpoint") & clipp::number("speed", modifier_args.acc_fn_args.acc_args.midpoint)) % "midpoint" ); auto pow_mode = "power accel mode:" % ( - clipp::command("power").set(accel_args.accel_mode, accel_implementation_t::id) >> [&] { accel_args.accel = 1; }, - (clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent", - (clipp::option("scale") & clipp::number("num", accel_args.accel)) % "scale factor" + clipp::command("power").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id) >> [&] { modifier_args.acc_fn_args.acc_args.accel = 1; }, + (clipp::required("exponent") & clipp::number("num", modifier_args.acc_fn_args.acc_args.lim_exp)) % "exponent", + (clipp::option("scale") & clipp::number("num", modifier_args.acc_fn_args.acc_args.accel)) % "scale factor" ); auto accel_mode_exclusive = (lin_mode | classic_mode | nat_mode | log_mode | sig_mode | pow_mode); @@ -121,7 +119,7 @@ mouse_modifier parse(int argc, char** argv) { std::exit(0); } - return mouse_modifier(-degrees, sens, accel_args); + return mouse_modifier(modifier_args); } } // rawaccel diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 08829dd..9cfa5e7 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -9,6 +9,13 @@ namespace rawaccel { +// Error throwing calls std libraries which are unavailable in kernel mode. +#ifdef _KERNEL_MODE + void error(const char*) {} +#else + void error(const char* s); +#endif + /// Struct to hold vector rotation details. struct rotator { @@ -66,25 +73,15 @@ namespace rawaccel { accel_scale_clamp() = default; }; -// Error throwing calls std libraries which are unavailable in kernel mode. -#ifdef _KERNEL_MODE - void error(const char*) {} -#else - void error(const char* s); -#endif - using milliseconds = double; /// Struct to hold arguments for an acceleration function. struct accel_args { - int accel_mode = 0; milliseconds time_min = 0.4; double offset = 0; double accel = 0; double lim_exp = 2; double midpoint = 0; - vec2d weight = { 1, 1 }; - vec2d cap = { 0, 0 }; }; /// @@ -255,6 +252,14 @@ namespace rawaccel { /// Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. using accel_implementation_t = tagged_union; + struct accel_fn_args { + accel_args acc_args = accel_args{}; + int accel_mode = 0; + milliseconds time_min = 0.4; + vec2d weight = { 1, 1 }; + vec2d cap = { 0, 0 }; + }; + /// Struct for holding acceleration application details. struct accel_function { @@ -278,16 +283,16 @@ namespace rawaccel { /// The object which sets a min and max for the acceleration scale. vec2 clamp; - accel_function(accel_args args) { + accel_function(accel_fn_args args) { accel.tag = args.accel_mode; - accel.visit([&](auto& a){ a = {args}; }); + accel.visit([&](auto& a){ a = {args.acc_args}; }); // Verification is performed by the accel_implementation object // and therefore must occur after the object has been instantiated - verify(args); + verify(args.acc_args); time_min = args.time_min; - speed_offset = args.offset; + speed_offset = args.acc_args.offset; weight = args.weight; clamp.x = accel_scale_clamp(args.cap.x); clamp.y = accel_scale_clamp(args.cap.y); @@ -335,6 +340,13 @@ namespace rawaccel { accel_function() = default; }; + struct modifier_args + { + double degrees = 0; + vec2d sens = { 1, 1 }; + accel_fn_args acc_fn_args = accel_fn_args{}; + }; + /// Struct to hold variables and methods for modifying mouse input struct mouse_modifier { bool apply_rotate = false; @@ -343,19 +355,19 @@ namespace rawaccel { accel_function accel_fn; vec2d sensitivity = { 1, 1 }; - mouse_modifier(double degrees, vec2d sens, accel_args accel_args) - : accel_fn(accel_args) + mouse_modifier(modifier_args args) + : accel_fn(args.acc_fn_args) { - apply_rotate = degrees != 0; - if (apply_rotate) rotate = rotator(degrees); + apply_rotate = args.degrees != 0; + if (apply_rotate) rotate = rotator(args.degrees); else rotate = rotator(); - apply_accel = (accel_args.accel_mode != 0 && - accel_args.accel_mode != accel_implementation_t::id); + apply_accel = (args.acc_fn_args.accel_mode != 0 && + args.acc_fn_args.accel_mode != accel_implementation_t::id); - if (sens.x == 0) sens.x = 1; - if (sens.y == 0) sens.y = 1; - sensitivity = sens; + if (args.sens.x == 0) args.sens.x = 1; + if (args.sens.y == 0) args.sens.y = 1; + sensitivity = args.sens; } /// diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 727bfcc..2cbc01c 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -18,12 +18,12 @@ public: ManagedAccel(int mode, double offset, double accel, double lim_exp, double midpoint) { - accel_args args{}; - args.accel = accel; - args.lim_exp = lim_exp; - args.midpoint = midpoint; + accel_fn_args args{}; + args.acc_args.accel = accel; + args.acc_args.lim_exp = lim_exp; + args.acc_args.midpoint = midpoint; args.accel_mode = mode; - args.offset = offset; + args.acc_args.offset = offset; accel_instance = new accel_function(args); } -- cgit v1.2.3 From 33317e79489848ae537ac78b9c9e70372857aee8 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Wed, 29 Jul 2020 00:35:39 -0700 Subject: Separate accel implementations into files --- common/accel_classic.cpp | 21 +++++ common/accel_linear.cpp | 21 +++++ common/accel_logarithmic.cpp | 21 +++++ common/accel_natural.cpp | 23 +++++ common/accel_noaccel.cpp | 15 +++ common/accel_power.cpp | 24 +++++ common/accel_sigmoid.cpp | 21 +++++ common/accel_types.hpp | 130 ++++++++++++++++++++++++++ common/common.vcxitems | 10 ++ common/rawaccel.hpp | 212 +++++-------------------------------------- driver/driver.cpp | 8 +- 11 files changed, 314 insertions(+), 192 deletions(-) create mode 100644 common/accel_classic.cpp create mode 100644 common/accel_linear.cpp create mode 100644 common/accel_logarithmic.cpp create mode 100644 common/accel_natural.cpp create mode 100644 common/accel_noaccel.cpp create mode 100644 common/accel_power.cpp create mode 100644 common/accel_sigmoid.cpp create mode 100644 common/accel_types.hpp diff --git a/common/accel_classic.cpp b/common/accel_classic.cpp new file mode 100644 index 0000000..e4e7ab9 --- /dev/null +++ b/common/accel_classic.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_classic::accel_classic(accel_args args) + : accel_implentation(args) {} + + double accel_classic::accelerate(double speed) { + //f(x) = (mx)^k + return pow(curve_constant_one * speed, curve_constant_two); + } + + void accel_classic::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_linear.cpp b/common/accel_linear.cpp new file mode 100644 index 0000000..d12e798 --- /dev/null +++ b/common/accel_linear.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_linear::accel_linear(accel_args args) + : accel_implentation(args) {} + + double accel_linear::accelerate(double speed) { + //f(x) = mx + return curve_constant_one * speed; + } + + void accel_linear::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("limit must be greater than 1"); + } +} diff --git a/common/accel_logarithmic.cpp b/common/accel_logarithmic.cpp new file mode 100644 index 0000000..c127bcb --- /dev/null +++ b/common/accel_logarithmic.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_logarithmic::accel_logarithmic(accel_args args) + : accel_implentation(args) {} + + double accel_logarithmic::accelerate(double speed) { + //f(x) = log(m*x+1) + return log(speed * curve_constant_one + 1); + } + + void accel_logarithmic::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_natural.cpp b/common/accel_natural.cpp new file mode 100644 index 0000000..ba9bc02 --- /dev/null +++ b/common/accel_natural.cpp @@ -0,0 +1,23 @@ + +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_natural::accel_natural(accel_args args) + : accel_implentation(args) + { curve_constant_one /= curve_constant_two; } + + double accel_natural::accelerate(double speed) { + // f(x) = k(1-e^(-mx)) + return curve_constant_two - (curve_constant_two * exp(-curve_constant_one * speed));; + } + + void accel_natural::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_noaccel.cpp b/common/accel_noaccel.cpp new file mode 100644 index 0000000..50506a7 --- /dev/null +++ b/common/accel_noaccel.cpp @@ -0,0 +1,15 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_noaccel::accel_noaccel(accel_args args) + : accel_implentation(args) {} + + double accel_noaccel::accelerate(double speed) { return 0; } + + void accel_noaccel::verify(accel_args args) { } +} diff --git a/common/accel_power.cpp b/common/accel_power.cpp new file mode 100644 index 0000000..26f800d --- /dev/null +++ b/common/accel_power.cpp @@ -0,0 +1,24 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_power::accel_power(accel_args args) + : accel_implentation(args) + { curve_constant_two++; } + + double accel_power::accelerate(double speed) { + // f(x) = (mx)^k - 1 + // The subtraction of 1 occurs with later addition of 1 in mind, + // so that the input vector is directly multiplied by (mx)^k (if unweighted) + return (offset > 0 && speed < 1) ? 0 : pow(speed * curve_constant_one, curve_constant_two) - 1; + } + + void accel_power::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 0) error("exponent must be greater than 0"); + } +} diff --git a/common/accel_sigmoid.cpp b/common/accel_sigmoid.cpp new file mode 100644 index 0000000..c5280bc --- /dev/null +++ b/common/accel_sigmoid.cpp @@ -0,0 +1,21 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +#include "accel_types.hpp" + +namespace rawaccel { + accel_sigmoid::accel_sigmoid(accel_args args) + : accel_implentation(args) {} + + double accel_sigmoid::accelerate(double speed) { + //f(x) = k/(1+e^(-m(c-x))) + return curve_constant_two / (exp(-curve_constant_one * (speed - curve_constant_three)) + 1); + } + + void accel_sigmoid::verify(accel_args args) { + accel_implentation::verify(args); + if (args.lim_exp <= 1) error("exponent must be greater than 1"); + } +} diff --git a/common/accel_types.hpp b/common/accel_types.hpp new file mode 100644 index 0000000..c931097 --- /dev/null +++ b/common/accel_types.hpp @@ -0,0 +1,130 @@ +#pragma once + +#define _USE_MATH_DEFINES +#include + +namespace rawaccel { + +// Error throwing calls std libraries which are unavailable in kernel mode. +#ifdef _KERNEL_MODE + void error(const char*) {} +#else + void error(const char* s); +#endif + + using milliseconds = double; + + /// Struct to hold arguments for an acceleration function. + struct accel_args { + milliseconds time_min = 0.4; + double offset = 0; + double accel = 0; + double lim_exp = 2; + double midpoint = 0; + }; + + /// + /// Struct to hold acceleration curve implementation details. + /// + /// Type of acceleration. + template + struct accel_implentation { + + /// First constant for use in acceleration curves. Generally, the acceleration ramp rate. + double curve_constant_one = 0; + + /// Second constant for use in acceleration curves. Generally, the limit or exponent in the curve. + double curve_constant_two = 0; + + /// Third constant for use in acceleration curves. The midpoint in sigmoid mode. + double curve_constant_three = 0; + + /// The offset past which acceleration is applied. Used in power mode. + double offset = 0; + + /// + /// Initializes a new instance of the struct. + /// + /// + /// + accel_implentation(accel_args args) + { + curve_constant_one = args.accel; + curve_constant_two = args.lim_exp - 1; + curve_constant_three = args.midpoint; + offset = args.offset; + } + + /// + /// Returns accelerated value of speed as a ratio of magnitude. + /// + /// Mouse speed at which to calculate acceleration. + /// Ratio of accelerated movement magnitude to input movement magnitude. + double accelerate(double speed) { return 0; } + + /// + /// Verifies arguments as valid. Errors if not. + /// + /// Arguments to verified. + void verify(accel_args args) { + if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); + if (args.time_min <= 0) error("min time must be positive"); + } + + /// + /// + /// + /// + accel_implentation() = default; + }; + + /// Struct to hold linear acceleration implementation. + struct accel_linear : accel_implentation { + accel_linear(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// Struct to hold "classic" (linear raised to power) acceleration implementation. + struct accel_classic : accel_implentation { + accel_classic(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// Struct to hold "natural" (vanishing difference) acceleration implementation. + struct accel_natural : accel_implentation { + accel_natural(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// Struct to hold logarithmic acceleration implementation. + struct accel_logarithmic : accel_implentation { + accel_logarithmic(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// Struct to hold sigmoid (s-shaped) acceleration implementation. + struct accel_sigmoid : accel_implentation { + accel_sigmoid(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// Struct to hold power (non-additive) acceleration implementation. + struct accel_power : accel_implentation { + accel_power(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + + /// Struct to hold acceleration implementation which applies no acceleration. + struct accel_noaccel : accel_implentation { + accel_noaccel(accel_args args); + double accelerate(double speed); + void verify(accel_args args); + }; + +} diff --git a/common/common.vcxitems b/common/common.vcxitems index 224792c..f33d8e1 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -14,10 +14,20 @@ + + + + + + + + + + \ No newline at end of file diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 9cfa5e7..d0c1b66 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -7,14 +7,15 @@ #include "x64-util.hpp" #include "external/tagged-union-single.h" -namespace rawaccel { +#include "accel_linear.cpp" +#include "accel_classic.cpp" +#include "accel_natural.cpp" +#include "accel_logarithmic.cpp" +#include "accel_sigmoid.cpp" +#include "accel_power.cpp" +#include "accel_noaccel.cpp" -// Error throwing calls std libraries which are unavailable in kernel mode. -#ifdef _KERNEL_MODE - void error(const char*) {} -#else - void error(const char* s); -#endif +namespace rawaccel { /// Struct to hold vector rotation details. struct rotator { @@ -73,182 +74,6 @@ namespace rawaccel { accel_scale_clamp() = default; }; - using milliseconds = double; - - /// Struct to hold arguments for an acceleration function. - struct accel_args { - milliseconds time_min = 0.4; - double offset = 0; - double accel = 0; - double lim_exp = 2; - double midpoint = 0; - }; - - /// - /// Struct to hold acceleration curve implementation details. - /// - /// Type of acceleration. - template - struct accel_implentation { - - /// First constant for use in acceleration curves. Generally, the acceleration ramp rate. - double curve_constant_one = 0; - - /// Second constant for use in acceleration curves. Generally, the limit or exponent in the curve. - double curve_constant_two = 0; - - /// Third constant for use in acceleration curves. The midpoint in sigmoid mode. - double curve_constant_three = 0; - - /// The offset past which acceleration is applied. Used in power mode. - double offset = 0; - - /// - /// Initializes a new instance of the struct. - /// - /// - /// - accel_implentation(accel_args args) - { - curve_constant_one = args.accel; - curve_constant_two = args.lim_exp - 1; - curve_constant_three = args.midpoint; - offset = args.offset; - } - - /// - /// Returns accelerated value of speed as a ratio of magnitude. - /// - /// Mouse speed at which to calculate acceleration. - /// Ratio of accelerated movement magnitude to input movement magnitude. - double accelerate(double speed) { return 0; } - - /// - /// Verifies arguments as valid. Errors if not. - /// - /// Arguments to verified. - void verify(accel_args args) { - if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); - if (args.time_min <= 0) error("min time must be positive"); - } - - /// - /// - /// - /// - accel_implentation() = default; - }; - - /// Struct to hold linear acceleration implementation. - struct accel_linear : accel_implentation { - - accel_linear(accel_args args) - : accel_implentation(args) {} - - double accelerate(double speed) { - //f(x) = mx - return curve_constant_one * speed; - } - - void verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("limit must be greater than 1"); - } - }; - - /// Struct to hold "classic" (linear raised to power) acceleration implementation. - struct accel_classic : accel_implentation { - accel_classic(accel_args args) - : accel_implentation(args) {} - - double accelerate(double speed) { - //f(x) = (mx)^k - return pow(curve_constant_one * speed, curve_constant_two); - } - - void verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } - }; - - /// Struct to hold "natural" (vanishing difference) acceleration implementation. - struct accel_natural : accel_implentation { - accel_natural(accel_args args) - : accel_implentation(args) - { curve_constant_one /= curve_constant_two; } - - double accelerate(double speed) { - // f(x) = k(1-e^(-mx)) - return curve_constant_two - (curve_constant_two * exp(-curve_constant_one * speed));; - } - - void verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } - }; - - /// Struct to hold logarithmic acceleration implementation. - struct accel_logarithmic : accel_implentation { - accel_logarithmic(accel_args args) - : accel_implentation(args) {} - - double accelerate(double speed) { - return log(speed * curve_constant_one + 1); - } - - void verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } - }; - - /// Struct to hold sigmoid (s-shaped) acceleration implementation. - struct accel_sigmoid : accel_implentation { - accel_sigmoid(accel_args args) - : accel_implentation(args) {} - - double accelerate(double speed) { - //f(x) = k/(1+e^(-m(c-x))) - return curve_constant_two / (exp(-curve_constant_one * (speed - curve_constant_three)) + 1); - } - - void verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } - }; - - /// Struct to hold power (non-additive) acceleration implementation. - struct accel_power : accel_implentation { - accel_power(accel_args args) - : accel_implentation(args) - { curve_constant_two++; } - - double accelerate(double speed) { - // f(x) = (mx)^k - 1 - // The subtraction of 1 occurs with later addition of 1 in mind, - // so that the input vector is directly multiplied by (mx)^k (if unweighted) - return (offset > 0 && speed < 1) ? 0 : pow(speed * curve_constant_one, curve_constant_two) - 1; - } - - void verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 0) error("exponent must be greater than 0"); - } - }; - - /// Struct to hold acceleration implementation which applies no acceleration. - struct accel_noaccel : accel_implentation { - accel_noaccel(accel_args args) - : accel_implentation(args) {} - - double accelerate(double speed) { return 0; } - - void verify(accel_args args) {} - }; - /// Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. using accel_implementation_t = tagged_union; @@ -371,18 +196,20 @@ namespace rawaccel { } /// - /// Applies modification without acceleration. Rotation is the only - /// modification currently implemented. + /// Applies modification without acceleration. /// /// Input to be modified. /// 2d vector of modified input. - inline vec2d modify(vec2d input) + inline vec2d modify_without_accel(vec2d input) { if (apply_rotate) { return rotate(input); } + input.x *= sensitivity.x; + input.y *= sensitivity.y; + return input; } @@ -392,9 +219,18 @@ namespace rawaccel { /// Input to be modified /// Time period for determining acceleration. /// 2d vector with modified input. - inline vec2d modify(vec2d input, milliseconds time) + inline vec2d modify_with_accel(vec2d input, milliseconds time) { - return accel_fn(modify(input), time); + if (apply_rotate) + { + return rotate(input); + } + + input = accel_fn(input, time); + input.x *= sensitivity.x; + input.y *= sensitivity.y; + + return input; } mouse_modifier() = default; diff --git a/driver/driver.cpp b/driver/driver.cpp index 9704b21..1f9cebd 100644 --- a/driver/driver.cpp +++ b/driver/driver.cpp @@ -79,15 +79,15 @@ Arguments: DebugPrint(("RA time < min with %d ticks\n", ticks)); } - input = global.modifier.modify(input, time); + input = global.modifier.modify_with_accel(input, time); } else { - input = global.modifier.modify(input); + input = global.modifier.modify_without_accel(input); } - double result_x = input.x * global.modifier.sensitivity.x + local_carry.x; - double result_y = input.y * global.modifier.sensitivity.y + local_carry.y; + double result_x = input.x + local_carry.x; + double result_y = input.y + local_carry.y; LONG out_x = static_cast(result_x); LONG out_y = static_cast(result_y); -- cgit v1.2.3 From 7963edee802d5a7b51f1867a5133857c403c8ef6 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Wed, 29 Jul 2020 01:10:29 -0700 Subject: Inline methods for linking, and fix sens application bug --- common/accel_classic.cpp | 6 +++--- common/accel_linear.cpp | 6 +++--- common/accel_logarithmic.cpp | 6 +++--- common/accel_natural.cpp | 6 +++--- common/accel_noaccel.cpp | 6 +++--- common/accel_power.cpp | 6 +++--- common/accel_sigmoid.cpp | 6 +++--- common/accel_types.hpp | 2 +- common/rawaccel.hpp | 10 +++++++--- 9 files changed, 29 insertions(+), 25 deletions(-) diff --git a/common/accel_classic.cpp b/common/accel_classic.cpp index e4e7ab9..323cd3b 100644 --- a/common/accel_classic.cpp +++ b/common/accel_classic.cpp @@ -6,15 +6,15 @@ #include "accel_types.hpp" namespace rawaccel { - accel_classic::accel_classic(accel_args args) + inline accel_classic::accel_classic(accel_args args) : accel_implentation(args) {} - double accel_classic::accelerate(double speed) { + inline double accel_classic::accelerate(double speed) { //f(x) = (mx)^k return pow(curve_constant_one * speed, curve_constant_two); } - void accel_classic::verify(accel_args args) { + inline void accel_classic::verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } diff --git a/common/accel_linear.cpp b/common/accel_linear.cpp index d12e798..307e33e 100644 --- a/common/accel_linear.cpp +++ b/common/accel_linear.cpp @@ -6,15 +6,15 @@ #include "accel_types.hpp" namespace rawaccel { - accel_linear::accel_linear(accel_args args) + inline accel_linear::accel_linear(accel_args args) : accel_implentation(args) {} - double accel_linear::accelerate(double speed) { + inline double accel_linear::accelerate(double speed) { //f(x) = mx return curve_constant_one * speed; } - void accel_linear::verify(accel_args args) { + inline void accel_linear::verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("limit must be greater than 1"); } diff --git a/common/accel_logarithmic.cpp b/common/accel_logarithmic.cpp index c127bcb..64808a1 100644 --- a/common/accel_logarithmic.cpp +++ b/common/accel_logarithmic.cpp @@ -6,15 +6,15 @@ #include "accel_types.hpp" namespace rawaccel { - accel_logarithmic::accel_logarithmic(accel_args args) + inline accel_logarithmic::accel_logarithmic(accel_args args) : accel_implentation(args) {} - double accel_logarithmic::accelerate(double speed) { + inline double accel_logarithmic::accelerate(double speed) { //f(x) = log(m*x+1) return log(speed * curve_constant_one + 1); } - void accel_logarithmic::verify(accel_args args) { + inline void accel_logarithmic::verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } diff --git a/common/accel_natural.cpp b/common/accel_natural.cpp index ba9bc02..c6f14b4 100644 --- a/common/accel_natural.cpp +++ b/common/accel_natural.cpp @@ -7,16 +7,16 @@ #include "accel_types.hpp" namespace rawaccel { - accel_natural::accel_natural(accel_args args) + inline accel_natural::accel_natural(accel_args args) : accel_implentation(args) { curve_constant_one /= curve_constant_two; } - double accel_natural::accelerate(double speed) { + inline double accel_natural::accelerate(double speed) { // f(x) = k(1-e^(-mx)) return curve_constant_two - (curve_constant_two * exp(-curve_constant_one * speed));; } - void accel_natural::verify(accel_args args) { + inline void accel_natural::verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } diff --git a/common/accel_noaccel.cpp b/common/accel_noaccel.cpp index 50506a7..fce5dd4 100644 --- a/common/accel_noaccel.cpp +++ b/common/accel_noaccel.cpp @@ -6,10 +6,10 @@ #include "accel_types.hpp" namespace rawaccel { - accel_noaccel::accel_noaccel(accel_args args) + inline accel_noaccel::accel_noaccel(accel_args args) : accel_implentation(args) {} - double accel_noaccel::accelerate(double speed) { return 0; } + inline double accel_noaccel::accelerate(double speed) { return 0; } - void accel_noaccel::verify(accel_args args) { } + inline void accel_noaccel::verify(accel_args args) { } } diff --git a/common/accel_power.cpp b/common/accel_power.cpp index 26f800d..f104554 100644 --- a/common/accel_power.cpp +++ b/common/accel_power.cpp @@ -6,18 +6,18 @@ #include "accel_types.hpp" namespace rawaccel { - accel_power::accel_power(accel_args args) + inline accel_power::accel_power(accel_args args) : accel_implentation(args) { curve_constant_two++; } - double accel_power::accelerate(double speed) { + inline double accel_power::accelerate(double speed) { // f(x) = (mx)^k - 1 // The subtraction of 1 occurs with later addition of 1 in mind, // so that the input vector is directly multiplied by (mx)^k (if unweighted) return (offset > 0 && speed < 1) ? 0 : pow(speed * curve_constant_one, curve_constant_two) - 1; } - void accel_power::verify(accel_args args) { + inline void accel_power::verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 0) error("exponent must be greater than 0"); } diff --git a/common/accel_sigmoid.cpp b/common/accel_sigmoid.cpp index c5280bc..d3b8ab7 100644 --- a/common/accel_sigmoid.cpp +++ b/common/accel_sigmoid.cpp @@ -6,15 +6,15 @@ #include "accel_types.hpp" namespace rawaccel { - accel_sigmoid::accel_sigmoid(accel_args args) + inline accel_sigmoid::accel_sigmoid(accel_args args) : accel_implentation(args) {} - double accel_sigmoid::accelerate(double speed) { + inline double accel_sigmoid::accelerate(double speed) { //f(x) = k/(1+e^(-m(c-x))) return curve_constant_two / (exp(-curve_constant_one * (speed - curve_constant_three)) + 1); } - void accel_sigmoid::verify(accel_args args) { + inline void accel_sigmoid::verify(accel_args args) { accel_implentation::verify(args); if (args.lim_exp <= 1) error("exponent must be greater than 1"); } diff --git a/common/accel_types.hpp b/common/accel_types.hpp index c931097..15f5a50 100644 --- a/common/accel_types.hpp +++ b/common/accel_types.hpp @@ -7,7 +7,7 @@ namespace rawaccel { // Error throwing calls std libraries which are unavailable in kernel mode. #ifdef _KERNEL_MODE - void error(const char*) {} + inline void error(const char*) {} #else void error(const char* s); #endif diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index d0c1b66..6f737da 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -204,7 +204,7 @@ namespace rawaccel { { if (apply_rotate) { - return rotate(input); + input = rotate(input); } input.x *= sensitivity.x; @@ -223,10 +223,14 @@ namespace rawaccel { { if (apply_rotate) { - return rotate(input); + input = rotate(input); + } + + if (apply_accel) + { + input = accel_fn(input, time); } - input = accel_fn(input, time); input.x *= sensitivity.x; input.y *= sensitivity.y; -- cgit v1.2.3 From 6bb5b03e2afb0dd52204dfb1924dfd096387de3a Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Wed, 29 Jul 2020 11:52:36 -0700 Subject: Use modifier object in wrapper --- common/rawaccel.hpp | 2 +- wrapper/wrapper.cpp | 2 +- wrapper/wrapper.hpp | 32 ++++++++++++++++---------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 6f737da..b480e87 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -20,7 +20,7 @@ namespace rawaccel { /// Struct to hold vector rotation details. struct rotator { - /// Rotational vector, which points in the direction of the post-rotation positive y axis. + /// Rotational vector, which points in the direction of the post-rotation positive x axis. vec2d rot_vec = { 1, 0 }; /// diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 1adafba..c1cc570 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -8,7 +8,7 @@ using namespace System; Tuple^ ManagedAccel::Accelerate(int x, int y, double time) { vec2d input_vec2d = {x, y}; - vec2d output = (*accel_instance)(input_vec2d, (milliseconds)time); + vec2d output = (*modifier_instance).modify_with_accel(input_vec2d, (milliseconds)time); return gcnew Tuple(output.x, output.y); } \ No newline at end of file diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 2cbc01c..19b0987 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -9,43 +9,43 @@ using namespace System; public ref class ManagedAccel { protected: - accel_function* accel_instance; + mouse_modifier* modifier_instance; public: - ManagedAccel(accel_function* accel) - : accel_instance(accel) + ManagedAccel(mouse_modifier* accel) + : modifier_instance(accel) { } ManagedAccel(int mode, double offset, double accel, double lim_exp, double midpoint) { - accel_fn_args args{}; - args.acc_args.accel = accel; - args.acc_args.lim_exp = lim_exp; - args.acc_args.midpoint = midpoint; - args.accel_mode = mode; - args.acc_args.offset = offset; + modifier_args args{}; + args.acc_fn_args.acc_args.accel = accel; + args.acc_fn_args.acc_args.lim_exp = lim_exp; + args.acc_fn_args.acc_args.midpoint = midpoint; + args.acc_fn_args.accel_mode = mode; + args.acc_fn_args.acc_args.offset = offset; - accel_instance = new accel_function(args); + modifier_instance = new mouse_modifier(args); } virtual ~ManagedAccel() { - if (accel_instance != nullptr) + if (modifier_instance!= nullptr) { - delete accel_instance; + delete modifier_instance; } } !ManagedAccel() { - if (accel_instance != nullptr) + if (modifier_instance!= nullptr) { - delete accel_instance; + delete modifier_instance; } } - accel_function* GetInstance() + mouse_modifier* GetInstance() { - return accel_instance; + return modifier_instance; } Tuple^ Accelerate(int x, int y, double time); -- cgit v1.2.3 From 2ce052e54d55e9029eff00f0985e399fa1eb2c1a Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Wed, 29 Jul 2020 17:36:33 -0400 Subject: add sum types --- common/external/nillable.h | 30 +++++ common/external/tagged-union-single.h | 202 ++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 common/external/nillable.h create mode 100644 common/external/tagged-union-single.h diff --git a/common/external/nillable.h b/common/external/nillable.h new file mode 100644 index 0000000..40cf01c --- /dev/null +++ b/common/external/nillable.h @@ -0,0 +1,30 @@ +inline constexpr struct nil_t {} nil; + +// Requirements: T is default-constructible and trivially-destructible +template +struct nillable { + bool has_value = false; + T value; + + nillable() = default; + + nillable(nil_t) : nillable() {} + nillable(const T& v) : has_value(true), value(v) {} + + nillable& operator=(nil_t) { + has_value = false; + return *this; + } + nillable& operator=(const T& v) { + value = v; + has_value = true; + return *this; + } + + const T* operator->() const { return &value; } + T* operator->() { return &value; } + + explicit operator bool() const { return has_value; } +}; + +template nillable(T)->nillable; diff --git a/common/external/tagged-union-single.h b/common/external/tagged-union-single.h new file mode 100644 index 0000000..bcfc1cf --- /dev/null +++ b/common/external/tagged-union-single.h @@ -0,0 +1,202 @@ +#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 { typedef T type; }; +template< class T > struct remove_cv { typedef T type; }; +template< class T > struct remove_cv { typedef T type; }; +template< class T > using remove_cv_t = typename remove_cv::type; + +template< class T > struct remove_reference { typedef T type; }; +template< class T > struct remove_reference { typedef T type; }; +template< class T > struct remove_reference { typedef T type; }; +template< class T > using remove_reference_t = typename remove_reference::type; + +template< class T > +struct remove_cvref { + using type = remove_cv_t>; +}; +template< class T > using remove_cvref_t = typename remove_cvref::type; + +namespace detail { + +template struct type_identity { using type = T; }; + +template +auto try_add_lvalue_reference(int)->type_identity; +template +auto try_add_lvalue_reference(...)->type_identity; + +template +auto try_add_rvalue_reference(int)->type_identity; +template +auto try_add_rvalue_reference(...)->type_identity; + +} // type_traits::detail + +template struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference(0)) {}; +template< class T > using add_lvalue_reference_t = typename add_lvalue_reference::type; + +template struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {}; +template< class T > using add_rvalue_reference_t = typename add_rvalue_reference::type; + +template inline constexpr bool is_same_v = false; +template inline constexpr bool is_same_v = true; +template inline constexpr bool is_void_v = is_same_v, void>; + +} // type_traits + +template type_traits::add_rvalue_reference_t declval() noexcept; + +template +inline constexpr T maxv(const T& a, const T& b) { + return (b < a) ? a : b; +} + +template +inline constexpr T minv(const T& a, const T& b) { + return (a < b) ? a : b; +} + +template +inline constexpr T clampv(const T& v, const T& lo, const T& hi) { + return minv(maxv(v, lo), hi); +} + +template +inline constexpr const T& select_ref(bool pred, const T& t, const T& f) { + return pred ? t : f; +} + +template +inline constexpr size_t max_size_of = maxv(sizeof(First), max_size_of); + +template +inline constexpr size_t max_size_of = sizeof(T); + +template +inline constexpr size_t max_align_of = maxv(alignof(First), max_align_of); + +template +inline constexpr size_t max_align_of = alignof(T); + +namespace detail { + +template +struct b1_index_of_impl { + + template + struct idx { + static constexpr size_t value = 0; + }; + + template + struct idx { + static constexpr size_t value = []() { + if constexpr (type_traits::is_same_v) { + return sizeof...(Ts) - sizeof...(Rest); + } + return idx::value; + }(); + }; +}; + +} // detail + +template +inline constexpr int base1_index_of = +detail::b1_index_of_impl::template idx::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 +*/ +template +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 + inline constexpr auto visit(Visitor vis) { + return visit_impl(vis); + } + + template + inline constexpr auto visit(Visitor vis) const { + return visit_impl(vis); + } + + template + static constexpr int id = base1_index_of; + + int tag = 0; + + struct storage_t { + alignas(max_align_of) char bytes[max_size_of]; + + template + inline constexpr T& as() { + static_assert(id != 0, "tagged_union can not hold T"); + return reinterpret_cast(bytes); + } + + template + inline constexpr const T& as() const { + static_assert(id != 0, "tagged_union can not hold T"); + return reinterpret_cast(bytes); + } + + } storage; + + constexpr tagged_union() noexcept = default; + + template + inline constexpr tagged_union(const T& val) noexcept { + tag = id; + storage.template as() = val; + } + + template + inline constexpr tagged_union& operator=(const T& val) noexcept { + tag = id; + storage.template as() = val; + return *this; + } + +private: + template + inline constexpr auto visit_impl(Visitor vis) const { + if (tag == id) { + return vis(storage.template as()); + } + if constexpr (sizeof...(TRest) > 0) { + return visit_impl(vis); + } + else { + using ReturnType = decltype(vis(declval())); + if constexpr (!type_traits::is_void_v) return ReturnType{}; + } + } + + template + inline constexpr auto visit_impl(Visitor vis) { + if (tag == id) { + return vis(storage.template as()); + } + if constexpr (sizeof...(TRest) > 0) { + return visit_impl(vis); + } + else { + using ReturnType = decltype(vis(declval())); + if constexpr (!type_traits::is_void_v) return ReturnType{}; + } + } +}; + +template struct overloaded : Ts... { using Ts::operator()...; }; +template overloaded(Ts...)->overloaded; -- cgit v1.2.3 From e8417a29fb2153ea035a757f36bfa300cf8b480d Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 30 Jul 2020 17:07:35 -0400 Subject: add tweaks for st-refactor --- common/Error.hpp | 10 ---- common/accel-base.hpp | 50 ++++++++++++++++ common/accel-classic.hpp | 29 ++++++++++ common/accel-error.hpp | 11 ++++ common/accel-linear.hpp | 18 ++++++ common/accel-logarithmic.hpp | 20 +++++++ common/accel-natural.hpp | 31 ++++++++++ common/accel-noaccel.hpp | 15 +++++ common/accel-power.hpp | 33 +++++++++++ common/accel-sigmoid.hpp | 32 +++++++++++ common/accel_classic.cpp | 21 ------- common/accel_linear.cpp | 21 ------- common/accel_logarithmic.cpp | 21 ------- common/accel_natural.cpp | 23 -------- common/accel_noaccel.cpp | 15 ----- common/accel_power.cpp | 24 -------- common/accel_sigmoid.cpp | 21 ------- common/accel_types.hpp | 130 ------------------------------------------ common/common.vcxitems | 20 +++---- common/rawaccel-userspace.hpp | 53 +++++++++-------- common/rawaccel.hpp | 73 +++++++++++------------- 21 files changed, 309 insertions(+), 362 deletions(-) delete mode 100644 common/Error.hpp create mode 100644 common/accel-base.hpp create mode 100644 common/accel-classic.hpp create mode 100644 common/accel-error.hpp create mode 100644 common/accel-linear.hpp create mode 100644 common/accel-logarithmic.hpp create mode 100644 common/accel-natural.hpp create mode 100644 common/accel-noaccel.hpp create mode 100644 common/accel-power.hpp create mode 100644 common/accel-sigmoid.hpp delete mode 100644 common/accel_classic.cpp delete mode 100644 common/accel_linear.cpp delete mode 100644 common/accel_logarithmic.cpp delete mode 100644 common/accel_natural.cpp delete mode 100644 common/accel_noaccel.cpp delete mode 100644 common/accel_power.cpp delete mode 100644 common/accel_sigmoid.cpp delete mode 100644 common/accel_types.hpp diff --git a/common/Error.hpp b/common/Error.hpp deleted file mode 100644 index ed87090..0000000 --- a/common/Error.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - - -namespace rawaccel { - void error(const char* s) { - throw std::domain_error(s); - } -} diff --git a/common/accel-base.hpp b/common/accel-base.hpp new file mode 100644 index 0000000..ed79bdb --- /dev/null +++ b/common/accel-base.hpp @@ -0,0 +1,50 @@ +#pragma once + +namespace rawaccel { + + // Error throwing calls std libraries which are unavailable in kernel mode. + void error(const char* s); + + using milliseconds = double; + + /// Struct to hold arguments for an acceleration function. + struct accel_args { + double offset = 0; + double accel = 0; + double limit = 2; + double exponent = 2; + double midpoint = 0; + double power_scale = 1; + }; + + /// + /// Struct to hold common acceleration curve implementation details. + /// + struct accel_base { + + /// Generally, the acceleration ramp rate. + double speed_coeff = 0; + + /// + /// Initializes a new instance of the struct. + /// + /// + /// + accel_base(accel_args args) { + verify(args); + + speed_coeff = args.accel; + } + + /// + /// Verifies arguments as valid. Errors if not. + /// + /// Arguments to verified. + void verify(accel_args args) const { + if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); + } + + accel_base() = default; + }; + +} diff --git a/common/accel-classic.hpp b/common/accel-classic.hpp new file mode 100644 index 0000000..e2eb494 --- /dev/null +++ b/common/accel-classic.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold "classic" (linear raised to power) acceleration implementation. + struct accel_classic : accel_base { + double exponent; + + accel_classic(accel_args args) : accel_base(args) { + verify(args); + + exponent = args.exponent - 1; + } + + inline double accelerate(double speed) const { + //f(x) = (mx)^k + return pow(speed_coeff * speed, exponent); + } + + void verify(accel_args args) const { + if (args.exponent <= 1) error("exponent must be greater than 1"); + } + }; + +} diff --git a/common/accel-error.hpp b/common/accel-error.hpp new file mode 100644 index 0000000..fa1f999 --- /dev/null +++ b/common/accel-error.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace rawaccel { + + void error(const char* s) { + throw std::domain_error(s); + } + +} diff --git a/common/accel-linear.hpp b/common/accel-linear.hpp new file mode 100644 index 0000000..28150a8 --- /dev/null +++ b/common/accel-linear.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold linear acceleration implementation. + struct accel_linear : accel_base { + + accel_linear(accel_args args) : accel_base(args) {} + + inline double accelerate(double speed) const { + //f(x) = mx + return speed_coeff * speed; + } + }; + +} diff --git a/common/accel-logarithmic.hpp b/common/accel-logarithmic.hpp new file mode 100644 index 0000000..b628327 --- /dev/null +++ b/common/accel-logarithmic.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold logarithmic acceleration implementation. + struct accel_logarithmic : accel_base { + + accel_logarithmic(accel_args args) : accel_base(args) {} + + inline double accelerate(double speed) const { + //f(x) = log(m*x+1) + return log(speed_coeff * speed + 1); + } + }; + +} diff --git a/common/accel-natural.hpp b/common/accel-natural.hpp new file mode 100644 index 0000000..6ccb193 --- /dev/null +++ b/common/accel-natural.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold "natural" (vanishing difference) acceleration implementation. + struct accel_natural : accel_base { + double limit = 1; + double midpoint = 0; + + accel_natural(accel_args args) : accel_base(args) { + verify(args); + + limit = args.limit - 1; + speed_coeff /= limit; + } + + inline double accelerate(double speed) const { + // f(x) = k(1-e^(-mx)) + return limit - (limit * exp(-speed_coeff * speed)); + } + + void verify(accel_args args) const { + if (args.limit <= 1) error("limit must be greater than 1"); + } + }; + +} diff --git a/common/accel-noaccel.hpp b/common/accel-noaccel.hpp new file mode 100644 index 0000000..151002a --- /dev/null +++ b/common/accel-noaccel.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold acceleration implementation which applies no acceleration. + struct accel_noaccel : accel_base { + + accel_noaccel(accel_args args) : accel_base(args) {} + + inline double accelerate(double) const { return 0; } + }; + +} diff --git a/common/accel-power.hpp b/common/accel-power.hpp new file mode 100644 index 0000000..c8b12cd --- /dev/null +++ b/common/accel-power.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold power (non-additive) acceleration implementation. + struct accel_power : accel_base { + double exponent; + double offset; + + accel_power(accel_args args) { + verify(args); + + speed_coeff = args.power_scale; + exponent = args.exponent; + offset = args.offset; + } + + inline double accelerate(double speed) const { + // f(x) = (mx)^k + return (offset > 0 && speed < 1) ? 1 : pow(speed * speed_coeff, exponent); + } + + void verify(accel_args args) const { + if (args.power_scale < 0) error("scale can not be negative"); + if (args.exponent <= 0) error("exponent must be greater than 0"); + } + }; + +} diff --git a/common/accel-sigmoid.hpp b/common/accel-sigmoid.hpp new file mode 100644 index 0000000..e992e0c --- /dev/null +++ b/common/accel-sigmoid.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "accel-base.hpp" + +namespace rawaccel { + + /// Struct to hold sigmoid (s-shaped) acceleration implementation. + struct accel_sigmoid : accel_base { + double limit = 1; + double midpoint = 0; + + accel_sigmoid(accel_args args) : accel_base(args) { + verify(args); + + limit = args.limit - 1; + midpoint = args.midpoint; + } + + inline double accelerate(double speed) const { + //f(x) = k/(1+e^(-m(c-x))) + return limit / (exp(-speed_coeff * (speed - midpoint)) + 1); + } + + void verify(accel_args args) const { + if (args.limit <= 1) error("exponent must be greater than 1"); + if (args.midpoint < 0) error("midpoint must not be negative"); + } + }; + +} diff --git a/common/accel_classic.cpp b/common/accel_classic.cpp deleted file mode 100644 index 323cd3b..0000000 --- a/common/accel_classic.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_classic::accel_classic(accel_args args) - : accel_implentation(args) {} - - inline double accel_classic::accelerate(double speed) { - //f(x) = (mx)^k - return pow(curve_constant_one * speed, curve_constant_two); - } - - inline void accel_classic::verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -} diff --git a/common/accel_linear.cpp b/common/accel_linear.cpp deleted file mode 100644 index 307e33e..0000000 --- a/common/accel_linear.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_linear::accel_linear(accel_args args) - : accel_implentation(args) {} - - inline double accel_linear::accelerate(double speed) { - //f(x) = mx - return curve_constant_one * speed; - } - - inline void accel_linear::verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("limit must be greater than 1"); - } -} diff --git a/common/accel_logarithmic.cpp b/common/accel_logarithmic.cpp deleted file mode 100644 index 64808a1..0000000 --- a/common/accel_logarithmic.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_logarithmic::accel_logarithmic(accel_args args) - : accel_implentation(args) {} - - inline double accel_logarithmic::accelerate(double speed) { - //f(x) = log(m*x+1) - return log(speed * curve_constant_one + 1); - } - - inline void accel_logarithmic::verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -} diff --git a/common/accel_natural.cpp b/common/accel_natural.cpp deleted file mode 100644 index c6f14b4..0000000 --- a/common/accel_natural.cpp +++ /dev/null @@ -1,23 +0,0 @@ - -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_natural::accel_natural(accel_args args) - : accel_implentation(args) - { curve_constant_one /= curve_constant_two; } - - inline double accel_natural::accelerate(double speed) { - // f(x) = k(1-e^(-mx)) - return curve_constant_two - (curve_constant_two * exp(-curve_constant_one * speed));; - } - - inline void accel_natural::verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -} diff --git a/common/accel_noaccel.cpp b/common/accel_noaccel.cpp deleted file mode 100644 index fce5dd4..0000000 --- a/common/accel_noaccel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_noaccel::accel_noaccel(accel_args args) - : accel_implentation(args) {} - - inline double accel_noaccel::accelerate(double speed) { return 0; } - - inline void accel_noaccel::verify(accel_args args) { } -} diff --git a/common/accel_power.cpp b/common/accel_power.cpp deleted file mode 100644 index f104554..0000000 --- a/common/accel_power.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_power::accel_power(accel_args args) - : accel_implentation(args) - { curve_constant_two++; } - - inline double accel_power::accelerate(double speed) { - // f(x) = (mx)^k - 1 - // The subtraction of 1 occurs with later addition of 1 in mind, - // so that the input vector is directly multiplied by (mx)^k (if unweighted) - return (offset > 0 && speed < 1) ? 0 : pow(speed * curve_constant_one, curve_constant_two) - 1; - } - - inline void accel_power::verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 0) error("exponent must be greater than 0"); - } -} diff --git a/common/accel_sigmoid.cpp b/common/accel_sigmoid.cpp deleted file mode 100644 index d3b8ab7..0000000 --- a/common/accel_sigmoid.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -#include "accel_types.hpp" - -namespace rawaccel { - inline accel_sigmoid::accel_sigmoid(accel_args args) - : accel_implentation(args) {} - - inline double accel_sigmoid::accelerate(double speed) { - //f(x) = k/(1+e^(-m(c-x))) - return curve_constant_two / (exp(-curve_constant_one * (speed - curve_constant_three)) + 1); - } - - inline void accel_sigmoid::verify(accel_args args) { - accel_implentation::verify(args); - if (args.lim_exp <= 1) error("exponent must be greater than 1"); - } -} diff --git a/common/accel_types.hpp b/common/accel_types.hpp deleted file mode 100644 index 15f5a50..0000000 --- a/common/accel_types.hpp +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#define _USE_MATH_DEFINES -#include - -namespace rawaccel { - -// Error throwing calls std libraries which are unavailable in kernel mode. -#ifdef _KERNEL_MODE - inline void error(const char*) {} -#else - void error(const char* s); -#endif - - using milliseconds = double; - - /// Struct to hold arguments for an acceleration function. - struct accel_args { - milliseconds time_min = 0.4; - double offset = 0; - double accel = 0; - double lim_exp = 2; - double midpoint = 0; - }; - - /// - /// Struct to hold acceleration curve implementation details. - /// - /// Type of acceleration. - template - struct accel_implentation { - - /// First constant for use in acceleration curves. Generally, the acceleration ramp rate. - double curve_constant_one = 0; - - /// Second constant for use in acceleration curves. Generally, the limit or exponent in the curve. - double curve_constant_two = 0; - - /// Third constant for use in acceleration curves. The midpoint in sigmoid mode. - double curve_constant_three = 0; - - /// The offset past which acceleration is applied. Used in power mode. - double offset = 0; - - /// - /// Initializes a new instance of the struct. - /// - /// - /// - accel_implentation(accel_args args) - { - curve_constant_one = args.accel; - curve_constant_two = args.lim_exp - 1; - curve_constant_three = args.midpoint; - offset = args.offset; - } - - /// - /// Returns accelerated value of speed as a ratio of magnitude. - /// - /// Mouse speed at which to calculate acceleration. - /// Ratio of accelerated movement magnitude to input movement magnitude. - double accelerate(double speed) { return 0; } - - /// - /// Verifies arguments as valid. Errors if not. - /// - /// Arguments to verified. - void verify(accel_args args) { - if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); - if (args.time_min <= 0) error("min time must be positive"); - } - - /// - /// - /// - /// - accel_implentation() = default; - }; - - /// Struct to hold linear acceleration implementation. - struct accel_linear : accel_implentation { - accel_linear(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - - /// Struct to hold "classic" (linear raised to power) acceleration implementation. - struct accel_classic : accel_implentation { - accel_classic(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - - /// Struct to hold "natural" (vanishing difference) acceleration implementation. - struct accel_natural : accel_implentation { - accel_natural(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - - /// Struct to hold logarithmic acceleration implementation. - struct accel_logarithmic : accel_implentation { - accel_logarithmic(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - - /// Struct to hold sigmoid (s-shaped) acceleration implementation. - struct accel_sigmoid : accel_implentation { - accel_sigmoid(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - - /// Struct to hold power (non-additive) acceleration implementation. - struct accel_power : accel_implentation { - accel_power(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - - /// Struct to hold acceleration implementation which applies no acceleration. - struct accel_noaccel : accel_implentation { - accel_noaccel(accel_args args); - double accelerate(double speed); - void verify(accel_args args); - }; - -} diff --git a/common/common.vcxitems b/common/common.vcxitems index f33d8e1..d1e8db0 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -14,20 +14,18 @@ - - + + + + + + + + + - - - - - - - - - \ No newline at end of file diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index 3e8886f..49c0fcd 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -4,6 +4,7 @@ #include "external/clipp.h" +#include #include "rawaccel.hpp" namespace rawaccel { @@ -12,12 +13,14 @@ inline constexpr int SYSTEM_ERROR = -1; inline constexpr int PARSE_ERROR = 1; inline constexpr int INVALID_ARGUMENT = 2; -void error(const char* s) { - throw std::domain_error(s); +template +clipp::parameter make_accel_cmd(modifier_args& args, StrFirst&& first_flag, StrRest&&... rest) { + return clipp::command(first_flag, rest...) + .set(args.acc_fn_args.accel_mode, accel_impl_t::id); } mouse_modifier parse(int argc, char** argv) { - modifier_args modifier_args{}; + modifier_args args{}; auto make_opt_vec = [](vec2d& v, auto first_flag, auto... rest) { return clipp::option(first_flag, rest...) & ( @@ -38,64 +41,64 @@ mouse_modifier parse(int argc, char** argv) { }; // default options - auto opt_sens = "sensitivity (default = 1)" % make_opt_vec(modifier_args.sens, "sens"); + auto opt_sens = "sensitivity (default = 1)" % make_opt_vec(args.sens, "sens"); auto opt_rot = "counter-clockwise rotation (default = 0)" % ( clipp::option("rotate") & - clipp::number("degrees", modifier_args.degrees) + clipp::number("degrees", args.degrees) ); // mode-independent accel options auto opt_weight = "accel multiplier (default = 1)" % - make_opt_vec(modifier_args.acc_fn_args.weight, "weight"); + make_opt_vec(args.acc_fn_args.weight, "weight"); auto opt_offset = "speed (dots/ms) where accel kicks in (default = 0)" % ( - clipp::option("offset") & clipp::number("speed", modifier_args.acc_fn_args.acc_args.offset) + clipp::option("offset") & clipp::number("speed", args.acc_fn_args.acc_args.offset) ); auto opt_cap = "accel scale cap (default = 9)" % - make_opt_vec(modifier_args.acc_fn_args.cap, "cap"); + make_opt_vec(args.acc_fn_args.cap, "cap"); auto opt_tmin = "minimum time between polls (default = 0.4)" % ( clipp::option("tmin") & - clipp::number("ms", modifier_args.acc_fn_args.acc_args.time_min) + clipp::number("ms", args.acc_fn_args.time_min) ); - auto accel_var = (clipp::required("accel") & clipp::number("num", modifier_args.acc_fn_args.acc_args.accel)) % "ramp rate"; - auto limit_var = (clipp::required("limit") & clipp::number("scale", modifier_args.acc_fn_args.acc_args.lim_exp)) % "limit"; + auto accel_var = (clipp::required("accel") & clipp::number("num", args.acc_fn_args.acc_args.accel)) % "ramp rate"; + auto limit_var = (clipp::required("limit") & clipp::number("scale", args.acc_fn_args.acc_args.limit)) % "limit"; + auto exp_var = (clipp::required("exponent") & clipp::number("num", args.acc_fn_args.acc_args.exponent)) % "exponent"; // modes - auto noaccel_mode = "no-accel mode" % ( - clipp::command("off", "noaccel").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id) - ); + auto noaccel_mode = "no-accel mode" % make_accel_cmd(args, "off", "noaccel"); + auto lin_mode = "linear accel mode:" % ( - clipp::command("linear").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), + make_accel_cmd(args, "linear"), accel_var ); auto classic_mode = "classic accel mode:" % ( - clipp::command("classic").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), + make_accel_cmd(args, "classic"), accel_var, - (clipp::required("exponent") & clipp::number("num", modifier_args.acc_fn_args.acc_args.lim_exp)) % "exponent" + exp_var ); auto nat_mode = "natural accel mode:" % ( - clipp::command("natural").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), + make_accel_cmd(args, "natural"), accel_var, limit_var ); auto log_mode = "logarithmic accel mode:" % ( - clipp::command("logarithmic").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), + make_accel_cmd(args, "logarithmic"), accel_var ); auto sig_mode = "sigmoid accel mode:" % ( - clipp::command("sigmoid").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id), + make_accel_cmd(args, "sigmoid"), accel_var, limit_var, - (clipp::required("midpoint") & clipp::number("speed", modifier_args.acc_fn_args.acc_args.midpoint)) % "midpoint" + (clipp::required("midpoint") & clipp::number("speed", args.acc_fn_args.acc_args.midpoint)) % "midpoint" ); auto pow_mode = "power accel mode:" % ( - clipp::command("power").set(modifier_args.acc_fn_args.accel_mode, accel_implementation_t::id) >> [&] { modifier_args.acc_fn_args.acc_args.accel = 1; }, - (clipp::required("exponent") & clipp::number("num", modifier_args.acc_fn_args.acc_args.lim_exp)) % "exponent", - (clipp::option("scale") & clipp::number("num", modifier_args.acc_fn_args.acc_args.accel)) % "scale factor" + make_accel_cmd(args, "power"), + exp_var, + (clipp::option("scale") & clipp::number("num", args.acc_fn_args.acc_args.power_scale)) % "scale factor" ); auto accel_mode_exclusive = (lin_mode | classic_mode | nat_mode | log_mode | sig_mode | pow_mode); @@ -119,7 +122,7 @@ mouse_modifier parse(int argc, char** argv) { std::exit(0); } - return mouse_modifier(modifier_args); + return mouse_modifier(args); } } // rawaccel diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index b480e87..0aeb42d 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -7,13 +7,13 @@ #include "x64-util.hpp" #include "external/tagged-union-single.h" -#include "accel_linear.cpp" -#include "accel_classic.cpp" -#include "accel_natural.cpp" -#include "accel_logarithmic.cpp" -#include "accel_sigmoid.cpp" -#include "accel_power.cpp" -#include "accel_noaccel.cpp" +#include "accel-linear.hpp" +#include "accel-classic.hpp" +#include "accel-natural.hpp" +#include "accel-logarithmic.hpp" +#include "accel-sigmoid.hpp" +#include "accel-power.hpp" +#include "accel-noaccel.hpp" namespace rawaccel { @@ -75,11 +75,11 @@ namespace rawaccel { }; /// Tagged union to hold all accel implementations and allow "polymorphism" via a visitor call. - using accel_implementation_t = tagged_union; + using accel_impl_t = tagged_union; struct accel_fn_args { - accel_args acc_args = accel_args{}; - int accel_mode = 0; + accel_args acc_args; + int accel_mode = accel_impl_t::id; milliseconds time_min = 0.4; vec2d weight = { 1, 1 }; vec2d cap = { 0, 0 }; @@ -100,21 +100,24 @@ namespace rawaccel { double speed_offset = 0; /// The acceleration implementation (i.e. curve) - accel_implementation_t accel; + accel_impl_t accel; /// The weight of acceleration applied in {x, y} dimensions. vec2d weight = { 1, 1 }; + /// The constant added to weighted accel values to get the acceleration scale. + double scale_base = 1; + /// The object which sets a min and max for the acceleration scale. vec2 clamp; - accel_function(accel_fn_args args) { + accel_function(accel_fn_args args) : accel_function() { + verify(args); + accel.tag = args.accel_mode; - accel.visit([&](auto& a){ a = {args.acc_args}; }); + accel.visit([&](auto& impl){ impl = { args.acc_args }; }); - // Verification is performed by the accel_implementation object - // and therefore must occur after the object has been instantiated - verify(args.acc_args); + if (accel.tag == accel_impl_t::id) scale_base = 0; time_min = args.time_min; speed_offset = args.acc_args.offset; @@ -124,20 +127,12 @@ namespace rawaccel { } /// - /// Applies mouse acceleration to a given speed, via visitor function to accel_implementation_t - /// - /// Speed from which to determine acceleration - /// Acceleration as a ratio magnitudes, as a double - double apply(double speed) const { - return accel.visit([=](auto accel_t) { return accel_t.accelerate(speed); }); - } - - /// - /// Verifies acceleration arguments, via visitor function to accel_implementation_t + /// Verifies acceleration arguments, via visitor function to accel_impl_t /// /// Arguments to be verified - void verify(accel_args args) const { - return accel.visit([=](auto accel_t) { accel_t.verify(args); }); + void verify(accel_fn_args args) { + if (args.time_min <= 0) error("min time must be positive"); + if (args.acc_args.offset < 0) error("offset must not be negative"); } /// @@ -151,10 +146,12 @@ namespace rawaccel { double time_clamped = clampsd(time, time_min, 100); double speed = maxsd(mag / time_clamped - speed_offset, 0); - double accel_val = apply(speed); + double accel_val = accel.visit([=](auto&& impl) { + return impl.accelerate(speed); + }); - double scale_x = weight.x * accel_val + 1; - double scale_y = weight.y * accel_val + 1; + double scale_x = weight.x * accel_val + scale_base; + double scale_y = weight.y * accel_val + scale_base; return { input.x * clamp.x(scale_x), @@ -165,11 +162,10 @@ namespace rawaccel { accel_function() = default; }; - struct modifier_args - { + struct modifier_args { double degrees = 0; vec2d sens = { 1, 1 }; - accel_fn_args acc_fn_args = accel_fn_args{}; + accel_fn_args acc_fn_args; }; /// Struct to hold variables and methods for modifying mouse input @@ -187,8 +183,8 @@ namespace rawaccel { if (apply_rotate) rotate = rotator(args.degrees); else rotate = rotator(); - apply_accel = (args.acc_fn_args.accel_mode != 0 && - args.acc_fn_args.accel_mode != accel_implementation_t::id); + apply_accel = args.acc_fn_args.acc_args.accel != 0 && + args.acc_fn_args.accel_mode != accel_impl_t::id; if (args.sens.x == 0) args.sens.x = 1; if (args.sens.y == 0) args.sens.y = 1; @@ -226,10 +222,7 @@ namespace rawaccel { input = rotate(input); } - if (apply_accel) - { - input = accel_fn(input, time); - } + input = accel_fn(input, time); input.x *= sensitivity.x; input.y *= sensitivity.y; -- cgit v1.2.3 From b59cf98c2f326abeb6b993d8ecc5759d23096253 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 30 Jul 2020 22:04:44 -0400 Subject: Make weight a member of accel_base This exposes weight to derived accel types, which now supply a method to transform acceleration into scale. --- common/accel-base.hpp | 21 +++++++++++++++++++-- common/accel-power.hpp | 10 +++++++++- common/rawaccel-userspace.hpp | 2 +- common/rawaccel.hpp | 24 ++++++------------------ 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/common/accel-base.hpp b/common/accel-base.hpp index ed79bdb..e87b463 100644 --- a/common/accel-base.hpp +++ b/common/accel-base.hpp @@ -1,5 +1,7 @@ #pragma once +#include "vec2.h" + namespace rawaccel { // Error throwing calls std libraries which are unavailable in kernel mode. @@ -15,14 +17,18 @@ namespace rawaccel { double exponent = 2; double midpoint = 0; double power_scale = 1; + vec2d weight = { 1, 1 }; }; /// /// Struct to hold common acceleration curve implementation details. /// struct accel_base { - - /// Generally, the acceleration ramp rate. + + /// Coefficients applied to acceleration per axis. + vec2d weight = { 1, 1 }; + + /// Generally, the acceleration ramp rate. double speed_coeff = 0; /// @@ -34,6 +40,17 @@ namespace rawaccel { verify(args); speed_coeff = args.accel; + weight = args.weight; + } + + /// + /// Default transformation of acceleration -> mouse input multipliers. + /// + inline vec2d scale(double accel_val) const { + return { + weight.x * accel_val + 1, + weight.y * accel_val + 1 + }; } /// diff --git a/common/accel-power.hpp b/common/accel-power.hpp index c8b12cd..d96cb96 100644 --- a/common/accel-power.hpp +++ b/common/accel-power.hpp @@ -14,6 +14,7 @@ namespace rawaccel { accel_power(accel_args args) { verify(args); + weight = args.weight; speed_coeff = args.power_scale; exponent = args.exponent; offset = args.offset; @@ -24,8 +25,15 @@ namespace rawaccel { 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(accel_args args) const { - if (args.power_scale < 0) error("scale can not be negative"); + if (args.power_scale <= 0) error("scale must be positive"); if (args.exponent <= 0) error("exponent must be greater than 0"); } }; diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index 49c0fcd..6a79d23 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -50,7 +50,7 @@ mouse_modifier parse(int argc, char** argv) { // mode-independent accel options auto opt_weight = "accel multiplier (default = 1)" % - make_opt_vec(args.acc_fn_args.weight, "weight"); + make_opt_vec(args.acc_fn_args.acc_args.weight, "weight"); auto opt_offset = "speed (dots/ms) where accel kicks in (default = 0)" % ( clipp::option("offset") & clipp::number("speed", args.acc_fn_args.acc_args.offset) diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 0aeb42d..7be37c2 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -81,7 +81,6 @@ namespace rawaccel { accel_args acc_args; int accel_mode = accel_impl_t::id; milliseconds time_min = 0.4; - vec2d weight = { 1, 1 }; vec2d cap = { 0, 0 }; }; @@ -102,26 +101,17 @@ namespace rawaccel { /// The acceleration implementation (i.e. curve) accel_impl_t accel; - /// The weight of acceleration applied in {x, y} dimensions. - vec2d weight = { 1, 1 }; - - /// The constant added to weighted accel values to get the acceleration scale. - double scale_base = 1; - /// The object which sets a min and max for the acceleration scale. vec2 clamp; - accel_function(accel_fn_args args) : accel_function() { + accel_function(accel_fn_args args) { verify(args); accel.tag = args.accel_mode; accel.visit([&](auto& impl){ impl = { args.acc_args }; }); - if (accel.tag == accel_impl_t::id) scale_base = 0; - time_min = args.time_min; speed_offset = args.acc_args.offset; - weight = args.weight; clamp.x = accel_scale_clamp(args.cap.x); clamp.y = accel_scale_clamp(args.cap.y); } @@ -146,16 +136,14 @@ namespace rawaccel { double time_clamped = clampsd(time, time_min, 100); double speed = maxsd(mag / time_clamped - speed_offset, 0); - double accel_val = accel.visit([=](auto&& impl) { - return impl.accelerate(speed); + vec2d scale = accel.visit([=](auto&& impl) { + double accel_val = impl.accelerate(speed); + return impl.scale(accel_val); }); - double scale_x = weight.x * accel_val + scale_base; - double scale_y = weight.y * accel_val + scale_base; - return { - input.x * clamp.x(scale_x), - input.y * clamp.y(scale_y) + input.x * clamp.x(scale.x), + input.y * clamp.y(scale.y) }; } -- cgit v1.2.3 From b3ed8fd4e4fcad0b749126dee62588260d74b106 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Fri, 31 Jul 2020 01:37:41 -0400 Subject: add more tweaks for st-refactor --- common/accel-base.hpp | 16 +++++++++------- common/accel-classic.hpp | 4 ++-- common/accel-linear.hpp | 8 ++------ common/accel-logarithmic.hpp | 2 +- common/accel-natural.hpp | 4 ++-- common/accel-noaccel.hpp | 3 +-- common/accel-power.hpp | 4 ++-- common/accel-sigmoid.hpp | 4 ++-- common/external/tagged-union-single.h | 2 +- common/rawaccel-userspace.hpp | 2 +- common/rawaccel.hpp | 28 +++++++++++----------------- 11 files changed, 34 insertions(+), 43 deletions(-) diff --git a/common/accel-base.hpp b/common/accel-base.hpp index e87b463..da2c96b 100644 --- a/common/accel-base.hpp +++ b/common/accel-base.hpp @@ -31,18 +31,20 @@ namespace rawaccel { /// Generally, the acceleration ramp rate. double speed_coeff = 0; - /// - /// Initializes a new instance of the struct. - /// - /// - /// - accel_base(accel_args args) { + accel_base(const accel_args& args) { verify(args); speed_coeff = args.accel; weight = args.weight; } + /// + /// Default transformation of speed -> acceleration. + /// + inline double accelerate(double speed) const { + return speed_coeff * speed; + } + /// /// Default transformation of acceleration -> mouse input multipliers. /// @@ -57,7 +59,7 @@ namespace rawaccel { /// Verifies arguments as valid. Errors if not. /// /// Arguments to verified. - void verify(accel_args args) const { + void verify(const accel_args& args) const { if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate"); } diff --git a/common/accel-classic.hpp b/common/accel-classic.hpp index e2eb494..1a2adca 100644 --- a/common/accel-classic.hpp +++ b/common/accel-classic.hpp @@ -10,7 +10,7 @@ namespace rawaccel { struct accel_classic : accel_base { double exponent; - accel_classic(accel_args args) : accel_base(args) { + accel_classic(const accel_args& args) : accel_base(args) { verify(args); exponent = args.exponent - 1; @@ -21,7 +21,7 @@ namespace rawaccel { return pow(speed_coeff * speed, exponent); } - void verify(accel_args args) const { + void verify(const accel_args& args) const { if (args.exponent <= 1) error("exponent must be greater than 1"); } }; diff --git a/common/accel-linear.hpp b/common/accel-linear.hpp index 28150a8..5cbb7c6 100644 --- a/common/accel-linear.hpp +++ b/common/accel-linear.hpp @@ -5,14 +5,10 @@ namespace rawaccel { /// Struct to hold linear acceleration implementation. - struct accel_linear : accel_base { + struct accel_linear : accel_base { - accel_linear(accel_args args) : accel_base(args) {} + using accel_base::accel_base; - inline double accelerate(double speed) const { - //f(x) = mx - return speed_coeff * speed; - } }; } diff --git a/common/accel-logarithmic.hpp b/common/accel-logarithmic.hpp index b628327..928eda9 100644 --- a/common/accel-logarithmic.hpp +++ b/common/accel-logarithmic.hpp @@ -9,7 +9,7 @@ namespace rawaccel { /// Struct to hold logarithmic acceleration implementation. struct accel_logarithmic : accel_base { - accel_logarithmic(accel_args args) : accel_base(args) {} + using accel_base::accel_base; inline double accelerate(double speed) const { //f(x) = log(m*x+1) diff --git a/common/accel-natural.hpp b/common/accel-natural.hpp index 6ccb193..c87fda8 100644 --- a/common/accel-natural.hpp +++ b/common/accel-natural.hpp @@ -11,7 +11,7 @@ namespace rawaccel { double limit = 1; double midpoint = 0; - accel_natural(accel_args args) : accel_base(args) { + accel_natural(const accel_args& args) : accel_base(args) { verify(args); limit = args.limit - 1; @@ -23,7 +23,7 @@ namespace rawaccel { return limit - (limit * exp(-speed_coeff * speed)); } - void verify(accel_args args) const { + void verify(const accel_args& args) const { if (args.limit <= 1) error("limit must be greater than 1"); } }; diff --git a/common/accel-noaccel.hpp b/common/accel-noaccel.hpp index 151002a..b7f730b 100644 --- a/common/accel-noaccel.hpp +++ b/common/accel-noaccel.hpp @@ -7,9 +7,8 @@ namespace rawaccel { /// Struct to hold acceleration implementation which applies no acceleration. struct accel_noaccel : accel_base { - accel_noaccel(accel_args args) : accel_base(args) {} + accel_noaccel(const accel_args&) : accel_base() {} - inline double accelerate(double) const { return 0; } }; } diff --git a/common/accel-power.hpp b/common/accel-power.hpp index d96cb96..7f4c220 100644 --- a/common/accel-power.hpp +++ b/common/accel-power.hpp @@ -11,7 +11,7 @@ namespace rawaccel { double exponent; double offset; - accel_power(accel_args args) { + accel_power(const accel_args& args) { verify(args); weight = args.weight; @@ -32,7 +32,7 @@ namespace rawaccel { }; } - void verify(accel_args args) const { + void verify(const accel_args& args) const { if (args.power_scale <= 0) error("scale must be positive"); if (args.exponent <= 0) error("exponent must be greater than 0"); } diff --git a/common/accel-sigmoid.hpp b/common/accel-sigmoid.hpp index e992e0c..7cfa6c4 100644 --- a/common/accel-sigmoid.hpp +++ b/common/accel-sigmoid.hpp @@ -11,7 +11,7 @@ namespace rawaccel { double limit = 1; double midpoint = 0; - accel_sigmoid(accel_args args) : accel_base(args) { + accel_sigmoid(const accel_args& args) : accel_base(args) { verify(args); limit = args.limit - 1; @@ -23,7 +23,7 @@ namespace rawaccel { return limit / (exp(-speed_coeff * (speed - midpoint)) + 1); } - void verify(accel_args args) const { + void verify(const accel_args& args) const { if (args.limit <= 1) error("exponent must be greater than 1"); if (args.midpoint < 0) error("midpoint must not be negative"); } diff --git a/common/external/tagged-union-single.h b/common/external/tagged-union-single.h index bcfc1cf..3353325 100644 --- a/common/external/tagged-union-single.h +++ b/common/external/tagged-union-single.h @@ -137,7 +137,7 @@ struct tagged_union { int tag = 0; struct storage_t { - alignas(max_align_of) char bytes[max_size_of]; + alignas(max_align_of) char bytes[max_size_of] = ""; template inline constexpr T& as() { diff --git a/common/rawaccel-userspace.hpp b/common/rawaccel-userspace.hpp index 6a79d23..c80262c 100644 --- a/common/rawaccel-userspace.hpp +++ b/common/rawaccel-userspace.hpp @@ -4,7 +4,7 @@ #include "external/clipp.h" -#include +#include "accel-error.hpp" #include "rawaccel.hpp" namespace rawaccel { diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 7be37c2..59a0360 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -3,7 +3,6 @@ #define _USE_MATH_DEFINES #include -#include "vec2.h" #include "x64-util.hpp" #include "external/tagged-union-single.h" @@ -104,8 +103,9 @@ namespace rawaccel { /// The object which sets a min and max for the acceleration scale. vec2 clamp; - accel_function(accel_fn_args args) { - verify(args); + accel_function(const accel_fn_args& args) { + if (args.time_min <= 0) error("min time must be positive"); + if (args.acc_args.offset < 0) error("offset must not be negative"); accel.tag = args.accel_mode; accel.visit([&](auto& impl){ impl = { args.acc_args }; }); @@ -116,15 +116,6 @@ namespace rawaccel { clamp.y = accel_scale_clamp(args.cap.y); } - /// - /// Verifies acceleration arguments, via visitor function to accel_impl_t - /// - /// Arguments to be verified - void verify(accel_fn_args args) { - if (args.time_min <= 0) error("min time must be positive"); - if (args.acc_args.offset < 0) error("offset must not be negative"); - } - /// /// Applies weighted acceleration to given input for given time period. /// @@ -164,19 +155,22 @@ namespace rawaccel { accel_function accel_fn; vec2d sensitivity = { 1, 1 }; - mouse_modifier(modifier_args args) + mouse_modifier(const modifier_args& args) : accel_fn(args.acc_fn_args) { apply_rotate = args.degrees != 0; + if (apply_rotate) rotate = rotator(args.degrees); else rotate = rotator(); - apply_accel = args.acc_fn_args.acc_args.accel != 0 && + apply_accel = args.acc_fn_args.accel_mode != 0 && args.acc_fn_args.accel_mode != accel_impl_t::id; - if (args.sens.x == 0) args.sens.x = 1; - if (args.sens.y == 0) args.sens.y = 1; - sensitivity = args.sens; + if (args.sens.x == 0) sensitivity.x = 1; + else sensitivity.x = args.sens.x; + + if (args.sens.y == 0) sensitivity.y = 1; + else sensitivity.y = args.sens.y; } /// -- cgit v1.2.3 From f7c88d689e924010f6f95b22894414f0b96c4aa0 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Fri, 31 Jul 2020 04:52:24 -0400 Subject: update grapher/wrapper for st-refactor --- common/x64-util.hpp | 10 +++++++- grapher/Form1.cs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++- wrapper/wrapper.cpp | 5 +++- wrapper/wrapper.hpp | 18 +++++++------- 4 files changed, 89 insertions(+), 13 deletions(-) diff --git a/common/x64-util.hpp b/common/x64-util.hpp index 2fb61bb..40bc7c4 100644 --- a/common/x64-util.hpp +++ b/common/x64-util.hpp @@ -1,7 +1,13 @@ #pragma once -#include +#ifdef _MANAGED + +#include +inline double sqrtsd(double val) { return sqrt(val); } + +#else +#include inline double sqrtsd(double val) { __m128d src = _mm_load_sd(&val); __m128d dst = _mm_sqrt_sd(src, src); @@ -9,6 +15,8 @@ inline double sqrtsd(double val) { return val; } +#endif + inline constexpr double minsd(double a, double b) { return (a < b) ? a : b; } diff --git a/grapher/Form1.cs b/grapher/Form1.cs index 495640e..47ef1d9 100644 --- a/grapher/Form1.cs +++ b/grapher/Form1.cs @@ -7,15 +7,82 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using System.Runtime.InteropServices; namespace grapher { + public enum accel_mode + { + linear=1, classic, natural, logarithmic, sigmoid, power, 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 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 { public RawAcceleration() { InitializeComponent(); - var managedAccel = new ManagedAccel(5, 0, 0.3, 1.25, 15); + + 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.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 managedAccel = new ManagedAccel(args_ptr); + + Marshal.FreeHGlobal(args_ptr); + var orderedPoints = new SortedDictionary(); for (int i = 0; i < 100; i++) diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index c1cc570..26d05ec 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -7,7 +7,10 @@ using namespace System; Tuple^ ManagedAccel::Accelerate(int x, int y, double time) { - vec2d input_vec2d = {x, y}; + vec2d input_vec2d = { + (double)x, + (double)y + }; vec2d output = (*modifier_instance).modify_with_accel(input_vec2d, (milliseconds)time); return gcnew Tuple(output.x, output.y); diff --git a/wrapper/wrapper.hpp b/wrapper/wrapper.hpp index 19b0987..42f5865 100644 --- a/wrapper/wrapper.hpp +++ b/wrapper/wrapper.hpp @@ -1,11 +1,16 @@ #pragma once #include "..\common\rawaccel.hpp"; -#include "..\common\error.hpp"; +#include "..\common\accel-error.hpp"; #include using namespace rawaccel; using namespace System; + +public value struct ArgsWrapper { + int a; +}; + public ref class ManagedAccel { protected: @@ -16,16 +21,9 @@ public: { } - ManagedAccel(int mode, double offset, double accel, double lim_exp, double midpoint) + ManagedAccel(System::IntPtr args) { - modifier_args args{}; - args.acc_fn_args.acc_args.accel = accel; - args.acc_fn_args.acc_args.lim_exp = lim_exp; - args.acc_fn_args.acc_args.midpoint = midpoint; - args.acc_fn_args.accel_mode = mode; - args.acc_fn_args.acc_args.offset = offset; - - modifier_instance = new mouse_modifier(args); + modifier_instance = new mouse_modifier(*reinterpret_cast(args.ToPointer())); } virtual ~ManagedAccel() -- cgit v1.2.3