diff options
| author | a1xd <[email protected]> | 2021-09-24 02:04:43 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-09-24 02:04:43 -0400 |
| commit | 2896b8a09ce42e965705c58593b8738adc454f7f (patch) | |
| tree | 71e4d0cff60b5a1ad11427d78e1f8c7b775e5690 /common/rawaccel.hpp | |
| parent | Merge pull request #107 from a1xd/1.5.0-fix (diff) | |
| parent | make note clearer (diff) | |
| download | rawaccel-2896b8a09ce42e965705c58593b8738adc454f7f.tar.xz rawaccel-2896b8a09ce42e965705c58593b8738adc454f7f.zip | |
v1.6
Diffstat (limited to 'common/rawaccel.hpp')
| -rw-r--r-- | common/rawaccel.hpp | 261 |
1 files changed, 156 insertions, 105 deletions
diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 4e8b46c..b12fb8b 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -1,83 +1,136 @@ #pragma once -#include "accel-invoke.hpp" +#include "accel-union.hpp" namespace rawaccel { - inline vec2d direction(double degrees) - { - double radians = degrees * PI / 180; - return { cos(radians), sin(radians) }; - } + struct time_clamp { + milliseconds min = DEFAULT_TIME_MIN; + milliseconds max = DEFAULT_TIME_MAX; + }; + + struct device_config { + bool disable = false; + bool set_extra_info = false; + int dpi = 0; + int polling_rate = 0; + time_clamp clamp; + }; + + struct device_settings { + wchar_t name[MAX_NAME_LEN] = {}; + wchar_t profile[MAX_NAME_LEN] = {}; + wchar_t id[MAX_DEV_ID_LEN] = {}; + device_config config; + }; + + enum class distance_mode : unsigned char { + separate, + max, + Lp, + euclidean, + }; + + struct modifier_flags { + bool apply_rotate = 0; + bool compute_ref_angle = 0; + bool apply_snap = 0; + bool clamp_speed = 0; + distance_mode dist_mode = {}; + bool apply_directional_weight = 0; + bool apply_dir_mul_x = 0; + bool apply_dir_mul_y = 0; + + modifier_flags(const profile& args) + { + clamp_speed = args.speed_max > 0 && args.speed_min <= args.speed_max; + apply_rotate = args.degrees_rotation != 0; + apply_snap = args.degrees_snap != 0; + apply_directional_weight = args.range_weights.x != args.range_weights.y; + compute_ref_angle = apply_snap || apply_directional_weight; + apply_dir_mul_x = args.lr_sens_ratio != 1; + apply_dir_mul_y = args.ud_sens_ratio != 1; + + if (!args.whole) { + dist_mode = distance_mode::separate; + } + else if (args.lp_norm >= MAX_NORM || args.lp_norm <= 0) { + dist_mode = distance_mode::max; + } + else if (args.lp_norm != 2) { + dist_mode = distance_mode::Lp; + } + else { + dist_mode = distance_mode::euclidean; + } + } + + modifier_flags() = default; + }; + + struct modifier_settings { + profile prof; + + struct data_t { + modifier_flags flags; + vec2d rot_direction; + accel_union accel_x; + accel_union accel_y; + } data = {}; + }; - constexpr vec2d rotate(const vec2d& v, const vec2d& direction) + inline void init_data(modifier_settings& settings) { - return { - v.x * direction.x - v.y * direction.y, - v.x * direction.y + v.y * direction.x + auto set_accel = [](accel_union& u, const accel_args& args) { + u.visit([&](auto& impl) { + impl = { args }; + }, args); }; - } - inline double magnitude(const vec2d& v) - { - return sqrt(v.x * v.x + v.y * v.y); - } + set_accel(settings.data.accel_x, settings.prof.accel_x); + set_accel(settings.data.accel_y, settings.prof.accel_y); - inline double lp_distance(const vec2d& v, double p) - { - return pow(pow(v.x, p) + pow(v.y, p), 1 / p); + settings.data.rot_direction = direction(settings.prof.degrees_rotation); + + settings.data.flags = modifier_flags(settings.prof); } - class mouse_modifier { - public: - enum accel_distance_mode : unsigned char { - separate, - max, - Lp, - euclidean, - }; + struct io_base { + device_config default_dev_cfg; + unsigned modifier_data_size = 0; + unsigned device_data_size = 0; + }; - bool apply_rotate = false; - bool compute_ref_angle = false; - bool apply_snap = false; - bool cap_speed = false; - accel_distance_mode dist_mode = euclidean; - bool apply_directional_weight = false; - bool apply_dir_mul_x = false; - bool apply_dir_mul_y = false; - - vec2d rot_vec = { 1, 0 }; - double snap = 0; - double dpi_norm_factor = 1; - double speed_min = 0; - double speed_max = 0; - vec2d domain_weights = { 1, 1 }; - double p = 2; - vec2d range_weights = { 1, 1 }; - vec2d directional_multipliers = { 1, 1 }; - vec2d sensitivity = { 1, 1 }; - vec2<accel_union> accel; + static_assert(alignof(io_base) == alignof(modifier_settings) && alignof(modifier_settings) == alignof(device_settings)); + class modifier { + public: #ifdef _KERNEL_MODE __forceinline #endif - void modify(vec2d& in, const vec2<accel_invoker>& inv, milliseconds time = 1) const + void modify(vec2d& in, const modifier_settings& settings, double dpi_factor, milliseconds time) const { - double ips_factor = dpi_norm_factor / time; + auto& args = settings.prof; + auto& data = settings.data; + auto& flags = settings.data.flags; + double reference_angle = 0; + double ips_factor = dpi_factor / time; - if (apply_rotate) in = rotate(in, rot_vec); + if (flags.apply_rotate) in = rotate(in, data.rot_direction); - if (compute_ref_angle && in.y != 0) { + if (flags.compute_ref_angle && in.y != 0) { if (in.x == 0) { - reference_angle = PI / 2; + reference_angle = M_PI / 2; } else { reference_angle = atan(fabs(in.y / in.x)); - if (apply_snap) { - if (reference_angle > PI / 2 - snap) { - reference_angle = PI / 2; + if (flags.apply_snap) { + double snap = args.degrees_snap * M_PI / 180; + + if (reference_angle > M_PI / 2 - snap) { + reference_angle = M_PI / 2; in = { 0, _copysign(magnitude(in), in.y) }; } else if (reference_angle < snap) { @@ -88,92 +141,90 @@ namespace rawaccel { } } - if (cap_speed) { + if (flags.clamp_speed) { double speed = magnitude(in) * ips_factor; - double ratio = clampsd(speed, speed_min, speed_max) / speed; + double ratio = clampsd(speed, args.speed_min, args.speed_max) / speed; in.x *= ratio; in.y *= ratio; } vec2d abs_weighted_vel = { - fabs(in.x * ips_factor * domain_weights.x), - fabs(in.y * ips_factor * domain_weights.y) + fabs(in.x * ips_factor * args.domain_weights.x), + fabs(in.y * ips_factor * args.domain_weights.y) }; - if (dist_mode == separate) { - in.x *= inv.x.invoke(accel.x, abs_weighted_vel.x, range_weights.x); - in.y *= inv.y.invoke(accel.y, abs_weighted_vel.y, range_weights.y); + if (flags.dist_mode == distance_mode::separate) { + in.x *= (*cb_x)(data.accel_x, args.accel_x, abs_weighted_vel.x, args.range_weights.x); + in.y *= (*cb_y)(data.accel_y, args.accel_y, abs_weighted_vel.y, args.range_weights.y); } - else { + else { double speed; - if (dist_mode == max) { + if (flags.dist_mode == distance_mode::max) { speed = maxsd(abs_weighted_vel.x, abs_weighted_vel.y); } - else if (dist_mode == Lp) { - speed = lp_distance(abs_weighted_vel, p); + else if (flags.dist_mode == distance_mode::Lp) { + speed = lp_distance(abs_weighted_vel, args.lp_norm); } else { speed = magnitude(abs_weighted_vel); } - double weight = range_weights.x; + double weight = args.range_weights.x; - if (apply_directional_weight) { - double diff = range_weights.y - range_weights.x; - weight += 2 / PI * reference_angle * diff; + if (flags.apply_directional_weight) { + double diff = args.range_weights.y - args.range_weights.x; + weight += 2 / M_PI * reference_angle * diff; } - double scale = inv.x.invoke(accel.x, speed, weight); + double scale = (*cb_x)(data.accel_x, args.accel_x, speed, weight); in.x *= scale; in.y *= scale; } - if (apply_dir_mul_x && in.x < 0) { - in.x *= directional_multipliers.x; - } + double dpi_adjusted_sens = args.sensitivity * dpi_factor; + in.x *= dpi_adjusted_sens; + in.y *= dpi_adjusted_sens * args.yx_sens_ratio; - if (apply_dir_mul_y && in.y < 0) { - in.y *= directional_multipliers.y; + if (flags.apply_dir_mul_x && in.x < 0) { + in.x *= args.lr_sens_ratio; } - in.x *= sensitivity.x; - in.y *= sensitivity.y; + if (flags.apply_dir_mul_y && in.y < 0) { + in.y *= args.ud_sens_ratio; + } } - mouse_modifier(const settings& args) : - rot_vec(direction(args.degrees_rotation)), - snap(args.degrees_snap * PI / 180), - dpi_norm_factor(1000 / args.dpi), - speed_min(args.speed_min), - speed_max(args.speed_max), - p(args.dom_args.lp_norm), - domain_weights(args.dom_args.domain_weights), - range_weights(args.range_weights), - directional_multipliers(args.dir_multipliers), - sensitivity(args.sens), - accel({ { args.argsv.x }, { args.argsv.y } }) + modifier(modifier_settings& settings) { - cap_speed = speed_max > 0 && speed_min <= speed_max; - apply_rotate = rot_vec.x != 1; - apply_snap = snap != 0; - apply_directional_weight = range_weights.x != range_weights.y; - compute_ref_angle = apply_snap || apply_directional_weight; - apply_dir_mul_x = directional_multipliers.x != 1; - apply_dir_mul_y = directional_multipliers.y != 1; + set_callback(cb_x, settings.data.accel_x, settings.prof.accel_x); + set_callback(cb_y, settings.data.accel_y, settings.prof.accel_y); + } + + modifier() = default; - if (!args.combine_mags) dist_mode = separate; - else if (p >= MAX_NORM || p <= 0) dist_mode = max; - else if (p != 2) dist_mode = Lp; - else dist_mode = euclidean; + private: + using callback_t = double (*)(const accel_union&, const accel_args&, double, double); + + void set_callback(callback_t& cb, accel_union& u, const accel_args& args) + { + u.visit([&](auto& impl) { + cb = &callback_template<remove_ref_t<decltype(impl)>>; + }, args); } - mouse_modifier() = default; - }; + template <typename AccelFunc> + static double callback_template(const accel_union& u, + const accel_args& args, + double x, + double range_weight) + { + auto& accel_fn = reinterpret_cast<const AccelFunc&>(u); + return 1 + (accel_fn(x, args) - 1) * range_weight; + } - struct io_t { - settings args; - mouse_modifier mod; + callback_t cb_x = &callback_template<accel_noaccel>; + callback_t cb_y = &callback_template<accel_noaccel>; }; } // rawaccel |