summaryrefslogtreecommitdiff
path: root/common/rawaccel.hpp
diff options
context:
space:
mode:
authora1xd <[email protected]>2021-09-24 02:04:43 -0400
committerGitHub <[email protected]>2021-09-24 02:04:43 -0400
commit2896b8a09ce42e965705c58593b8738adc454f7f (patch)
tree71e4d0cff60b5a1ad11427d78e1f8c7b775e5690 /common/rawaccel.hpp
parentMerge pull request #107 from a1xd/1.5.0-fix (diff)
parentmake note clearer (diff)
downloadrawaccel-1.6.0.tar.xz
rawaccel-1.6.0.zip
Merge pull request #108 from a1xd/1.6r2HEADv1.6.0masterdark-mode
v1.6
Diffstat (limited to 'common/rawaccel.hpp')
-rw-r--r--common/rawaccel.hpp261
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