summaryrefslogtreecommitdiff
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
parentMerge pull request #107 from a1xd/1.5.0-fix (diff)
parentmake note clearer (diff)
downloadrawaccel-master.tar.xz
rawaccel-master.zip
Merge pull request #108 from a1xd/1.6r2HEADv1.6.0masterdark-mode
v1.6
-rw-r--r--common/accel-classic.hpp135
-rw-r--r--common/accel-invoke.hpp52
-rw-r--r--common/accel-jump.hpp18
-rw-r--r--common/accel-lookup.hpp305
-rw-r--r--common/accel-motivity.hpp81
-rw-r--r--common/accel-natural.hpp19
-rw-r--r--common/accel-noaccel.hpp2
-rw-r--r--common/accel-power.hpp161
-rw-r--r--common/accel-union.hpp119
-rw-r--r--common/common.vcxitems3
-rw-r--r--common/math-vec2.hpp37
-rw-r--r--common/rawaccel-base.hpp94
-rw-r--r--common/rawaccel-io-def.h10
-rw-r--r--common/rawaccel-io.hpp55
-rw-r--r--common/rawaccel-validate.hpp184
-rw-r--r--common/rawaccel-version.h6
-rw-r--r--common/rawaccel.hpp261
-rw-r--r--common/utility-install.hpp23
-rw-r--r--common/utility.hpp15
-rw-r--r--common/vec2.h9
-rw-r--r--converter/converter.cpp50
-rw-r--r--doc/Guide.md34
-rw-r--r--doc/images/LUT_example.pngbin55969 -> 65568 bytes
-rw-r--r--doc/images/accel_readme_example.pngbin50019 -> 65975 bytes
-rw-r--r--doc/images/anisotropy_example.pngbin62022 -> 55900 bytes
-rw-r--r--doc/images/classic_example.pngbin54866 -> 65169 bytes
-rw-r--r--doc/images/jump_example.pngbin47816 -> 59152 bytes
-rw-r--r--doc/images/linear_example.pngbin50547 -> 65667 bytes
-rw-r--r--doc/images/motivity_example.pngbin50916 -> 89155 bytes
-rw-r--r--doc/images/natural_gain_example.pngbin50679 -> 62130 bytes
-rw-r--r--doc/images/power_example.pngbin50340 -> 64430 bytes
-rw-r--r--driver/driver.cpp340
-rw-r--r--driver/driver.h22
-rw-r--r--driver/driver.vcxproj10
-rw-r--r--grapher/Constants/Constants.cs25
-rw-r--r--grapher/DeviceMenuForm.cs405
-rw-r--r--grapher/Form1.Designer.cs1194
-rw-r--r--grapher/Form1.cs162
-rw-r--r--grapher/Layouts/ClassicLayout.cs11
-rw-r--r--grapher/Layouts/DefaultLayout.cs11
-rw-r--r--grapher/Layouts/JumpLayout.cs11
-rw-r--r--grapher/Layouts/LUTLayout.cs11
-rw-r--r--grapher/Layouts/LayoutBase.cs78
-rw-r--r--grapher/Layouts/LinearLayout.cs12
-rw-r--r--grapher/Layouts/MotivityLayout.cs11
-rw-r--r--grapher/Layouts/NaturalLayout.cs11
-rw-r--r--grapher/Layouts/OffLayout.cs11
-rw-r--r--grapher/Layouts/PowerLayout.cs11
-rw-r--r--grapher/Layouts/UnsupportedLayout.cs11
-rw-r--r--grapher/Models/AccelGUI.cs84
-rw-r--r--grapher/Models/AccelGUIFactory.cs341
-rw-r--r--grapher/Models/Calculations/AccelCalculator.cs20
-rw-r--r--grapher/Models/Calculations/Data/AccelDataCombined.cs4
-rw-r--r--grapher/Models/Calculations/Data/AccelDataXYComponential.cs7
-rw-r--r--grapher/Models/Calculations/Data/AccelDataXYDirectional.cs2
-rw-r--r--grapher/Models/Calculations/Data/IAccelData.cs2
-rw-r--r--grapher/Models/Charts/AccelCharts.cs8
-rw-r--r--grapher/Models/Charts/ChartState/ChartState.cs6
-rw-r--r--grapher/Models/Charts/ChartState/ChartStateManager.cs6
-rw-r--r--grapher/Models/Charts/ChartState/XYTwoGraphState.cs2
-rw-r--r--grapher/Models/Devices/DeviceDialogItem.cs26
-rw-r--r--grapher/Models/Devices/DeviceIDItem.cs73
-rw-r--r--grapher/Models/Devices/DeviceIDManager.cs68
-rw-r--r--grapher/Models/Mouse/MouseWatcher.cs47
-rw-r--r--grapher/Models/Options/AccelOptionSet.cs2
-rw-r--r--grapher/Models/Options/AccelTypeOptions.cs176
-rw-r--r--grapher/Models/Options/ApplyOptions.cs34
-rw-r--r--grapher/Models/Options/Cap/CapOptions.cs249
-rw-r--r--grapher/Models/Options/Cap/CapTypeOptions.cs160
-rw-r--r--grapher/Models/Options/CheckBoxOption.cs9
-rw-r--r--grapher/Models/Options/ComboBoxOptionsBase.cs124
-rw-r--r--grapher/Models/Options/Directionality/DirectionalityOptions.cs21
-rw-r--r--grapher/Models/Options/LUT/LUTPanelOptions.cs27
-rw-r--r--grapher/Models/Options/LUT/LutApplyOptions.cs138
-rw-r--r--grapher/Models/Options/LockableOption.cs137
-rw-r--r--grapher/Models/Options/SwitchOption.cs162
-rw-r--r--grapher/Models/Serialized/SettingsManager.cs236
-rw-r--r--grapher/grapher.csproj11
-rw-r--r--installer/installer.cpp89
-rw-r--r--signed/driver/rawaccel.sysbin72304 -> 50176 bytes
-rw-r--r--signed/installer.exebin60296 -> 61752 bytes
-rw-r--r--signed/uninstaller.exebin55688 -> 54584 bytes
-rw-r--r--uninstaller/uninstaller.cpp20
-rw-r--r--wrapper/input.cpp120
-rw-r--r--wrapper/input.h110
-rw-r--r--wrapper/wrapper.cpp912
-rw-r--r--wrapper/wrapper.vcxproj7
-rw-r--r--writer/Program.cs101
88 files changed, 5044 insertions, 2517 deletions
diff --git a/common/accel-classic.hpp b/common/accel-classic.hpp
index 4385897..2ca1233 100644
--- a/common/accel-classic.hpp
+++ b/common/accel-classic.hpp
@@ -3,84 +3,142 @@
#include "rawaccel-base.hpp"
#include "utility.hpp"
-#include <math.h>
#include <float.h>
namespace rawaccel {
/// <summary> Struct to hold "classic" (linear raised to power) acceleration implementation. </summary>
struct classic_base {
- double offset;
- double power;
- double accel_raised;
-
- classic_base(const accel_args& args) :
- offset(args.offset),
- power(args.power),
- accel_raised(pow(args.accel_classic, power - 1)) {}
+ double base_fn(double x, double accel_raised, const accel_args& args) const
+ {
+ return accel_raised * pow(x - args.input_offset, args.exponent_classic) / x;
+ }
- double base_fn(double x) const
+ static double base_accel(double x, double y, const accel_args& args)
{
- return accel_raised * pow(x - offset, power) / x;
+ auto power = args.exponent_classic;
+ return pow(x * y * pow(x - args.input_offset, -power), 1 / (power - 1));
}
};
- struct classic_legacy : classic_base {
- double sens_cap = DBL_MAX;
+ template <bool Gain> struct classic;
+
+ template<>
+ struct classic<LEGACY> : classic_base {
+ double accel_raised;
+ double cap = DBL_MAX;
double sign = 1;
- classic_legacy(const accel_args& args) :
- classic_base(args)
+ classic(const accel_args& args)
{
- if (args.cap > 0) {
- sens_cap = args.cap - 1;
+ switch (args.cap_mode) {
+ case cap_mode::io:
+ cap = args.cap.y - 1;
- if (sens_cap < 0) {
- sens_cap = -sens_cap;
+ if (cap < 0) {
+ cap = -cap;
sign = -sign;
}
+
+ {
+ double a = base_accel(args.cap.x, cap, args);
+ accel_raised = pow(a, args.exponent_classic - 1);
+ }
+ break;
+ case cap_mode::in:
+ accel_raised = pow(args.acceleration, args.exponent_classic - 1);
+ if (args.cap.x > 0) {
+ cap = base_fn(args.cap.x, accel_raised, args);
+ }
+ break;
+ case cap_mode::out:
+ default:
+ accel_raised = pow(args.acceleration, args.exponent_classic - 1);
+
+ if (args.cap.y > 0) {
+ cap = args.cap.y - 1;
+
+ if (cap < 0) {
+ cap = -cap;
+ sign = -sign;
+ }
+ }
+
+ break;
}
}
- double operator()(double x) const
+ double operator()(double x, const accel_args& args) const
{
- if (x <= offset) return 1;
- return sign * minsd(base_fn(x), sens_cap) + 1;
- }
+ if (x <= args.input_offset) return 1;
+ return sign * minsd(base_fn(x, accel_raised, args), cap) + 1;
+ }
+
};
- struct classic : classic_base {
- vec2d gain_cap = { DBL_MAX, DBL_MAX };
+ template<>
+ struct classic<GAIN> : classic_base {
+ double accel_raised;
+ vec2d cap = { DBL_MAX, DBL_MAX };
double constant = 0;
double sign = 1;
- classic(const accel_args& args) :
- classic_base(args)
+ classic(const accel_args& args)
{
- if (args.cap > 0) {
- gain_cap.y = args.cap - 1;
+ switch (args.cap_mode) {
+ case cap_mode::io:
+ cap.x = args.cap.x;
+ cap.y = args.cap.y - 1;
- if (gain_cap.y < 0) {
- gain_cap.y = -gain_cap.y;
+ if (cap.y < 0) {
+ cap.y = -cap.y;
sign = -sign;
}
- gain_cap.x = gain_inverse(gain_cap.y, args.accel_classic, power, offset);
- constant = (base_fn(gain_cap.x) - gain_cap.y) * gain_cap.x;
+ {
+ double a = gain_accel(cap.x, cap.y, args.exponent_classic, args.input_offset);
+ accel_raised = pow(a, args.exponent_classic - 1);
+ }
+ constant = (base_fn(cap.x, accel_raised, args) - cap.y) * cap.x;
+ break;
+ case cap_mode::in:
+ accel_raised = pow(args.acceleration, args.exponent_classic - 1);
+ if (args.cap.x > 0) {
+ cap.x = args.cap.x;
+ cap.y = gain(cap.x, args.acceleration, args.exponent_classic, args.input_offset);
+ constant = (base_fn(cap.x, accel_raised, args) - cap.y) * cap.x;
+ }
+ break;
+ case cap_mode::out:
+ default:
+ accel_raised = pow(args.acceleration, args.exponent_classic - 1);
+
+ if (args.cap.y > 0) {
+ cap.y = args.cap.y - 1;
+
+ if (cap.y < 0) {
+ cap.y = -cap.y;
+ sign = -sign;
+ }
+
+ cap.x = gain_inverse(cap.y, args.acceleration, args.exponent_classic, args.input_offset);
+ constant = (base_fn(cap.x, accel_raised, args) - cap.y) * cap.x;
+ }
+ break;
}
}
- double operator()(double x) const
+ double operator()(double x, const accel_args& args) const
{
double output;
- if (x <= offset) return 1;
+ if (x <= args.input_offset) return 1;
- if (x < gain_cap.x) {
- output = base_fn(x);
+ if (x < cap.x) {
+ output = base_fn(x, accel_raised, args);
}
else {
- output = constant / x + gain_cap.y;
+ output = constant / x + cap.y;
}
return sign * output + 1;
@@ -100,6 +158,7 @@ namespace rawaccel {
{
return -pow(y / power, 1 / (power - 1)) / (offset - x);
}
+
};
}
diff --git a/common/accel-invoke.hpp b/common/accel-invoke.hpp
deleted file mode 100644
index f2a95dc..0000000
--- a/common/accel-invoke.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include "accel-union.hpp"
-
-namespace rawaccel {
-
- class accel_invoker {
- using callback_t = double (*)(const accel_union&, double, double);
-
- callback_t cb = &invoke_impl<accel_noaccel>;
-
- template <typename T>
- static double invoke_impl(const accel_union& u, double x, double w)
- {
- return apply_weighted(reinterpret_cast<const T&>(u), x, w);
- }
-
- public:
-
- accel_invoker(const accel_args& args)
- {
- cb = visit_accel([](auto&& arg) {
- using T = remove_ref_t<decltype(arg)>;
-
- if constexpr (is_same_v<T, motivity>) {
- static_assert(sizeof motivity == sizeof binlog_lut);
- return &invoke_impl<binlog_lut>;
- }
- else {
- return &invoke_impl<T>;
- }
-
- }, make_mode(args), accel_union{});
- }
-
- accel_invoker() = default;
-
- double invoke(const accel_union& u, double x, double weight = 1) const
- {
- return (*cb)(u, x, weight);
- }
- };
-
- inline vec2<accel_invoker> invokers(const settings& args)
- {
- return {
- accel_invoker(args.argsv.x),
- accel_invoker(args.argsv.y)
- };
- }
-
-}
diff --git a/common/accel-jump.hpp b/common/accel-jump.hpp
index 95fa461..e3d798e 100644
--- a/common/accel-jump.hpp
+++ b/common/accel-jump.hpp
@@ -5,14 +5,14 @@
namespace rawaccel {
struct jump_base {
- static constexpr double smooth_scale = 2 * PI;
+ static constexpr double smooth_scale = 2 * M_PI;
vec2d step;
double smooth_rate;
// requirements: args.smooth in range [0, 1]
jump_base(const accel_args& args) :
- step({ args.offset, args.cap - 1 })
+ step({ args.cap.x, args.cap.y - 1 })
{
double rate_inverse = args.smooth * step.x;
@@ -43,12 +43,16 @@ namespace rawaccel {
{
return step.y * (x + log(1 + decay(x)) / smooth_rate);
}
+
};
- struct jump_legacy : jump_base {
+ template <bool Gain> struct jump;
+
+ template<>
+ struct jump<LEGACY> : jump_base {
using jump_base::jump_base;
- double operator()(double x) const
+ double operator()(double x, const accel_args&) const
{
if (is_smooth()) return smooth(x) + 1;
else if (x < step.x) return 1;
@@ -56,14 +60,15 @@ namespace rawaccel {
}
};
- struct jump : jump_base {
+ template<>
+ struct jump<GAIN> : jump_base {
double C;
jump(const accel_args& args) :
jump_base(args),
C(-smooth_antideriv(0)) {}
- double operator()(double x) const
+ double operator()(double x, const accel_args&) const
{
if (x <= 0) return 1;
@@ -72,6 +77,7 @@ namespace rawaccel {
if (x < step.x) return 1;
else return 1 + step.y * (x - step.x) / x;
}
+
};
}
diff --git a/common/accel-lookup.hpp b/common/accel-lookup.hpp
index 99f39e9..920df1c 100644
--- a/common/accel-lookup.hpp
+++ b/common/accel-lookup.hpp
@@ -3,31 +3,8 @@
#include "rawaccel-base.hpp"
#include "utility.hpp"
-#include <math.h>
-
namespace rawaccel {
- struct linear_range {
- double start;
- double stop;
- int num;
-
- template <typename Func>
- void for_each(Func fn) const
- {
- double interval = (stop - start) / (num - 1);
- for (int i = 0; i < num; i++) {
- fn(i * interval + start);
- }
- }
-
- int size() const
- {
- return num;
- }
- };
-
-
// represents the range [2^start, 2^stop], with num - 1
// elements linearly spaced between each exponential step
struct fp_rep_range {
@@ -55,252 +32,70 @@ namespace rawaccel {
}
};
- template <typename Lookup>
- struct lut_base {
- enum { capacity = SPACED_LUT_CAPACITY };
- using value_t = float;
-
- template <typename Func>
- void fill(Func fn)
- {
- auto* self = static_cast<Lookup*>(this);
-
- self->range.for_each([&, fn, i = 0](double x) mutable {
- self->data[i++] = static_cast<value_t>(fn(x));
- });
- }
-
- };
-
- struct linear_lut : lut_base<linear_lut> {
- linear_range range;
- bool transfer = false;
- value_t data[capacity] = {};
-
- double operator()(double x) const
- {
- if (x > range.start) {
- double range_dist = range.stop - range.start;
- double idx_f = (x - range.start) * (range.num - 1) / range_dist;
-
- unsigned idx = min(static_cast<int>(idx_f), range.size() - 2);
-
- if (idx < capacity - 1) {
- double y = lerp(data[idx], data[idx + 1], idx_f - idx);
- if (transfer) y /= x;
- return y;
- }
- }
-
- double y = data[0];
- if (transfer) y /= range.start;
- return y;
+ __forceinline
+ constexpr double lerp(double a, double b, double t)
+ {
+ double x = a + t * (b - a);
+ if ((t > 1) == (a < b)) {
+ return maxsd(x, b);
}
+ return minsd(x, b);
+ }
- linear_lut(const spaced_lut_args& args) :
- range({
- args.start,
- args.stop,
- args.num_elements
- }),
- transfer(args.transfer) {}
+ struct lookup {
+ enum { capacity = LUT_POINTS_CAPACITY };
- linear_lut(const accel_args& args) :
- linear_lut(args.spaced_args) {}
- };
+ int size;
+ bool velocity;
- struct binlog_lut : lut_base<binlog_lut> {
- fp_rep_range range;
- double x_start;
- bool transfer = false;
- value_t data[capacity] = {};
+ lookup(const accel_args& args) :
+ size(args.length / 2),
+ velocity(args.gain) {}
- double operator()(double x) const
+ double operator()(double x, const accel_args& args) const
{
- int e = min(ilogb(x), range.stop - 1);
-
- if (e >= range.start) {
- int idx_int_log_part = e - range.start;
- double idx_frac_lin_part = scalbn(x, -e) - 1;
- double idx_f = range.num * (idx_int_log_part + idx_frac_lin_part);
-
- unsigned idx = min(static_cast<int>(idx_f), range.size() - 2);
+ auto* points = reinterpret_cast<const vec2<float>*>(args.data);
+
+ int lo = 0;
+ int hi = size - 2;
+
+ if (x <= 0) return 0;
+
+ if (hi < capacity - 1) {
+
+ while (lo <= hi) {
+ int mid = (lo + hi) / 2;
+ auto p = points[mid];
+
+ if (x < p.x) {
+ hi = mid - 1;
+ }
+ else if (x > p.x) {
+ lo = mid + 1;
+ }
+ else {
+ double y = p.y;
+ if (velocity) y /= x;
+ return y;
+ }
+ }
- if (idx < capacity - 1) {
- double y = lerp(data[idx], data[idx + 1], idx_f - idx);
- if (transfer) y /= x;
+ if (lo > 0) {
+ auto& a = points[lo - 1];
+ auto& b = points[lo];
+ double t = (x - a.x) / (b.x - a.x);
+ double y = lerp(a.y, b.y, t);
+ if (velocity) y /= x;
return y;
}
+
}
- double y = data[0];
- if (transfer) y /= x_start;
+ double y = points[0].y;
+ if (velocity) y /= points[0].x;
return y;
}
-
- binlog_lut(const spaced_lut_args& args) :
- range({
- static_cast<int>(args.start),
- static_cast<int>(args.stop),
- args.num_elements
- }),
- x_start(scalbn(1, range.start)),
- transfer(args.transfer) {}
-
- binlog_lut(const accel_args& args) :
- binlog_lut(args.spaced_args) {}
};
- struct si_pair {
- float slope = 0;
- float intercept = 0;
- };
-
- struct arbitrary_lut_point {
- float applicable_speed = 0;
- si_pair slope_intercept = {};
- };
- struct arbitrary_lut {
- enum { capacity = ARB_LUT_CAPACITY };
-
- fp_rep_range range;
- arbitrary_lut_point data[capacity] = {};
- int log_lookup[capacity] = {};
- double first_point_speed;
- double last_point_speed;
- int last_arbitrary_index;
- int last_log_lookup_index;
- double last_log_lookup_speed;
- double first_log_lookup_speed;
- bool velocity_points;
-
- double operator()(double speed) const
- {
- int index = 0;
- int last_arb_index = last_arbitrary_index;
- int last_log_index = last_log_lookup_index;
-
- if (speed <= 0) return 1;
-
- if (unsigned(last_arb_index) < capacity &&
- unsigned(last_log_index) < capacity &&
- speed > first_point_speed)
- {
- if (speed > last_point_speed)
- {
- index = last_arb_index;
- }
- else if (speed > last_log_lookup_speed)
- {
- int last_log = log_lookup[last_log_index];
- if (unsigned(last_log) >= capacity) return 1;
- index = search_from(last_log, last_arb_index, speed);
- }
- else if (speed < first_log_lookup_speed)
- {
- index = search_from(0, last_arb_index, speed);
- }
- else
- {
- int log_index = get_log_index(speed);
- if (unsigned(log_index) >= capacity) return 1;
- int arbitrary_index = log_lookup[log_index];
- if (arbitrary_index < 0) return 1;
- index = search_from(arbitrary_index, last_arb_index, speed);
- }
-
- }
-
- return apply(index, speed);
- }
-
- int inline get_log_index(double speed) const
- {
- double speed_log = log(speed) - range.start;
- int index = (int)floor(speed_log * range.num);
- return index;
- }
-
- int inline search_from(int index, int last, double speed) const
- {
- do
- {
- index++;
- }
- while (index <= last && data[index].applicable_speed < speed);
-
- return index - 1;
- }
-
- double inline apply(int index, double speed) const
- {
- auto [slope, intercept] = data[index].slope_intercept;
-
- if (velocity_points)
- {
- return slope + intercept / speed;
- }
- else
- {
- return slope * speed + intercept;
- }
- }
-
- void fill(const vec2<float>* points, int length)
- {
- first_point_speed = points[0].x;
- last_arbitrary_index = length - 1;
- // -2 because the last index in the arbitrary array is used for slope-intercept only
- last_point_speed = points[length-2].x;
-
- int start = static_cast<int>(floor(log(first_point_speed)));
- first_log_lookup_speed = exp(start*1.0);
- int end = static_cast<int>(floor(log(last_point_speed)));
- last_log_lookup_speed = exp(end*1.0);
- int num = end > start ? static_cast<int>(capacity / (end - start)) : 1;
- range = fp_rep_range{ start, end, num };
- last_log_lookup_index = end > start ? num * (end - start) - 1 : 0;
-
- vec2<float> current = {0, velocity_points ? 0.0f : 1.0f };
- vec2<float> next;
- int log_index = 0;
- double log_inner_iterator = range.start;
- double log_inner_slice = 1.0 / (range.num * 1.0);
- double log_value = exp(log_inner_iterator);
-
- for (int i = 0; i < length; i++)
- {
- next = points[i];
- double slope = (next.y - current.y) / (next.x - current.x);
- double intercept = next.y - slope * next.x;
- si_pair current_si = {
- static_cast<float>(slope),
- static_cast<float>(intercept)
- };
- arbitrary_lut_point current_lut_point = {
- static_cast<float>(current.x),
- current_si
- };
-
- this->data[i] = current_lut_point;
-
- while (log_value < next.x && log_inner_iterator < end)
- {
- this->log_lookup[log_index] = i;
- log_index++;
- log_inner_iterator += log_inner_slice;
- log_value = exp(log_inner_iterator);
- }
-
- current = next;
- }
- }
-
- arbitrary_lut(const accel_args& args)
- {
- velocity_points = args.arb_args.velocity;
- fill(args.arb_args.data, args.arb_args.length);
- }
- };
}
diff --git a/common/accel-motivity.hpp b/common/accel-motivity.hpp
index 0efe7ea..e9be023 100644
--- a/common/accel-motivity.hpp
+++ b/common/accel-motivity.hpp
@@ -2,43 +2,52 @@
#include "accel-lookup.hpp"
-#include <math.h>
-
namespace rawaccel {
- struct sigmoid {
+ template <bool Gain> struct loglog_sigmoid;
+
+ template <>
+ struct loglog_sigmoid<LEGACY> {
double accel;
double motivity;
double midpoint;
double constant;
- sigmoid(const accel_args& args) :
+ loglog_sigmoid(const accel_args& args) :
accel(exp(args.growth_rate)),
motivity(2 * log(args.motivity)),
midpoint(log(args.midpoint)),
constant(-motivity / 2) {}
- double operator()(double x) const
+ double operator()(double x, const accel_args&) const
{
double denom = exp(accel * (midpoint - log(x))) + 1;
return exp(motivity / denom + constant);
}
+
};
- /// <summary> Struct to hold sigmoid (s-shaped) gain implementation. </summary>
- struct motivity : binlog_lut {
+ template <>
+ struct loglog_sigmoid<GAIN> {
+ enum { capacity = LUT_RAW_DATA_CAPACITY };
- using binlog_lut::operator();
+ bool velocity;
+ fp_rep_range range;
+ double x_start;
- motivity(const accel_args& args) :
- binlog_lut(args)
+ loglog_sigmoid(const accel_args& args)
{
+ init({ -3, 9, 8 }, true);
+
double sum = 0;
double a = 0;
- auto sigmoid_sum = [&, sig = sigmoid(args)](double b) mutable {
- double interval = (b - a) / args.spaced_args.partitions;
- for (int i = 1; i <= args.spaced_args.partitions; i++) {
- sum += sig(a + i * interval) * interval;
+ auto sig = loglog_sigmoid<LEGACY>(args);
+ auto sigmoid_sum = [&](double b) {
+ int partitions = 2;
+
+ double interval = (b - a) / partitions;
+ for (int i = 1; i <= partitions; i++) {
+ sum += sig(a + i * interval, args) * interval;
}
a = b;
return sum;
@@ -46,9 +55,49 @@ namespace rawaccel {
fill([&](double x) {
double y = sigmoid_sum(x);
- if (!this->transfer) y /= x;
+ if (!velocity) y /= x;
return y;
- });
+ }, args, range);
+ }
+
+ double operator()(double x, const accel_args& args) const
+ {
+ auto* data = args.data;
+
+ int e = min(ilogb(x), range.stop - 1);
+
+ if (e >= range.start) {
+ int idx_int_log_part = e - range.start;
+ double idx_frac_lin_part = scalbn(x, -e) - 1;
+ double idx_f = range.num * (idx_int_log_part + idx_frac_lin_part);
+
+ unsigned idx = min(static_cast<int>(idx_f), range.size() - 2);
+
+ if (idx < capacity - 1) {
+ double y = lerp(data[idx], data[idx + 1], idx_f - idx);
+ if (velocity) y /= x;
+ return y;
+ }
+ }
+
+ double y = data[0];
+ if (velocity) y /= x_start;
+ return y;
+ }
+
+ void init(const fp_rep_range& r, bool vel)
+ {
+ velocity = vel;
+ range = r;
+ x_start = scalbn(1, range.start);
+ }
+
+ template <typename Func>
+ static void fill(Func fn, const accel_args& args, const fp_rep_range& range)
+ {
+ range.for_each([&, fn, i = 0](double x) mutable {
+ args.data[i++] = static_cast<float>(fn(x));
+ });
}
};
diff --git a/common/accel-natural.hpp b/common/accel-natural.hpp
index 9f76d1a..9d615a9 100644
--- a/common/accel-natural.hpp
+++ b/common/accel-natural.hpp
@@ -2,8 +2,6 @@
#include "rawaccel-base.hpp"
-#include <math.h>
-
namespace rawaccel {
/// <summary> Struct to hold "natural" (vanishing difference) acceleration implementation. </summary>
@@ -13,16 +11,20 @@ namespace rawaccel {
double limit;
natural_base(const accel_args& args) :
- offset(args.offset),
+ offset(args.input_offset),
limit(args.limit - 1)
{
accel = args.decay_rate / fabs(limit);
}
+
};
- struct natural_legacy : natural_base {
+ template<bool Gain> struct natural;
+
+ template<>
+ struct natural<LEGACY> : natural_base {
- double operator()(double x) const
+ double operator()(double x, const accel_args&) const
{
if (x <= offset) return 1;
@@ -34,10 +36,11 @@ namespace rawaccel {
using natural_base::natural_base;
};
- struct natural : natural_base {
+ template<>
+ struct natural<GAIN> : natural_base {
double constant;
- double operator()(double x) const
+ double operator()(double x, const accel_args&) const
{
if (x <= offset) return 1;
@@ -50,6 +53,6 @@ namespace rawaccel {
natural(const accel_args& args) :
natural_base(args),
constant(-limit / accel) {}
- };
+ };
}
diff --git a/common/accel-noaccel.hpp b/common/accel-noaccel.hpp
index 8d1e758..b307d99 100644
--- a/common/accel-noaccel.hpp
+++ b/common/accel-noaccel.hpp
@@ -10,7 +10,7 @@ namespace rawaccel {
accel_noaccel(const accel_args&) {}
accel_noaccel() = default;
- double operator()(double) const { return 1; }
+ double operator()(double, const accel_args&) const { return 1; }
};
}
diff --git a/common/accel-power.hpp b/common/accel-power.hpp
index c8faabb..8e3f417 100644
--- a/common/accel-power.hpp
+++ b/common/accel-power.hpp
@@ -2,25 +2,162 @@
#include "rawaccel-base.hpp"
-#include <math.h>
+#include <float.h>
namespace rawaccel {
- /// <summary> Struct to hold power (non-additive) acceleration implementation. </summary>
- struct power {
- double pre_scale;
- double exponent;
- double post_scale;
+ struct power_base {
+ vec2d offset;
+ double scale;
+ double constant;
+
+ power_base(const accel_args& args)
+ {
+ auto n = args.exponent_power;
+
+ if (args.cap_mode != cap_mode::io) {
+ scale = args.scale;
+ }
+ else if (args.gain) {
+ scale = scale_from_gain_point(args.cap.x, args.cap.y, n);
+ }
+ else {
+ /*
+ * special case for legacy + io cap mode
+ *
+ * offset is ignored because of the circular dependency:
+ * scale -> constant -> offset
+ */
+ offset = {};
+ constant = 0;
+ scale = scale_from_sens_point(args.cap.x, args.cap.y, n, constant);
+ return;
+ }
+
+ offset.x = gain_inverse(args.output_offset, n, scale);
+ offset.y = args.output_offset;
+ constant = offset.x * offset.y * n / (n + 1);
+ }
+
+ double base_fn(double x, const accel_args& args) const
+ {
+ if (x <= offset.x) {
+ return offset.y;
+ }
+ else {
+ return pow(scale * x, args.exponent_power) + constant / x;
+ }
+ }
+
+ static double gain(double input, double power, double scale)
+ {
+ return (power + 1) * pow(input * scale, power);
+ }
+
+ static double gain_inverse(double gain, double power, double scale)
+ {
+ return pow(gain / (power + 1), 1 / power) / scale;
+ }
+
+ static double scale_from_gain_point(double input, double gain, double power)
+ {
+ return pow(gain / (power + 1), 1 / power) / input;
+ }
+
+ static double scale_from_sens_point(double input, double sens, double power, double C)
+ {
+ return pow(sens - C / input, 1 / power) / input;
+ }
+ };
+
+ template <bool Gain> struct power;
+
+ template <>
+ struct power<LEGACY> : power_base {
+ double cap = DBL_MAX;
+
+ power(const accel_args& args) :
+ power_base(args)
+ {
+
+ switch (args.cap_mode){
+ case cap_mode::io:
+ cap = args.cap.y;
+ break;
+ case cap_mode::in:
+ if (args.cap.x > 0) cap = base_fn(args.cap.x, args);
+ break;
+ case cap_mode::out:
+ default:
+ if (args.cap.y > 0) cap = args.cap.y;
+ break;
+ }
+ }
+
+ double operator()(double speed, const accel_args& args) const
+ {
+ return minsd(base_fn(speed, args), cap);
+ }
+
+ };
+
+ template <>
+ struct power<GAIN> : power_base {
+ vec2d cap = { DBL_MAX, DBL_MAX };
+ double constant_b;
power(const accel_args& args) :
- pre_scale(args.scale),
- exponent(args.exponent),
- post_scale(args.weight) {}
+ power_base(args)
+ {
+ switch (args.cap_mode) {
+ case cap_mode::io:
+ cap = args.cap;
+ break;
+ case cap_mode::in:
+ if (args.cap.x > 0) {
+
+ if (args.cap.x <= offset.x) {
+ cap.x = 0;
+ cap.y = offset.y;
+ constant_b = 0;
+ return;
+ }
+
+ cap.x = args.cap.x;
+ cap.y = gain(
+ args.cap.x,
+ args.exponent_power,
+ scale);
+ }
+ break;
+ case cap_mode::out:
+ default:
+ if (args.cap.y > 0) {
+ cap.x = gain_inverse(
+ args.cap.y,
+ args.exponent_power,
+ scale);
+ cap.y = args.cap.y;
+ }
+ break;
+ }
+
+ constant_b = integration_constant(cap.x, cap.y, base_fn(cap.x, args));
+ }
+
+ double operator()(double speed, const accel_args& args) const
+ {
+ if (speed < cap.x) {
+ return base_fn(speed, args);
+ }
+ else {
+ return cap.y + constant_b / speed;
+ }
+ }
- double operator()(double speed) const
+ static double integration_constant(double input, double gain, double output)
{
- // f(x) = (mx)^k
- return post_scale * pow(speed * pre_scale, exponent);
+ return (output - gain) * input;
}
};
diff --git a/common/accel-union.hpp b/common/accel-union.hpp
index 8495a62..136db44 100644
--- a/common/accel-union.hpp
+++ b/common/accel-union.hpp
@@ -2,101 +2,56 @@
#include "accel-classic.hpp"
#include "accel-jump.hpp"
-#include "accel-natural.hpp"
-#include "accel-power.hpp"
+#include "accel-lookup.hpp"
#include "accel-motivity.hpp"
+#include "accel-natural.hpp"
#include "accel-noaccel.hpp"
+#include "accel-power.hpp"
namespace rawaccel {
- enum class internal_mode {
- classic_lgcy,
- classic_gain,
- jump_lgcy,
- jump_gain,
- natural_lgcy,
- natural_gain,
- motivity_lgcy,
- motivity_gain,
- power,
- lut_arb,
- lut_log,
- lut_lin,
- noaccel
- };
-
- constexpr internal_mode make_mode(accel_mode mode, spaced_lut_mode lut_mode, bool legacy)
- {
- if (lut_mode != spaced_lut_mode::off) {
- switch (lut_mode) {
- case spaced_lut_mode::binlog: return internal_mode::lut_log;
- case spaced_lut_mode::linear: return internal_mode::lut_lin;
- default: return internal_mode::noaccel;
- }
- }
- else if (mode == accel_mode::power) {
- return internal_mode::power;
- }
- else if (mode == accel_mode::arb_lookup) {
- return internal_mode::lut_arb;
- }
- else if (mode >= accel_mode::noaccel) {
- return internal_mode::noaccel;
- }
- else {
- int im = static_cast<int>(mode) * 2 + (legacy ? 0 : 1);
- return static_cast<internal_mode>(im);
+ union accel_union {
+ accel_noaccel noaccel;
+ lookup lut;
+ classic<GAIN> classic_g;
+ classic<LEGACY> classic_l;
+ jump<GAIN> jump_g;
+ jump<LEGACY> jump_l;
+ natural<GAIN> natural_g;
+ natural<LEGACY> natural_l;
+ power<GAIN> power_g;
+ power<LEGACY> power_l;
+ loglog_sigmoid<GAIN> loglog_sigmoid_g;
+ loglog_sigmoid<LEGACY> loglog_sigmoid_l;
+
+ template <template <bool> class AccelTemplate, typename Visitor>
+ auto visit_helper(Visitor vis, bool gain)
+ {
+ if (gain) return vis(reinterpret_cast<AccelTemplate<GAIN>&>(*this));
+ else return vis(reinterpret_cast<AccelTemplate<LEGACY>&>(*this));
}
- }
-
- constexpr internal_mode make_mode(const accel_args& args)
- {
- return make_mode(args.mode, args.spaced_args.mode, args.legacy);
- }
- template <typename Visitor, typename AccelUnion>
- constexpr auto visit_accel(Visitor vis, internal_mode mode, AccelUnion&& u)
- {
- switch (mode) {
- case internal_mode::classic_lgcy: return vis(u.classic_l);
- case internal_mode::classic_gain: return vis(u.classic_g);
- case internal_mode::jump_lgcy: return vis(u.jump_l);
- case internal_mode::jump_gain: return vis(u.jump_g);
- case internal_mode::natural_lgcy: return vis(u.natural_l);
- case internal_mode::natural_gain: return vis(u.natural_g);
- case internal_mode::motivity_lgcy: return vis(u.motivity_l);
- case internal_mode::motivity_gain: return vis(u.motivity_g);
- case internal_mode::power: return vis(u.power);
- case internal_mode::lut_arb: return vis(u.arb_lut);
- case internal_mode::lut_log: return vis(u.log_lut);
- case internal_mode::lut_lin: return vis(u.lin_lut);
- default: return vis(u.noaccel);
+ template <typename Visitor>
+ auto visit(Visitor vis, const accel_args& args)
+ {
+ switch (args.mode) {
+ case accel_mode::classic: return visit_helper<classic>(vis, args.gain);
+ case accel_mode::jump: return visit_helper<jump>(vis, args.gain);
+ case accel_mode::natural: return visit_helper<natural>(vis, args.gain);
+ case accel_mode::motivity: return visit_helper<loglog_sigmoid>(vis, args.gain);
+ case accel_mode::power: return visit_helper<power>(vis, args.gain);
+ case accel_mode::lookup: return vis(lut);
+ default: return vis(noaccel);
+ }
}
- }
-
- union accel_union {
- classic classic_g;
- classic_legacy classic_l;
- jump jump_g;
- jump_legacy jump_l;
- natural natural_g;
- natural_legacy natural_l;
- power power;
- sigmoid motivity_l;
- motivity motivity_g;
- linear_lut lin_lut;
- binlog_lut log_lut;
- arbitrary_lut arb_lut;
- accel_noaccel noaccel = {};
- accel_union(const accel_args& args)
+ void init(const accel_args& args)
{
- visit_accel([&](auto& impl) {
+ visit([&](auto& impl) {
impl = { args };
- }, make_mode(args), *this);
+ }, args);
}
- accel_union() = default;
};
}
diff --git a/common/common.vcxitems b/common/common.vcxitems
index 296fbfd..b49acd2 100644
--- a/common/common.vcxitems
+++ b/common/common.vcxitems
@@ -15,7 +15,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)accel-classic.hpp" />
- <ClInclude Include="$(MSBuildThisFileDirectory)accel-invoke.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)accel-jump.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)accel-lookup.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)accel-motivity.hpp" />
@@ -31,7 +30,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-version.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
- <ClInclude Include="$(MSBuildThisFileDirectory)vec2.h" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)math-vec2.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)utility.hpp" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/common/math-vec2.hpp b/common/math-vec2.hpp
new file mode 100644
index 0000000..f84c4c0
--- /dev/null
+++ b/common/math-vec2.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+template <typename T>
+struct vec2 {
+ T x;
+ T y;
+};
+
+using vec2d = vec2<double>;
+
+inline vec2d direction(double degrees)
+{
+ double radians = degrees * M_PI / 180;
+ return { cos(radians), sin(radians) };
+}
+
+constexpr vec2d rotate(const vec2d& v, const vec2d& direction)
+{
+ return {
+ v.x * direction.x - v.y * direction.y,
+ v.x * direction.y + v.y * direction.x
+ };
+}
+
+inline double magnitude(const vec2d& v)
+{
+ return sqrt(v.x * v.x + v.y * v.y);
+}
+
+
+inline double lp_distance(const vec2d& v, double p)
+{
+ return pow(pow(v.x, p) + pow(v.y, p), 1 / p);
+}
diff --git a/common/rawaccel-base.hpp b/common/rawaccel-base.hpp
index c1b2db3..91f58dc 100644
--- a/common/rawaccel-base.hpp
+++ b/common/rawaccel-base.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include "vec2.h"
+#include "math-vec2.hpp"
namespace rawaccel {
using milliseconds = double;
@@ -14,96 +14,78 @@ namespace rawaccel {
inline constexpr milliseconds WRITE_DELAY = 1000;
inline constexpr size_t MAX_DEV_ID_LEN = 200;
+ inline constexpr size_t MAX_NAME_LEN = 256;
- inline constexpr size_t SPACED_LUT_CAPACITY = 1025;
- inline constexpr size_t ARB_LUT_CAPACITY = SPACED_LUT_CAPACITY / 4;
+ inline constexpr size_t LUT_RAW_DATA_CAPACITY = 514;
+ inline constexpr size_t LUT_POINTS_CAPACITY = LUT_RAW_DATA_CAPACITY / 2;
inline constexpr double MAX_NORM = 16;
- inline constexpr double PI = 3.14159265358979323846;
+ inline constexpr bool LEGACY = 0;
+ inline constexpr bool GAIN = 1;
+
enum class accel_mode {
classic,
jump,
natural,
motivity,
power,
- arb_lookup,
+ lookup,
noaccel
};
- enum class spaced_lut_mode {
- off,
- binlog,
- linear
- };
-
- struct spaced_lut_args {
- spaced_lut_mode mode = spaced_lut_mode::off;
- bool transfer = true;
- unsigned char partitions = 2;
- short num_elements = 8;
- double start = 0;
- double stop = 8;
- };
-
- struct table_args {
- bool velocity = true;
- int length = 0;
- vec2<float> data[ARB_LUT_CAPACITY] = {};
+ enum class cap_mode {
+ io, in, out
};
struct accel_args {
accel_mode mode = accel_mode::noaccel;
- bool legacy = false;
+ bool gain = 1;
- double offset = 0;
- double cap = 1.5;
- double accel_classic = 0.005;
+ double input_offset = 0;
+ double output_offset = 0;
+ double acceleration = 0.005;
double decay_rate = 0.1;
double growth_rate = 1;
double motivity = 1.5;
- double power = 2;
+ double exponent_classic = 2;
double scale = 1;
- double weight = 1;
- double exponent = 0.05;
+ double exponent_power = 0.05;
double limit = 1.5;
double midpoint = 5;
double smooth = 0.5;
- spaced_lut_args spaced_args;
- table_args arb_args;
+ vec2d cap = { 15, 1.5 };
+ cap_mode cap_mode = cap_mode::out;
+
+ int length = 0;
+ mutable float data[LUT_RAW_DATA_CAPACITY] = {};
};
- struct domain_args {
- vec2d domain_weights = { 1, 1 };
+
+ struct profile {
+ wchar_t name[MAX_NAME_LEN] = L"default";
+
+ bool whole = true;
double lp_norm = 2;
- };
+ vec2d domain_weights = { 1, 1 };
+ vec2d range_weights = { 1, 1 };
+
+ accel_args accel_x;
+ accel_args accel_y;
+
+ double sensitivity = 1;
+ double yx_sens_ratio = 1;
+ double lr_sens_ratio = 1;
+ double ud_sens_ratio = 1;
- struct settings {
double degrees_rotation = 0;
+
double degrees_snap = 0;
- bool combine_mags = true;
- double dpi = 1000;
+
double speed_min = 0;
double speed_max = 0;
-
- vec2<accel_args> argsv;
- vec2d sens = { 1, 1 };
- vec2d dir_multipliers = { 1, 1 };
- domain_args dom_args = {};
- vec2d range_weights = { 1, 1 };
-
- milliseconds time_min = DEFAULT_TIME_MIN;
- milliseconds time_max = DEFAULT_TIME_MAX;
-
- bool ignore = false;
- wchar_t device_id[MAX_DEV_ID_LEN] = {};
};
- template <typename AccelFunc>
- inline double apply_weighted(AccelFunc&& f, double x, double w)
- {
- return 1 + (f(x) - 1) * w;
- }
}
diff --git a/common/rawaccel-io-def.h b/common/rawaccel-io-def.h
index 399e0f2..2f67b8f 100644
--- a/common/rawaccel-io-def.h
+++ b/common/rawaccel-io-def.h
@@ -8,8 +8,8 @@
#include <Windows.h>
#endif
-#define RA_DEV_TYPE 0x8888u
-
-#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define RA_WRITE CTL_CODE(RA_DEV_TYPE, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_BUFFERED, FILE_ANY_ACCESS)
+namespace rawaccel {
+ constexpr ULONG READ = (ULONG)CTL_CODE(0x8888u, 0x888, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ constexpr ULONG WRITE = (ULONG)CTL_CODE(0x8888u, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS);
+ constexpr ULONG GET_VERSION = (ULONG)CTL_CODE(0x8888u, 0x88a, METHOD_BUFFERED, FILE_ANY_ACCESS);
+} \ No newline at end of file
diff --git a/common/rawaccel-io.hpp b/common/rawaccel-io.hpp
index a80e254..046ac3d 100644
--- a/common/rawaccel-io.hpp
+++ b/common/rawaccel-io.hpp
@@ -5,8 +5,7 @@
#include "rawaccel-error.hpp"
#include "rawaccel.hpp"
-#pragma warning(push)
-#pragma warning(disable:4245) // int -> DWORD conversion while passing CTL_CODE
+#include <memory>
namespace rawaccel {
@@ -40,14 +39,54 @@ namespace rawaccel {
}
}
- inline void read(io_t& args)
+ inline std::unique_ptr<std::byte[]> read()
{
- io_control(RA_READ, NULL, 0, &args, sizeof(io_t));
+ io_base base_data;
+
+ io_control(READ, NULL, 0, &base_data, sizeof(io_base));
+
+ size_t size = sizeof(base_data);
+
+ if (base_data.modifier_data_size == 0) {
+ // driver has no data, but it's more useful to return something,
+ // so return a default modifier_settings object along with base data
+
+ size += sizeof(modifier_settings);
+ base_data.modifier_data_size = 1;
+ auto bytes = std::make_unique<std::byte[]>(size);
+ *reinterpret_cast<io_base*>(bytes.get()) = base_data;
+ *reinterpret_cast<modifier_settings*>(bytes.get() + sizeof(io_base)) = {};
+ return bytes;
+ }
+ else {
+ size += sizeof(modifier_settings) * base_data.modifier_data_size;
+ size += sizeof(device_settings) * base_data.device_data_size;
+ auto bytes = std::make_unique<std::byte[]>(size);
+ io_control(READ, NULL, 0, bytes.get(), DWORD(size));
+ return bytes;
+ }
}
- inline void write(const io_t& args)
+ // buffer must point to at least sizeof(io_base) bytes
+ inline void write(const void* buffer)
{
- io_control(RA_WRITE, const_cast<io_t*>(&args), sizeof(io_t), NULL, 0);
+ if (buffer == nullptr) throw io_error("write buffer is null");
+
+ auto* base_ptr = static_cast<const io_base*>(buffer);
+ auto size = sizeof(io_base);
+ size += base_ptr->modifier_data_size * sizeof(modifier_settings);
+ size += base_ptr->device_data_size * sizeof(device_settings);
+
+ if (size > DWORD(-1)) throw io_error("write buffer is too large");
+
+ io_control(WRITE, const_cast<void*>(buffer), DWORD(size), NULL, 0);
+ }
+
+ inline void reset()
+ {
+ io_base base_data{};
+ // all modifier/device data is cleared when a default io_base is passed
+ io_control(WRITE, &base_data, sizeof(io_base), NULL, 0);
}
inline version_t get_version()
@@ -55,7 +94,7 @@ namespace rawaccel {
version_t v;
try {
- io_control(RA_GET_VERSION, NULL, 0, &v, sizeof(version_t));
+ io_control(GET_VERSION, NULL, 0, &v, sizeof(version_t));
}
catch (const sys_error&) {
// assume request is not implemented (< 1.3)
@@ -81,5 +120,3 @@ namespace rawaccel {
}
}
-
-#pragma warning(pop)
diff --git a/common/rawaccel-validate.hpp b/common/rawaccel-validate.hpp
index a03f56a..b84fdb7 100644
--- a/common/rawaccel-validate.hpp
+++ b/common/rawaccel-validate.hpp
@@ -5,7 +5,7 @@
namespace rawaccel {
- struct valid_ret_t {
+ struct valid_profile_ret_t {
int last_x = 0;
int last_y = 0;
int count = 0;
@@ -16,10 +16,19 @@ namespace rawaccel {
}
};
+ struct valid_device_ret_t {
+ int count = 0;
+
+ explicit operator bool() const
+ {
+ return count == 0;
+ }
+ };
+
template <typename MsgHandler = noop>
- valid_ret_t valid(const settings& args, MsgHandler fn = {})
+ valid_profile_ret_t valid(const profile& args, MsgHandler fn = {})
{
- valid_ret_t ret;
+ valid_profile_ret_t ret;
auto error = [&](auto msg) {
++ret.count;
@@ -27,95 +36,83 @@ namespace rawaccel {
};
auto check_accel = [&error](const accel_args& args) {
- static_assert(SPACED_LUT_CAPACITY == 1025, "update error msg");
+ static_assert(LUT_POINTS_CAPACITY == 257, "update error msg");
- const auto& lut_args = args.spaced_args;
-
- if (lut_args.partitions <= 0) {
- error("lut partitions"" must be positive");
- }
-
- if (lut_args.mode == spaced_lut_mode::linear) {
- if (lut_args.start <= 0) {
- error("start"" must be positive");
- }
-
- if (lut_args.stop <= lut_args.start) {
- error("stop must be greater than start");
+ if (args.mode == accel_mode::lookup) {
+ if (args.length < 4) {
+ error("lookup mode requires at least 2 points");
}
-
- if (lut_args.num_elements < 2 ||
- lut_args.num_elements > 1025) {
- error("num must be between 2 and 1025");
+ else if (args.length > ra::LUT_RAW_DATA_CAPACITY) {
+ error("too many data points (max=257)");
}
}
- else if (lut_args.mode == spaced_lut_mode::binlog) {
- int istart = static_cast<int>(lut_args.start);
- int istop = static_cast<int>(lut_args.stop);
-
- if (lut_args.start < -99) {
- error("start is too small");
- }
- else if (lut_args.stop > 99) {
- error("stop is too large");
- }
- else if (istart != lut_args.start || istop != lut_args.stop) {
- error("start and stop must be integers");
- }
- else if (istop <= istart) {
- error("stop must be greater than start");
- }
- else if (lut_args.num_elements <= 0) {
- error("num"" must be positive");
- }
- else if (((lut_args.stop - lut_args.start) * lut_args.num_elements) >= 1025) {
- error("binlog mode requires (num * (stop - start)) < 1025");
- }
+ else if (args.length > ra::LUT_RAW_DATA_CAPACITY) {
+ error("data size > max");
}
- if (args.mode == accel_mode::arb_lookup) {
- if (args.arb_args.length < 2) {
- error("lookup mode requires at least 2 points");
- }
+ if (args.input_offset < 0) {
+ error("offset can not be negative");
}
- if (args.offset < 0) {
+ if (args.output_offset < 0) {
error("offset can not be negative");
}
- else if (args.mode == accel_mode::jump && args.offset == 0) {
- error("offset can not be 0");
- }
- if (args.cap < 0) {
- error("cap"" must not be negative");
+ bool jump_or_io_cap =
+ (args.mode == accel_mode::jump ||
+ ((args.mode == accel_mode::classic || args.mode == accel_mode::power) &&
+ args.cap_mode == cap_mode::io));
+
+ if (args.cap.x < 0) {
+ error("cap (input) can not be negative");
}
- else if (args.mode == accel_mode::jump && args.cap == 0) {
- error("cap can not be 0");
+ else if (args.cap.x == 0 && jump_or_io_cap) {
+ error("cap (input) can not be 0");
}
- if (args.growth_rate <= 0 ||
- args.decay_rate <= 0 ||
- args.accel_classic <= 0) {
- error("acceleration"" must be positive");
+ if (args.cap.y < 0) {
+ error("cap (output) can not be negative");
+ }
+ else if (args.cap.y == 0 && jump_or_io_cap) {
+ error("cap (output) can not be 0");
}
- if (args.motivity <= 1) {
- error("motivity must be greater than 1");
+ if ((args.mode == accel_mode::classic &&
+ args.cap.x > 0 &&
+ args.cap.x < args.input_offset &&
+ args.cap_mode != cap_mode::out) ||
+ (args.mode == accel_mode::power &&
+ args.cap.y > 0 &&
+ args.cap.y < args.output_offset &&
+ args.cap_mode != cap_mode::in)) {
+ error("cap < offset");
}
- if (args.power <= 1) {
- error("power must be greater than 1");
+ if (args.acceleration <= 0) {
+ error("acceleration"" must be positive");
}
if (args.scale <= 0) {
error("scale"" must be positive");
}
- if (args.weight <= 0) {
- error("weight"" must be positive");
+ if (args.growth_rate <= 0) {
+ error("growth rate"" must be positive");
+ }
+
+ if (args.decay_rate <= 0) {
+ error("decay rate"" must be positive");
}
- if (args.exponent <= 0) {
+ if (args.motivity <= 1) {
+ error("motivity must be greater than 1");
+ }
+
+ if (args.exponent_classic <= 1) {
+ error("exponent must be greater than 1");
+ }
+
+ if (args.exponent_power <= 0) {
error("exponent"" must be positive");
}
@@ -133,16 +130,16 @@ namespace rawaccel {
};
- check_accel(args.argsv.x);
+ check_accel(args.accel_x);
- if (!args.combine_mags) {
+ if (!args.whole) {
ret.last_x = ret.count;
- check_accel(args.argsv.y);
+ check_accel(args.accel_y);
ret.last_y = ret.count;
}
- if (args.dpi <= 0) {
- error("dpi"" must be positive");
+ if (args.name[0] == L'\0') {
+ error("profile name can not be empty");
}
if (args.speed_max < 0) {
@@ -156,36 +153,61 @@ namespace rawaccel {
error("snap angle must be between 0 and 45 degrees");
}
- if (args.sens.x == 0 || args.sens.y == 0) {
+ if (args.sensitivity == 0) {
error("sens multiplier is 0");
}
+
+ if (args.yx_sens_ratio == 0) {
+ error("Y/X sens ratio is 0");
+ }
- if (args.dom_args.domain_weights.x <= 0 ||
- args.dom_args.domain_weights.y <= 0) {
+ if (args.domain_weights.x <= 0 ||
+ args.domain_weights.y <= 0) {
error("domain weights"" must be positive");
}
- if (args.dir_multipliers.x <= 0 || args.dir_multipliers.y <= 0) {
- error("directional multipliers must be positive");
+ if (args.lr_sens_ratio <= 0 || args.ud_sens_ratio <= 0) {
+ error("sens ratio must be positive");
}
- if (args.dom_args.lp_norm < 2) {
- error("Lp norm is less than 2 (default=2)");
+ if (args.lp_norm <= 0) {
+ error("Lp norm must be positive (default=2)");
}
if (args.range_weights.x <= 0 || args.range_weights.y <= 0) {
error("range weights"" must be positive");
}
- if (args.time_min <= 0) {
+ return ret;
+ }
+
+ template <typename MsgHandler = noop>
+ valid_device_ret_t valid(const device_settings& args, MsgHandler fn = {})
+ {
+ valid_device_ret_t ret;
+
+ auto error = [&](auto msg) {
+ ++ret.count;
+ fn(msg);
+ };
+
+
+ if (args.config.dpi < 0) {
+ error("dpi"" can not be negative");
+ }
+
+ if (args.config.polling_rate < 0) {
+ error("polling rate"" can not be negative");
+ }
+
+ if (args.config.clamp.min <= 0) {
error("minimum time"" must be positive");
}
- if (args.time_max < args.time_min) {
+ if (args.config.clamp.max < args.config.clamp.min) {
error("max time is less than min time");
}
return ret;
}
-
}
diff --git a/common/rawaccel-version.h b/common/rawaccel-version.h
index 384ba6f..f3f684c 100644
--- a/common/rawaccel-version.h
+++ b/common/rawaccel-version.h
@@ -1,10 +1,10 @@
#pragma once
#define RA_VER_MAJOR 1
-#define RA_VER_MINOR 5
+#define RA_VER_MINOR 6
#define RA_VER_PATCH 0
-#define RA_OS "Win7+"
+#define RA_OS "Win10+"
#define RA_M_STR_HELPER(x) #x
#define RA_M_STR(x) RA_M_STR_HELPER(x)
@@ -30,7 +30,7 @@ namespace rawaccel {
inline constexpr version_t version = { RA_VER_MAJOR, RA_VER_MINOR, RA_VER_PATCH };
#ifndef _KERNEL_MODE
- inline constexpr version_t min_driver_version = { 1, 5, 0 };
+ inline constexpr version_t min_driver_version = { 1, 6, 0 };
#endif
}
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
diff --git a/common/utility-install.hpp b/common/utility-install.hpp
index e1823e4..55ae9d6 100644
--- a/common/utility-install.hpp
+++ b/common/utility-install.hpp
@@ -10,25 +10,24 @@ namespace wr = winreg;
inline const std::wstring DRIVER_NAME = L"rawaccel";
inline const std::wstring DRIVER_FILE_NAME = DRIVER_NAME + L".sys";
+inline const std::wstring DRIVER_ENV_PATH = L"%systemroot%\\system32\\drivers\\" + DRIVER_FILE_NAME;
-fs::path get_sys_path() {
- std::wstring path;
- path.resize(MAX_PATH);
+inline const auto sys_error = [](auto what, DWORD code = GetLastError()) {
+ return std::system_error(code, std::system_category(), what);
+};
- UINT chars_copied = GetSystemDirectoryW(path.data(), MAX_PATH);
- if (chars_copied == 0) throw std::runtime_error("GetSystemDirectory failed");
+inline std::wstring expand(const std::wstring& env_path) {
+ std::wstring path(MAX_PATH, L'\0');
- path.resize(chars_copied);
+ auto len = ExpandEnvironmentStringsW(env_path.c_str(), &path[0], MAX_PATH);
+ if (len == 0) throw sys_error("ExpandEnvironmentStrings failed");
+ path.resize(len - 1);
return path;
}
-fs::path get_target_path() {
- return get_sys_path() / L"drivers" / DRIVER_FILE_NAME;
-}
-
-fs::path make_temp_path(const fs::path& p) {
+inline fs::path make_temp_path(const fs::path& p) {
auto tmp_path = p;
- tmp_path.concat(".tmp");
+ tmp_path.concat(L".tmp");
return tmp_path;
}
diff --git a/common/utility.hpp b/common/utility.hpp
index cbd19e3..2587d91 100644
--- a/common/utility.hpp
+++ b/common/utility.hpp
@@ -35,15 +35,6 @@ namespace rawaccel {
return (v < lo) ? lo : (hi < v) ? hi : v;
}
- constexpr double lerp(double a, double b, double t)
- {
- double x = a + t * (b - a);
- if ((t > 1) == (a < b)) {
- return maxsd(x, b);
- }
- return minsd(x, b);
- }
-
// returns the unbiased exponent of x if x is normal
inline int ilogb(double x)
{
@@ -85,4 +76,10 @@ namespace rawaccel {
template <typename T, typename U>
inline constexpr bool is_same_v = is_same<T, U>::value;
+ template <class T> struct is_rvalue_ref { static constexpr bool value = false; };
+ template <class T> struct is_rvalue_ref<T&&> { static constexpr bool value = true; };
+
+ template <class T>
+ inline constexpr bool is_rvalue_ref_v = is_rvalue_ref<T>::value;
+
}
diff --git a/common/vec2.h b/common/vec2.h
deleted file mode 100644
index 6484e69..0000000
--- a/common/vec2.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-template <typename T>
-struct vec2 {
- T x;
- T y;
-};
-
-using vec2d = vec2<double>;
diff --git a/converter/converter.cpp b/converter/converter.cpp
index 61ed877..c40acc9 100644
--- a/converter/converter.cpp
+++ b/converter/converter.cpp
@@ -1,4 +1,4 @@
-#include <rawaccel-base.hpp>
+#include <rawaccel.hpp>
#include <array>
#include <charconv>
@@ -120,9 +120,9 @@ ra::accel_args convert_natural(const ia_settings_t& ia_settings, bool legacy) {
args.limit = 1 + std::abs(cap - sens) / sens;
args.decay_rate = accel / sens;
- args.offset = get("Offset").value_or(0);
+ args.input_offset = get("Offset").value_or(0);
args.mode = ra::accel_mode::natural;
- args.legacy = legacy;
+ args.gain = !legacy;
return args;
}
@@ -138,12 +138,13 @@ ra::accel_args convert_quake(const ia_settings_t& ia_settings, bool legacy) {
ra::accel_args args;
double accel_b = std::pow(accel, power - 1) / sens;
- args.accel_classic = std::pow(accel_b, 1 / (power - 1));
- args.cap = cap / sens;
- args.power = power;
- args.offset = get("Offset").value_or(0);
+ args.acceleration = std::pow(accel_b, 1 / (power - 1));
+ args.cap.y = cap / sens;
+ args.exponent_classic = power;
+ args.input_offset = get("Offset").value_or(0);
args.mode = ra::accel_mode::classic;
- args.legacy = legacy;
+ args.cap_mode = ra::cap_mode::out;
+ args.gain = !legacy;
return args;
}
@@ -151,27 +152,25 @@ ra::accel_args convert_quake(const ia_settings_t& ia_settings, bool legacy) {
bool try_convert(const ia_settings_t& ia_settings) {
auto get = make_extractor(ia_settings);
- ra::settings& ra_settings = *(new ra::settings());
+ auto& prof = *(new ra::profile());
vec2d prescale = { get("Pre-ScaleX").value_or(1), get("Pre-ScaleY").value_or(1) };
- ra_settings.dom_args.domain_weights = prescale;
- ra_settings.degrees_rotation = -1 * get("Angle", "AngleAdjustment").value_or(0);
- ra_settings.degrees_snap = get("AngleSnapping").value_or(0);
- ra_settings.sens = {
- get("Post-ScaleX").value_or(1) * prescale.x,
- get("Post-ScaleY").value_or(1) * prescale.y
- };
+ prof.domain_weights = prescale;
+ prof.degrees_rotation = -1 * get("Angle", "AngleAdjustment").value_or(0);
+ prof.sensitivity = get("Post-ScaleX").value_or(1) * prescale.x;
+ prof.yx_sens_ratio = get("Post-ScaleY").value_or(1) * prescale.y / prof.sensitivity;
+ prof.degrees_snap = get("AngleSnapping").value_or(0);
double mode = get("AccelMode").value_or(IA_QL);
switch (static_cast<IA_MODES_ENUM>(mode)) {
case IA_QL: {
- ra_settings.argsv.x = convert_quake(ia_settings, 1);
+ prof.accel_x = convert_quake(ia_settings, 1);
break;
}
case IA_NAT: {
- ra_settings.argsv.x = convert_natural(ia_settings, 1);
+ prof.accel_x = convert_natural(ia_settings, 1);
break;
}
case IA_LOG: {
@@ -181,16 +180,15 @@ bool try_convert(const ia_settings_t& ia_settings) {
default: return false;
}
- DriverSettings^ new_settings = Marshal::PtrToStructure<DriverSettings^>((IntPtr)&ra_settings);
- SettingsErrors^ errors = gcnew SettingsErrors(new_settings);
+ auto cfg = DriverConfig::FromProfile(Marshal::PtrToStructure<Profile^>(IntPtr(&prof)));
- if (!errors->Empty()) {
+ if (String^ errors = cfg->Errors(); errors) {
Console::WriteLine("Bad settings: {0}", errors);
return false;
}
- bool nat = ra_settings.argsv.x.mode == ra::accel_mode::natural;
- bool nat_or_capped = nat || ra_settings.argsv.x.cap > 0;
+ bool nat = prof.accel_x.mode == ra::accel_mode::natural;
+ bool nat_or_capped = nat || prof.accel_x.cap.y > 0;
if (nat_or_capped) {
Console::WriteLine("NOTE:\n"
@@ -198,7 +196,7 @@ bool try_convert(const ia_settings_t& ia_settings) {
" To test it out, run rawaccel.exe, check the 'Gain' option, and click 'Apply'.\n");
}
- if (ra_settings.argsv.x.offset > 0) {
+ if (prof.accel_x.input_offset > 0) {
Console::WriteLine("NOTE:\n"
" Offsets in Raw Accel work a bit differently compared to InterAccel,\n"
" the '{0}' parameter may need adjustment to compensate.\n",
@@ -206,11 +204,11 @@ bool try_convert(const ia_settings_t& ia_settings) {
}
Console::Write("Sending to driver... ");
- (gcnew ManagedAccel(gcnew ExtendedSettings(new_settings)))->Activate();
+ cfg->Activate();
Console::WriteLine("done");
Console::Write("Generating settings.json... ");
- File::WriteAllText("settings.json", RaConvert::Settings(new_settings));
+ File::WriteAllText("settings.json", cfg->ToJSON());
Console::WriteLine("done");
return true;
diff --git a/doc/Guide.md b/doc/Guide.md
index a0bc1ca..2569af8 100644
--- a/doc/Guide.md
+++ b/doc/Guide.md
@@ -5,9 +5,9 @@ Visit the [Releases page](https://github.com/a1xd/rawaccel/releases) and navigat
## Installation
- **Prerequisites**
+ * Windows 10
* Visual C++ 2019 runtime, [download here](https://aka.ms/vs/16/release/vc_redist.x64.exe)
* .NET Framework 4.7.2+ runtime, [download here](https://dotnet.microsoft.com/download/dotnet-framework/net48)
- * **For Windows 7 users only** — SHA-2 code signing support (download through Windows Update)
- Run `installer.exe` in the release directory to install the Raw Accel driver. Restart your computer for the installation to take effect.
@@ -58,6 +58,7 @@ There are anisotropic settings for whole mode.
- **Lp Norm**. The distance calculation can be generalized to ((in_x)^p + (in_y)^p)^(1/p)), bringing the calculation into [Lp space](https://en.wikipedia.org/wiki/Lp_space).
- p = 2 is then the "real world" value, yielding the pythagorean theorem as the distance calculation.
- Increasing p makes distances for diagonal movements (where in_x and in_y are close) smaller, and increases the dominance of the larger of the two in determining the distance.
+ - As p gets large, the above calculation approaches max(inx, iny). Raw Accel uses this formula when given any p > 64.
- We recommend almost everyone leave this at 2.
![AnisotropyExample](images/anisotropy_example.png)
@@ -68,7 +69,7 @@ With all anisotropic settings considered, the full formula looks like:
This can be more easily understood as
- (out_x, out_y) = (in_x\*sens_x, in_y\*sens_y) \* ((f( domain-weighted lp-space speed) - 1) \* (directional weight) + 1), where f(v) is our sensitivity function
-This formula gaurantees the smooth transition from the horizontal to vertical curve and vice versa as the user moves their hand diagonally.
+This formula guarantees the smooth transition from the horizontal to vertical curve and vice versa as the user moves their hand diagonally.
#### ***By Component***
In this case, the horizontal components are separated and each is given as input to the sensitivity calculation to multiplied by itself before being recombined at output.
@@ -82,26 +83,43 @@ The authors of this program feel that Whole is the best style for most users, bu
## Features
+### Sensitivity Multiplier
+As described above, the "sensitivity multiplier" parameter is a multiplier used on the post-calculation output vector. The "Y/X Ratio" parameter is then only applied to the Y component of the output, so that it defines the ratio of vertical to horizontal output sensitivity without acceleration.
+
### Gain Switch
The acceleration curve styles below (see "Acceleration Styles") each describe a certain shape mathematically. The gain switch determines whether that shape is applied in the sensitivity graph or the gain graph. For styles Linear, Classic, and Power, this setting does not change the possible shapes of the velocity curve - that is, for any particular settings with the gain switch set to Sensitivity, there is a different set of settings that will replicate the exact same velocity curve (output for a given hand motion) with the switch set to Gain. For styles Natural, Jump, and Motivity, this is not true, and the gain switch allows new velocity curves for each style.
### Offsets
An offset, sometimes called a threshold, is a speed in counts before acceleration "kicks in". The legacy way of applying an offset is having a multiplier of 1 below and at the offset, and applying the sensitivity of (speed-offset) above. This legacy "sensitivity offset" is not available because it causes a discontinuity in gain at the point of offset, leading to non-smooth feeling at offset cross. The new "gain offset" does a little extra math to simply shift the gain graph by the offset amount without any discontinuity. This feels smoother and has almost no effect on sensitivity. The theory behind "gain offsets" is developed in [this document](https://docs.google.com/document/d/1P6LygpeEazyHfjVmaEygCsyBjwwW2A-eMBl81ZfxXZk).
+Offsets are only applicable to the Classic, Linear, and Natural modes, where they are defined in terms of an input speed. Power mode has a special "output offset", where the curve "starts from" some ratio of the sens multiplier, described in its section.
+
### Caps
A cap is a point after which acceleration is not applied. The legacy way of applying an offset is simply applying the minimum of the cap sensitivity and the calculated sensitivity for any acceleration calculation. Thus, for the legacy "sensitivity cap" the value given is a sensitivity. This cap style is still available but causes a large discontinuity at the point of offset, leading to a non-smooth feeling at cap cross. The new default "gain cap" effectively caps the gain, but for internal calculation reasons, does so for a given speed rather than a given gain value. This feels much smoother but might have a large effect on sensitivity as gain generally raises faster than sensitivity. We recommend that users use a gain cap and simply adjust it to hit at the gain equivalent to the sensitivity they'd like to cap at. The theory behind "gain caps" is developed in [this document](https://docs.google.com/document/d/1FCpkqRxUaCP7J258SupbxNxvdPfljb16AKMs56yDucA).
+Caps are only applicable to the Classic, Linear, and Power modes. The capping point can be defined in terms of an input speed, an output ratio, or both (which will then set other acceleration parameters for the mode.)
+
### Anisotropy
See "Horizontal and Vertical" in the philosophy section to understand what these options do.
### Last Mouse Move
The Raw Accel GUI reads the output of the raw input stream, and thus the output of the Raw Accel Driver, and displays on the graphs red points corresponding to the last mouse movements. These calulations should be fast and your graph responsive, but it comes at the cost of higher CPU usage due to needing to refresh the graph often. This feature can be turned off in the "Charts" menu.
-### Scale by DPI and Poll Rate
-This option does not scale your acceleration curve in any way. Rather, DPI scales the set of points used to graph your curve, and shows you a window of input speed relevant for your chosen DPI. The poll rate is used as a safeguard for the Last Mouse Move points and therefore should be set for accuracy in that measurement.
+### Menu Options
+
+#### Charts >> Scale by DPI and Poll Rate
+These options does not scale your acceleration curve in any way. Rather, DPI scales the set of points used to graph your curve, and shows you a window of input speed relevant for your chosen DPI. The poll rate is used as a safeguard for the Last Mouse Move points and therefore should be set for accuracy in that measurement.
+
+#### Advanced >> Device Menu
+This menu provides options for individually disabling devices, and normalizing device DPI (see next section). Here you will also find an option for setting polling rate, which signals the driver to forgo the standard automatic rate adjustment. Leave this at 0 unless you are experiencing cursor stutters that only occur with acceleration enabled.
+
+#### DPI Normalization
+Setting the DPI option for a device to its actual DPI will scale its input so that the sensitivity and acceleration feels as if it were set to 1000 dpi. For example, with a sens multiplier of 0.8, mice with their DPI set in the device menu will have the equivalent sensitivity of an 800 DPI mouse with a sens multiplier of 1. Ignoring device-specific factors like weight, friction, and sensor position, normalization provides an easy method to synchronize settings across different setups.
+
+This is still an experimental setting, which perhaps will be more clearly presented in the future. For now, users should set their sensitivity multiplier to no greater than their DPI divided by 1000 to avoid pixel skipping on desktop (with 6/11 window sensitivity.)
## Acceleration Styles
-The examples of various types below show some typical settings, without a cap or offset, for a mouse at 1600 DPI and 1000 hz.
+The examples of various types below show some typical settings for a mouse at, or normalized to, 1000 DPI.
### Linear
This is simplest style used by most; it is simply a line rising at a given rate. This is a good choice for new users.
@@ -112,7 +130,9 @@ This is the style found in Quake 3, Quake Live, and countless inspired followers
![ClassicExample](images/classic_example.png)
### Power
-This is the style found in CS:GO and Source Engine games (m_customaccel 3). The user can set a rate by which the speed is multiplied, and then an exponent to which the product is raised, which is then the final multiplier (no adding to 1). In the aforementioned games the default m_customaccel_exponent value of 1.05 would be a value of 0.05 in Raw Accel, leading to a concave slowly rising curve. CS:GO and Source Engine games apply acceleration in an fps-dependent manner, so Raw Accel can only simulate acceleration from these games at a given fps. To do so, set scale to 1000/(in-game fps).
+This is the style found in CS:GO and Source Engine games (m_customaccel 3). The user can set a rate by which the speed is multiplied, and then an exponent to which the product is raised, which is then the final multiplier (no adding to 1). The formula for this curve starts at 0 for an input of 0, so the user can also set a ratio of the sens multiplier for the curve to start at, effectively an output offset.
+
+In the aforementioned games the default m_customaccel_exponent value of 1.05 would be a value of 0.05 in Raw Accel, leading to a concave slowly rising curve. CS:GO and Source Engine games apply acceleration in an fps-dependent manner, so Raw Accel can only simulate acceleration from these games at a given fps. To do so, set scale to 1000/(in-game fps) and the output offset to 1.
![PowerExample](images/power_example.png)
### Natural
@@ -120,7 +140,7 @@ Natural features a concave curve which starts at 1 and approaches some maximum s
![NaturalGainExample](images/natural_gain_example.png)
### Jump
- This style applies one sensitivity below a certain threshold, and another above it. It can be useful for those who want one constant sensitivity and gain for slow hand motions and a different constant sensitivity or gain for fast hand motions. Users can set a "smooth" parameter which dictates whether the jump happens instaneously (at smooth 0) or with a slight tailing in and out (smooth 1) leading to a small sigmoid shape (s-shape). (Note that this "smooth" parameter has nothing to do with averaging over mouse counts like in sensor smoothing on mice or mouse smoothing in games.)
+ This style applies one sensitivity or gain below a certain threshold, and another above it. It can be useful for those who want one constant sensitivity and gain for slow hand motions and a different constant sensitivity or gain for fast hand motions. Users can set a "smooth" parameter which dictates whether the jump happens instaneously (at smooth 0) or with a slight tailing in and out (smooth 1) leading to a small sigmoid shape (s-shape). (Note that this "smooth" parameter has nothing to do with averaging over mouse counts like in sensor smoothing on mice or mouse smoothing in games.)
![NaturalGainExample](images/jump_example.png)
### Motivity
diff --git a/doc/images/LUT_example.png b/doc/images/LUT_example.png
index 71f9ce3..96567d1 100644
--- a/doc/images/LUT_example.png
+++ b/doc/images/LUT_example.png
Binary files differ
diff --git a/doc/images/accel_readme_example.png b/doc/images/accel_readme_example.png
index 1622011..a23f9e4 100644
--- a/doc/images/accel_readme_example.png
+++ b/doc/images/accel_readme_example.png
Binary files differ
diff --git a/doc/images/anisotropy_example.png b/doc/images/anisotropy_example.png
index 6425e68..f8dd09c 100644
--- a/doc/images/anisotropy_example.png
+++ b/doc/images/anisotropy_example.png
Binary files differ
diff --git a/doc/images/classic_example.png b/doc/images/classic_example.png
index 58ca915..d51f693 100644
--- a/doc/images/classic_example.png
+++ b/doc/images/classic_example.png
Binary files differ
diff --git a/doc/images/jump_example.png b/doc/images/jump_example.png
index 770bab2..1d59134 100644
--- a/doc/images/jump_example.png
+++ b/doc/images/jump_example.png
Binary files differ
diff --git a/doc/images/linear_example.png b/doc/images/linear_example.png
index be1410e..29345d1 100644
--- a/doc/images/linear_example.png
+++ b/doc/images/linear_example.png
Binary files differ
diff --git a/doc/images/motivity_example.png b/doc/images/motivity_example.png
index 6041ec6..e9f719e 100644
--- a/doc/images/motivity_example.png
+++ b/doc/images/motivity_example.png
Binary files differ
diff --git a/doc/images/natural_gain_example.png b/doc/images/natural_gain_example.png
index 3b66dbe..49784e6 100644
--- a/doc/images/natural_gain_example.png
+++ b/doc/images/natural_gain_example.png
Binary files differ
diff --git a/doc/images/power_example.png b/doc/images/power_example.png
index 414a252..d41ad52 100644
--- a/doc/images/power_example.png
+++ b/doc/images/power_example.png
Binary files differ
diff --git a/driver/driver.cpp b/driver/driver.cpp
index feace77..febf64f 100644
--- a/driver/driver.cpp
+++ b/driver/driver.cpp
@@ -7,18 +7,26 @@
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
+#pragma alloc_text (INIT, RawaccelInit)
+#pragma alloc_text (INIT, CreateControlDevice)
#pragma alloc_text (PAGE, EvtDeviceAdd)
#pragma alloc_text (PAGE, EvtIoInternalDeviceControl)
#pragma alloc_text (PAGE, RawaccelControl)
+#pragma alloc_text (PAGE, DeviceCleanup)
+#pragma alloc_text (PAGE, DeviceSetup)
+#pragma alloc_text (PAGE, WriteDelay)
#endif
using milliseconds = double;
struct {
- ra::settings args;
+ bool initialized;
+ WDFCOLLECTION device_collection;
+ WDFWAITLOCK collection_lock;
+ ra::io_base base_data;
+ ra::modifier_settings* modifier_data;
+ ra::device_settings* device_data;
milliseconds tick_interval;
- vec2<ra::accel_invoker> invokers;
- ra::mouse_modifier modifier;
} global = {};
extern "C" PULONG InitSafeBootMode;
@@ -58,26 +66,39 @@ Arguments:
auto num_packets = InputDataEnd - InputDataStart;
if (num_packets > 0 &&
- !(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE) &&
- (global.args.device_id[0] == 0 ||
- bool(wcsncmp(devExt->dev_id, global.args.device_id, ra::MAX_DEV_ID_LEN)) ==
- global.args.ignore)) {
- counter_t now = KeQueryPerformanceCounter(NULL).QuadPart;
- counter_t ticks = now - devExt->counter;
- devExt->counter = now;
- milliseconds raw_elapsed = ticks * global.tick_interval;
- milliseconds time = ra::clampsd(raw_elapsed / num_packets,
- global.args.time_min,
- global.args.time_max);
+ !(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE) &&
+ devExt->enable) {
+
+ milliseconds time;
+ if (devExt->keep_time) {
+ counter_t now = KeQueryPerformanceCounter(NULL).QuadPart;
+ counter_t ticks = now - devExt->counter;
+ devExt->counter = now;
+ milliseconds raw = ticks * global.tick_interval / num_packets;
+ time = ra::clampsd(raw, devExt->clamp.min, devExt->clamp.max);
+ }
+ else {
+ time = devExt->clamp.min;
+ }
+
auto it = InputDataStart;
do {
+ if (devExt->set_extra_info) {
+ union {
+ short input[2];
+ ULONG data;
+ } u = { short(it->LastX), short(it->LastY) };
+
+ it->ExtraInformation = u.data;
+ }
+
if (it->LastX || it->LastY) {
vec2d input = {
static_cast<double>(it->LastX),
static_cast<double>(it->LastY)
};
- global.modifier.modify(input, global.invokers, time);
+ devExt->mod.modify(input, devExt->mod_settings, devExt->dpi_factor, time);
double carried_result_x = input.x + devExt->carry.x;
double carried_result_y = input.y + devExt->carry.y;
@@ -89,8 +110,8 @@ Arguments:
double carry_y = carried_result_y - out_y;
if (!ra::infnan(carry_x + carry_y)) {
- devExt->carry.x = carried_result_x - out_x;
- devExt->carry.y = carried_result_y - out_y;
+ devExt->carry.x = carry_x;
+ devExt->carry.y = carry_y;
it->LastX = out_x;
it->LastY = out_y;
}
@@ -139,7 +160,7 @@ Return Value:
{
NTSTATUS status;
void* buffer;
-
+ size_t buffer_length;
size_t bytes_out = 0;
UNREFERENCED_PARAMETER(Queue);
@@ -149,49 +170,126 @@ Return Value:
DebugPrint(("Ioctl received into filter control object.\n"));
+ if (!global.initialized) {
+ WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0);
+ return;
+ }
+
+ const auto SIZEOF_BASE = sizeof(ra::io_base);
+
switch (IoControlCode) {
- case RA_READ:
+ case ra::READ:
status = WdfRequestRetrieveOutputBuffer(
Request,
- sizeof(ra::io_t),
+ SIZEOF_BASE,
&buffer,
- NULL
+ &buffer_length
);
if (!NT_SUCCESS(status)) {
DebugPrint(("RetrieveOutputBuffer failed: 0x%x\n", status));
}
else {
- ra::io_t& output = *reinterpret_cast<ra::io_t*>(buffer);
+ *static_cast<ra::io_base*>(buffer) = global.base_data;
+
+ size_t modifier_bytes = global.base_data.modifier_data_size * sizeof(ra::modifier_settings);
+ size_t device_bytes = global.base_data.device_data_size * sizeof(ra::device_settings);
+ size_t total_bytes = SIZEOF_BASE + modifier_bytes + device_bytes;
- output.args = global.args;
- output.mod = global.modifier;
+ if (buffer_length < total_bytes) {
+ bytes_out = SIZEOF_BASE;
+ }
+ else {
+ BYTE* output_ptr = static_cast<BYTE*>(buffer) + SIZEOF_BASE;
- bytes_out = sizeof(ra::io_t);
+ if (global.modifier_data) RtlCopyMemory(output_ptr, global.modifier_data, modifier_bytes);
+ output_ptr += modifier_bytes;
+ if (global.device_data) RtlCopyMemory(output_ptr, global.device_data, device_bytes);
+ bytes_out = total_bytes;
+ }
}
break;
- case RA_WRITE:
+ case ra::WRITE:
status = WdfRequestRetrieveInputBuffer(
Request,
- sizeof(ra::io_t),
+ SIZEOF_BASE,
&buffer,
- NULL
+ &buffer_length
);
if (!NT_SUCCESS(status)) {
DebugPrint(("RetrieveInputBuffer failed: 0x%x\n", status));
}
else {
- LARGE_INTEGER interval;
- interval.QuadPart = static_cast<LONGLONG>(ra::WRITE_DELAY) * -10000;
- KeDelayExecutionThread(KernelMode, FALSE, &interval);
+ WriteDelay();
+
+ ra::io_base& input = *static_cast<ra::io_base*>(buffer);
+
+ auto modifier_bytes = size_t(input.modifier_data_size) * sizeof(ra::modifier_settings);
+ auto device_bytes = size_t(input.device_data_size) * sizeof(ra::device_settings);
+ auto alloc_size = modifier_bytes + device_bytes;
+ auto total_size = alloc_size + SIZEOF_BASE;
+
+ auto max_u32 = unsigned(-1);
+ if (modifier_bytes > max_u32 || device_bytes > max_u32 || total_size > max_u32) {
+ status = STATUS_CANCELLED;
+ break;
+ }
+
+ if (input.modifier_data_size == 0) {
+ // clear data and disable all devices
+ WdfWaitLockAcquire(global.collection_lock, NULL);
+
+ global.base_data = {};
- ra::io_t& input = *reinterpret_cast<ra::io_t*>(buffer);
+ if (global.modifier_data) {
+ ExFreePoolWithTag(global.modifier_data, 'g');
+ global.modifier_data = NULL;
+ global.device_data = NULL;
+ }
+
+ auto count = WdfCollectionGetCount(global.device_collection);
+
+ for (auto i = 0u; i < count; i++) {
+ DeviceSetup(WdfCollectionGetItem(global.device_collection, i));
+ }
+
+ WdfWaitLockRelease(global.collection_lock);
+ }
+ else if (buffer_length == total_size) {
+ void* pool = ExAllocatePoolWithTag(PagedPool, alloc_size, 'g');
+ if (!pool) {
+ DebugPrint(("ExAllocatePoolWithTag (PagedPool) failed"));
+ status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ RtlCopyMemory(pool, static_cast<BYTE*>(buffer) + SIZEOF_BASE, alloc_size);
- global.args = input.args;
- global.invokers = ra::invokers(input.args);
- global.modifier = input.mod;
+ WdfWaitLockAcquire(global.collection_lock, NULL);
+
+ if (global.modifier_data) {
+ ExFreePoolWithTag(global.modifier_data, 'g');
+ }
+
+ void* dev_data = static_cast<BYTE*>(pool) + modifier_bytes;
+ global.device_data = input.device_data_size > 0 ?
+ static_cast<ra::device_settings*>(dev_data) :
+ NULL;
+ global.modifier_data = static_cast<ra::modifier_settings*>(pool);
+ global.base_data = input;
+
+ auto count = WdfCollectionGetCount(global.device_collection);
+
+ for (auto i = 0u; i < count; i++) {
+ DeviceSetup(WdfCollectionGetItem(global.device_collection, i));
+ }
+
+ WdfWaitLockRelease(global.collection_lock);
+ }
+ else {
+ status = STATUS_CANCELLED;
+ }
}
break;
- case RA_GET_VERSION:
+ case ra::GET_VERSION:
status = WdfRequestRetrieveOutputBuffer(
Request,
sizeof(ra::version_t),
@@ -202,7 +300,7 @@ Return Value:
DebugPrint(("RetrieveOutputBuffer failed: 0x%x\n", status));
}
else {
- *reinterpret_cast<ra::version_t*>(buffer) = ra::version;
+ *static_cast<ra::version_t*>(buffer) = ra::version;
bytes_out = sizeof(ra::version_t);
}
break;
@@ -216,6 +314,120 @@ Return Value:
}
#pragma warning(pop) // enable 28118 again
+VOID
+RawaccelInit(WDFDRIVER driver)
+{
+ NTSTATUS status;
+
+ status = CreateControlDevice(driver);
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint(("CreateControlDevice failed with status 0x%x\n", status));
+ return;
+ }
+
+ status = WdfCollectionCreate(
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &global.device_collection
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint(("WdfCollectionCreate failed with status 0x%x\n", status));
+ return;
+ }
+
+ status = WdfWaitLockCreate(
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &global.collection_lock
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint(("WdfWaitLockCreate failed with status 0x%x\n", status));
+ return;
+ }
+
+ LARGE_INTEGER freq;
+ KeQueryPerformanceCounter(&freq);
+ global.tick_interval = 1e3 / freq.QuadPart;
+
+ global.initialized = true;
+}
+
+VOID
+DeviceSetup(WDFOBJECT hDevice)
+{
+ auto* devExt = FilterGetData(hDevice);
+
+ auto set_ext_from_cfg = [devExt](const ra::device_config& cfg) {
+ devExt->enable = !cfg.disable;
+ devExt->set_extra_info = cfg.set_extra_info;
+ devExt->keep_time = cfg.polling_rate <= 0;
+ devExt->dpi_factor = (cfg.dpi > 0) ? (1000.0 / cfg.dpi) : 1;
+
+ if (devExt->keep_time) {
+ devExt->clamp = cfg.clamp;
+ }
+ else {
+ milliseconds interval = 1000.0 / cfg.polling_rate;
+ devExt->clamp = { interval, interval };
+ }
+ };
+
+ auto set_mod_if_found = [devExt](auto* prof_name) {
+ for (auto i = 0u; i < global.base_data.modifier_data_size; i++) {
+ auto& profile = global.modifier_data[i].prof;
+
+ if (wcsncmp(prof_name, profile.name, ra::MAX_NAME_LEN) == 0) {
+ devExt->mod_settings = global.modifier_data[i];
+ devExt->mod = { devExt->mod_settings };
+ return;
+ }
+ }
+ };
+
+ if (!global.modifier_data) {
+ devExt->enable = false;
+ devExt->mod = {};
+ return;
+ }
+
+ set_ext_from_cfg(global.base_data.default_dev_cfg);
+ devExt->mod_settings = *global.modifier_data;
+ devExt->mod = { devExt->mod_settings };
+
+ for (auto i = 0u; i < global.base_data.device_data_size; i++) {
+ auto& dev_settings = global.device_data[i];
+
+ if (wcsncmp(devExt->dev_id, dev_settings.id, ra::MAX_DEV_ID_LEN) == 0) {
+ set_ext_from_cfg(dev_settings.config);
+
+ if (dev_settings.profile[0] != L'\0') {
+ set_mod_if_found(dev_settings.profile);
+ }
+
+ break;
+ }
+ }
+}
+
+VOID
+DeviceCleanup(WDFOBJECT hDevice)
+{
+ PAGED_CODE();
+ DebugPrint(("Removing device from collection\n"));
+
+ WdfWaitLockAcquire(global.collection_lock, NULL);
+ WdfCollectionRemove(global.device_collection, hDevice);
+ WdfWaitLockRelease(global.collection_lock);
+}
+
+VOID
+WriteDelay()
+{
+ LARGE_INTEGER interval;
+ interval.QuadPart = static_cast<LONGLONG>(ra::WRITE_DELAY) * -10000;
+ KeDelayExecutionThread(KernelMode, FALSE, &interval);
+}
NTSTATUS
DriverEntry(
@@ -259,14 +471,10 @@ Routine Description:
WDF_NO_OBJECT_ATTRIBUTES,
&config,
&driver);
-
- if (NT_SUCCESS(status)) {
- LARGE_INTEGER freq;
- KeQueryPerformanceCounter(&freq);
- global.tick_interval = 1e3 / freq.QuadPart;
- CreateControlDevice(driver);
+ if (NT_SUCCESS(status)) {
+ if (*InitSafeBootMode == 0) RawaccelInit(driver);
}
else {
DebugPrint(("WdfDriverCreate failed with status 0x%x\n", status));
@@ -276,8 +484,7 @@ Routine Description:
}
-inline
-VOID
+NTSTATUS
CreateControlDevice(WDFDRIVER Driver)
/*++
Routine Description:
@@ -378,7 +585,7 @@ Return Value:
//
WdfControlFinishInitializing(controlDevice);
- return;
+ return STATUS_SUCCESS;
Error:
@@ -393,8 +600,9 @@ Error:
}
DebugPrint(("CreateControlDevice failed with status code 0x%x\n", status));
-}
+ return status;
+}
NTSTATUS
EvtDeviceAdd(
@@ -437,7 +645,7 @@ Return Value:
DebugPrint(("Enter FilterEvtDeviceAdd \n"));
- if (*InitSafeBootMode > 0) {
+ if (!global.initialized) {
return STATUS_SUCCESS;
}
@@ -453,6 +661,7 @@ Return Value:
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes,
DEVICE_EXTENSION);
+ deviceAttributes.EvtCleanupCallback = DeviceCleanup;
//
// Create a framework device object. This call will in turn create
@@ -469,7 +678,7 @@ Return Value:
// get device id from bus driver
//
DEVICE_OBJECT* pdo = WdfDeviceWdmGetPhysicalDevice(hDevice);
-
+
KEVENT ke;
KeInitializeEvent(&ke, NotificationEvent, FALSE);
IO_STATUS_BLOCK iosb = {};
@@ -480,18 +689,36 @@ Return Value:
stack->MinorFunction = IRP_MN_QUERY_ID;
stack->Parameters.QueryId.IdType = BusQueryDeviceID;
- NTSTATUS nts = IoCallDriver(pdo, Irp);
+ NTSTATUS tmp = IoCallDriver(pdo, Irp);
- if (nts == STATUS_PENDING) {
+ if (tmp == STATUS_PENDING) {
KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
+ tmp = iosb.Status;
}
- if (NT_SUCCESS(nts)) {
- auto* id_ptr = reinterpret_cast<WCHAR*>(iosb.Information);
- wcsncpy(FilterGetData(hDevice)->dev_id, id_ptr, ra::MAX_DEV_ID_LEN);
- DebugPrint(("Device ID = %ws\n", id_ptr));
+ auto* devExt = FilterGetData(hDevice);
+
+ if (NT_SUCCESS(tmp)) {
+ auto* id_ptr = reinterpret_cast<WCHAR*>(iosb.Information);
+ wcsncpy(devExt->dev_id, id_ptr, ra::MAX_DEV_ID_LEN);
ExFreePool(id_ptr);
}
+ else {
+ DebugPrint(("IoCallDriver failed with status 0x%x\n", tmp));
+ *devExt->dev_id = L'\0';
+ }
+
+ WdfWaitLockAcquire(global.collection_lock, NULL);
+
+ DeviceSetup(hDevice);
+
+ tmp = WdfCollectionAdd(global.device_collection, hDevice);
+
+ if (!NT_SUCCESS(tmp)) {
+ DebugPrint(("WdfCollectionAdd failed with status 0x%x\n", tmp));
+ }
+
+ WdfWaitLockRelease(global.collection_lock);
//
// Configure the default queue to be Parallel. Do not use sequential queue
@@ -597,8 +824,6 @@ Routine Description:
break;
}
- devExt->counter = 0;
- devExt->carry = {};
devExt->UpperConnectData = *connectData;
//
@@ -636,7 +861,6 @@ Routine Description:
}
-inline
VOID
DispatchPassThrough(
_In_ WDFREQUEST Request,
diff --git a/driver/driver.h b/driver/driver.h
index 6184a69..c55afac 100644
--- a/driver/driver.h
+++ b/driver/driver.h
@@ -1,6 +1,6 @@
#pragma once
-#include "rawaccel-base.hpp"
+#include "rawaccel.hpp"
#include "rawaccel-io-def.h"
#include <kbdmou.h>
@@ -19,9 +19,16 @@ using counter_t = long long;
namespace ra = rawaccel;
typedef struct _DEVICE_EXTENSION {
+ bool enable;
+ bool keep_time;
+ bool set_extra_info;
+ double dpi_factor;
counter_t counter;
+ ra::time_clamp clamp;
+ ra::modifier mod;
vec2d carry;
CONNECT_DATA UpperConnectData;
+ ra::modifier_settings mod_settings;
WCHAR dev_id[ra::MAX_DEV_ID_LEN];
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
@@ -30,9 +37,18 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, FilterGetData)
EXTERN_C_START
DRIVER_INITIALIZE DriverEntry;
+
EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd;
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl;
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL RawaccelControl;
+EVT_WDF_OBJECT_CONTEXT_CLEANUP DeviceCleanup;
+
+VOID DeviceSetup(WDFOBJECT);
+VOID WriteDelay(VOID);
+VOID RawaccelInit(WDFDRIVER);
+NTSTATUS CreateControlDevice(WDFDRIVER);
+
+EXTERN_C_END
VOID RawaccelCallback(
IN PDEVICE_OBJECT DeviceObject,
@@ -41,10 +57,6 @@ VOID RawaccelCallback(
IN OUT PULONG InputDataConsumed
);
-EXTERN_C_END
-
-VOID CreateControlDevice(WDFDRIVER Driver);
-
VOID DispatchPassThrough(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target
diff --git a/driver/driver.vcxproj b/driver/driver.vcxproj
index c2e4629..dfc1fdb 100644
--- a/driver/driver.vcxproj
+++ b/driver/driver.vcxproj
@@ -22,9 +22,10 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <TargetVersion>Windows7</TargetVersion>
+ <TargetVersion>
+ </TargetVersion>
<UseDebugLibraries>False</UseDebugLibraries>
- <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
@@ -33,9 +34,10 @@
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <TargetVersion>Windows7</TargetVersion>
+ <TargetVersion>
+ </TargetVersion>
<UseDebugLibraries>True</UseDebugLibraries>
- <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
diff --git a/grapher/Constants/Constants.cs b/grapher/Constants/Constants.cs
index 383d7f4..af9db23 100644
--- a/grapher/Constants/Constants.cs
+++ b/grapher/Constants/Constants.cs
@@ -44,7 +44,7 @@ namespace grapher
public const int DropDownLeftSeparation = 10;
/// <summary> Height of sensitivity chart when displayed alone. </summary>
- public const int SensitivityChartAloneHeight = 480;
+ public const int SensitivityChartAloneHeight = 510;
/// <summary> Height of sensitivity chart when displayed alongside Velocity and Gain charts. </summary>
public const int SensitivityChartTogetherHeight = 328;
@@ -65,7 +65,7 @@ namespace grapher
public const int ButtonVerticalOffset = 60;
/// <summary> Vertical placement of directionality panel below top of containing form </summary>
- public const int DirectionalityVerticalOffset = 285;
+ public const int DirectionalityVerticalOffset = 315;
/// <summary> Padding between directionality title and containing panel </summary>
public const int DirectionalityTitlePad = 8;
@@ -104,10 +104,10 @@ namespace grapher
/// <summary> Default text to be displayed on button delay. </summary>
public const string ButtonDelayText = "Delay";
-
+
/// <summary> Default text to be displayed on button delay. </summary>
public const string ResetButtonText = "Reset";
-
+
/// <summary> Title of sensitivity chart. </summary>
public const string SensitivityChartTitle = "Sensitivity";
@@ -128,10 +128,10 @@ namespace grapher
public const string GuiConfigFileName = ".config";
- /// <summary> Text to direcitonality panel title when panel is closed. </summary>
+ /// <summary> Text to directionality panel title when panel is closed. </summary>
public const string DirectionalityTitleClosed = "Anisotropy \u25BC";
- /// <summary> Text to direcitonality panel title when panel is open. </summary>
+ /// <summary> Text to directionality panel title when panel is open. </summary>
public const string DirectionalityTitleOpen = "Anisotropy \u25B2";
/// <summary> Style used by System.Double.Parse </summary>
@@ -145,6 +145,15 @@ namespace grapher
/// <summary> Line Width For Series data on chart </summary>
public const int ChartSeriesLineWidth = 3;
+ #endregion Constants
+
+ #region ReadOnly
+
+ /// <summary> Default last mouse move label text format. </summary>
+ public static readonly string MouseMoveDefaultFormat = "Last (x, y): ({0}, {1})";
+
+ /// <summary> Last mouse move label text format when last input was from a dpi normalized device. </summary>
+ public static readonly string MouseMoveNormalizedFormat = $"{MouseMoveDefaultFormat} (n)";
/// <summary> Marker size for last-mouse-move chart series. </summary>
public const int DotMarkerSize = 7;
@@ -161,10 +170,6 @@ namespace grapher
/// <summary> Background Color When Streamer Mode Inactive </summary>
public static readonly System.Drawing.Color bgNoStreamer = System.Drawing.Color.White;
- #endregion Constants
-
- #region ReadOnly
-
/// <summary> Color of font in active value labels. </summary>
public static readonly Color ActiveValueFontColor = Color.FromArgb(255, 65, 65, 65);
diff --git a/grapher/DeviceMenuForm.cs b/grapher/DeviceMenuForm.cs
new file mode 100644
index 0000000..dd946f4
--- /dev/null
+++ b/grapher/DeviceMenuForm.cs
@@ -0,0 +1,405 @@
+using grapher.Models.Devices;
+using grapher.Models.Serialized;
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace grapher
+{
+ public class DeviceMenuForm : Form
+ {
+ #region Constructors
+ public DeviceMenuForm(SettingsManager sm)
+ {
+ Manager = sm;
+ defaultConfig = Manager.UserConfig.defaultDeviceConfig;
+
+ var columns = 3;
+ var rows = 9;
+ var tablePanel = new TableLayoutPanel
+ {
+ Dock = DockStyle.Fill,
+ ColumnCount = columns,
+ RowCount = rows
+ };
+
+ SuspendLayout();
+ tablePanel.SuspendLayout();
+
+ Label MakeConfigLabel(string text)
+ {
+ return new Label
+ {
+ Text = text,
+ Anchor = AnchorStyles.Left,
+ AutoSize = true,
+ };
+ }
+
+ DpiLabel = MakeConfigLabel("DPI:");
+ RateLabel = MakeConfigLabel("Polling rate:");
+ DisableLabel = MakeConfigLabel("Disable:");
+ OverrideLabel = MakeConfigLabel("Override defaults:");
+
+ var maxLabel = OverrideLabel;
+ tablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 2));
+ tablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, maxLabel.PreferredSize.Width + maxLabel.Margin.Left + maxLabel.Margin.Right));
+ tablePanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1));
+
+ var middleRowCount = rows - 2;
+ tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
+ for (int i = 0; i < middleRowCount; i++)
+ {
+ tablePanel.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
+ }
+ tablePanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
+
+ var topPanel = new FlowLayoutPanel
+ {
+ AutoSize = true,
+ };
+
+ DefaultDisableCheck = new CheckBox
+ {
+ Text = "Disable by default",
+ AutoSize = true,
+ Checked = defaultConfig.disable,
+ };
+
+ topPanel.Controls.Add(DefaultDisableCheck);
+
+ tablePanel.Controls.Add(topPanel, 0, 0);
+ tablePanel.SetColumnSpan(topPanel, columns);
+
+ var bottomPanel = new FlowLayoutPanel
+ {
+ AutoSize = true,
+ Anchor = AnchorStyles.Right | AnchorStyles.Bottom,
+ };
+
+ var applyButton = new Button
+ {
+ Text = "Apply",
+ DialogResult = DialogResult.OK,
+ };
+
+ bottomPanel.Controls.AddRange(new Control[] {
+ applyButton,
+ new Button
+ {
+ Text = "Cancel",
+ DialogResult = DialogResult.Cancel,
+ },
+ });
+
+ tablePanel.Controls.Add(bottomPanel, 0, rows - 1);
+ tablePanel.SetColumnSpan(bottomPanel, columns);
+
+ IdPanel = new Panel
+ {
+ Dock = DockStyle.Fill,
+ };
+
+ IdText = new TextBox
+ {
+ ReadOnly = true,
+ BorderStyle = BorderStyle.None,
+ BackColor = this.BackColor,
+ TabStop = false,
+ TextAlign = HorizontalAlignment.Center,
+ Dock = DockStyle.Fill,
+ };
+
+ IdPanel.Controls.Add(IdText);
+ IdPanel.Controls.Add(new Label
+ {
+ // divider
+ Height = 2,
+ BorderStyle = BorderStyle.Fixed3D,
+ AutoSize = false,
+ Text = string.Empty,
+ Dock = DockStyle.Bottom,
+ });
+
+ tablePanel.Controls.Add(IdPanel, 1, 1);
+ tablePanel.SetColumnSpan(IdPanel, 2);
+
+ NumericUpDown MakeNumericInput(int val = 0, int min = 0, int max = 999999)
+ {
+ return new NumericUpDown
+ {
+ Value = val,
+ Minimum = min,
+ Maximum = max,
+ Dock = DockStyle.Fill,
+ Anchor = AnchorStyles.Left,
+ AutoSize = true,
+ };
+ }
+
+ CheckBox MakeCheck()
+ {
+ return new CheckBox
+ {
+ Text = string.Empty,
+ AutoSize = true,
+ Anchor = AnchorStyles.Left,
+ };
+ }
+
+ DpiInput = MakeNumericInput();
+ RateInput = MakeNumericInput();
+ DisableCheck = MakeCheck();
+ OverrideCheck = MakeCheck();
+
+ tablePanel.Controls.Add(OverrideLabel, 1, 2);
+ tablePanel.Controls.Add(OverrideCheck, 2, 2);
+ tablePanel.Controls.Add(DisableLabel, 1, 3);
+ tablePanel.Controls.Add(DisableCheck, 2, 3);
+ tablePanel.Controls.Add(DpiLabel, 1, 5);
+ tablePanel.Controls.Add(DpiInput, 2, 5);
+ tablePanel.Controls.Add(RateLabel, 1, 6);
+ tablePanel.Controls.Add(RateInput, 2, 6);
+
+ DeviceSelect = new ListBox
+ {
+ Dock = DockStyle.Fill,
+ IntegralHeight = false,
+ HorizontalScrollbar = true
+ };
+
+ tablePanel.Controls.Add(DeviceSelect, 0, 1);
+ tablePanel.SetRowSpan(DeviceSelect, middleRowCount);
+
+ ResetDataAndSelection();
+ SetEnabled(false);
+ SetVisible(false);
+
+ applyButton.Click += ApplyButton_Click;
+ OverrideCheck.Click += OverrideCheck_Click;
+ OverrideCheck.CheckedChanged += OverrideCheck_Checked;
+ DefaultDisableCheck.CheckedChanged += DefaultDisableCheck_Checked;
+ IdText.DoubleClick += SelectAllText;
+ DeviceSelect.SelectedIndexChanged += DeviceSelect_SelectedIndexChanged;
+ Manager.DeviceChange += OnDeviceChange;
+ Disposed += OnDispose;
+
+ var toolTip = new ToolTip();
+ toolTip.SetToolTip(IdText, "Device ID");
+
+ var rateTip = "Keep at 0 for automatic adjustment";
+ toolTip.SetToolTip(RateInput, rateTip);
+ toolTip.SetToolTip(RateLabel, rateTip);
+
+ var dpiTip = "Normalizes sensitivity and input speed to 1000 DPI";
+ toolTip.SetToolTip(DpiInput, dpiTip);
+ toolTip.SetToolTip(DpiLabel, dpiTip);
+
+
+ Name = "DeviceMenuForm";
+ Text = "Devices";
+ MaximizeBox = false;
+ MinimizeBox = false;
+ FormBorderStyle = FormBorderStyle.FixedDialog;
+ StartPosition = FormStartPosition.CenterParent;
+ AutoScaleDimensions = new SizeF(6F, 13F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(500, 300);
+
+ Controls.Add(tablePanel);
+
+ tablePanel.ResumeLayout(false);
+ ResumeLayout(false);
+ }
+
+ #endregion Constructors
+
+ #region Fields
+
+ public DeviceConfig defaultConfig;
+
+ #endregion Fields
+
+ #region Properties
+
+ public DeviceDialogItem[] Items { get; private set; }
+
+ private DeviceDialogItem Selected
+ {
+ get => (DeviceDialogItem)DeviceSelect.SelectedItem;
+ }
+
+ private bool AnySelected
+ {
+ get => DeviceSelect.SelectedIndex != -1;
+ }
+
+ private int LastSelectedIndex { get; set; }
+
+ private SettingsManager Manager { get; }
+
+ private ListBox DeviceSelect { get; }
+
+ private CheckBox DefaultDisableCheck { get; }
+
+ private TextBox IdText { get; }
+ private Panel IdPanel { get; }
+
+ private Label OverrideLabel { get; }
+ private CheckBox OverrideCheck { get; }
+
+ private Label DisableLabel { get; }
+ private CheckBox DisableCheck { get; }
+
+ private Label DpiLabel { get; }
+ private NumericUpDown DpiInput { get; }
+
+ private Label RateLabel { get; }
+ private NumericUpDown RateInput { get; }
+
+ #endregion Properties
+
+ #region Methods
+
+ private void ResetDataAndSelection()
+ {
+ var count = Manager.SystemDevices.Count;
+ Items = new DeviceDialogItem[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ var sysDev = Manager.SystemDevices[i];
+ var settings = Manager.UserConfig.devices.Find(s => s.id == sysDev.id);
+ bool found = !(settings is null);
+
+ Items[i] = new DeviceDialogItem
+ {
+ device = sysDev,
+ overrideDefaultConfig = found,
+ oldSettings = settings,
+ newConfig = found ?
+ settings.config :
+ Manager.UserConfig.defaultDeviceConfig,
+ newProfile = found ?
+ settings.profile :
+ Manager.UserConfig.profiles[0].name
+ };
+ }
+
+ LastSelectedIndex = -1;
+ DeviceSelect.ClearSelected();
+ DeviceSelect.Items.Clear();
+ DeviceSelect.Items.AddRange(Items);
+ }
+
+ private void SetVisible(bool visible)
+ {
+ IdPanel.Visible = visible;
+ OverrideLabel.Visible = visible;
+ OverrideCheck.Visible = visible;
+ DisableLabel.Visible = visible;
+ DisableCheck.Visible = visible;
+ DpiInput.Visible = visible;
+ DpiLabel.Visible = visible;
+ RateInput.Visible = visible;
+ RateLabel.Visible = visible;
+ }
+
+ private void SetEnabled(bool enable)
+ {
+ DisableLabel.Enabled = enable;
+ DisableCheck.Enabled = enable;
+ DpiInput.Enabled = enable;
+ DpiLabel.Enabled = enable;
+ RateInput.Enabled = enable;
+ RateLabel.Enabled = enable;
+ }
+
+ private void SetInputsFromNewSelection()
+ {
+ IdText.Text = Selected.device.id;
+ OverrideCheck.Checked = Selected.overrideDefaultConfig;
+
+ SetOverrideDependentInputs();
+ }
+
+ private void SetOverrideDependentInputs()
+ {
+ var item = Selected;
+ bool oride = item.overrideDefaultConfig;
+ DisableCheck.Checked = oride ? item.newConfig.disable : defaultConfig.disable;
+ DpiInput.Value = oride ? item.newConfig.dpi : defaultConfig.dpi;
+ RateInput.Value = oride ? item.newConfig.pollingRate : defaultConfig.pollingRate;
+ }
+
+ private void UpdateLastSelected()
+ {
+ var item = Items[LastSelectedIndex];
+ bool oride = OverrideCheck.Checked;
+ item.overrideDefaultConfig = oride;
+ item.newConfig.disable = oride ? DisableCheck.Checked : defaultConfig.disable;
+ item.newConfig.dpi = oride ? (int)DpiInput.Value : defaultConfig.dpi;
+ item.newConfig.pollingRate = oride ? (int)RateInput.Value : defaultConfig.pollingRate;
+ }
+
+ private void ApplyButton_Click(object sender, EventArgs e)
+ {
+ if (AnySelected) UpdateLastSelected();
+ }
+
+ private void OverrideCheck_Checked(object sender, EventArgs e)
+ {
+ SetEnabled(OverrideCheck.Checked);
+ }
+
+ private void OverrideCheck_Click(object sender, EventArgs e)
+ {
+ UpdateLastSelected();
+ SetOverrideDependentInputs();
+ }
+
+ private void DefaultDisableCheck_Checked(object sender, EventArgs e)
+ {
+ defaultConfig.disable = DefaultDisableCheck.Checked;
+
+ if (AnySelected && !Selected.overrideDefaultConfig)
+ {
+ DisableCheck.Checked = DefaultDisableCheck.Checked;
+ }
+ }
+
+ private void DeviceSelect_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (AnySelected)
+ {
+ if (LastSelectedIndex != -1)
+ {
+ UpdateLastSelected();
+ }
+
+ SetInputsFromNewSelection();
+ }
+
+ LastSelectedIndex = DeviceSelect.SelectedIndex;
+
+ SetVisible(AnySelected);
+ }
+
+ private void OnDeviceChange(object sender, EventArgs e)
+ {
+ ResetDataAndSelection();
+ }
+
+ private void OnDispose(object sender, EventArgs e)
+ {
+ Manager.DeviceChange -= OnDeviceChange;
+ }
+
+ private static void SelectAllText(object sender, EventArgs e)
+ {
+ ((TextBoxBase)sender).SelectAll();
+ }
+
+ #endregion Methods
+ }
+}
diff --git a/grapher/Form1.Designer.cs b/grapher/Form1.Designer.cs
index 203397b..89eafda 100644
--- a/grapher/Form1.Designer.cs
+++ b/grapher/Form1.Designer.cs
@@ -71,6 +71,43 @@ namespace grapher
System.Windows.Forms.DataVisualization.Charting.Title title6 = new System.Windows.Forms.DataVisualization.Charting.Title();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RawAcceleration));
this.optionsPanel = new System.Windows.Forms.Panel();
+ this.OutCapActiveYLabelPower = new System.Windows.Forms.Label();
+ this.InCapActiveYLabelPower = new System.Windows.Forms.Label();
+ this.OutCapActiveXLabelPower = new System.Windows.Forms.Label();
+ this.InCapActiveXLabelPower = new System.Windows.Forms.Label();
+ this.CapTypeActiveYLabelPower = new System.Windows.Forms.Label();
+ this.CapTypeActiveXLabelPower = new System.Windows.Forms.Label();
+ this.outCapLabelYPower = new System.Windows.Forms.Label();
+ this.inCapLabelYPower = new System.Windows.Forms.Label();
+ this.CapTypeLabelYPower = new System.Windows.Forms.Label();
+ this.outCapLabelXPower = new System.Windows.Forms.Label();
+ this.inCapLabelXPower = new System.Windows.Forms.Label();
+ this.CapTypeLabelXPower = new System.Windows.Forms.Label();
+ this.outCapBoxYPower = new System.Windows.Forms.TextBox();
+ this.outCapBoxXPower = new System.Windows.Forms.TextBox();
+ this.inCapBoxYPower = new System.Windows.Forms.TextBox();
+ this.inCapBoxXPower = new System.Windows.Forms.TextBox();
+ this.CapTypeDropdownYPower = new System.Windows.Forms.ComboBox();
+ this.CapTypeDropdownXPower = new System.Windows.Forms.ComboBox();
+ this.CapTypeActiveYLabelClassic = new System.Windows.Forms.Label();
+ this.CapTypeActiveXLabelClassic = new System.Windows.Forms.Label();
+ this.OutCapActiveYLabelClassic = new System.Windows.Forms.Label();
+ this.OutCapActiveXLabelClassic = new System.Windows.Forms.Label();
+ this.outCapLabelYClassic = new System.Windows.Forms.Label();
+ this.outCapLabelXClassic = new System.Windows.Forms.Label();
+ this.outCapBoxYClassic = new System.Windows.Forms.TextBox();
+ this.outCapBoxXClassic = new System.Windows.Forms.TextBox();
+ this.CapTypeLabelYClassic = new System.Windows.Forms.Label();
+ this.CapTypeLabelXClassic = new System.Windows.Forms.Label();
+ this.CapTypeDropdownYClassic = new System.Windows.Forms.ComboBox();
+ this.CapTypeDropdownXClassic = new System.Windows.Forms.ComboBox();
+ this.VertHorzRatioLabel = new System.Windows.Forms.Label();
+ this.SmoothActiveYLabel = new System.Windows.Forms.Label();
+ this.smoothLabelY = new System.Windows.Forms.Label();
+ this.SmoothActiveXLabel = new System.Windows.Forms.Label();
+ this.smoothLabelX = new System.Windows.Forms.Label();
+ this.smoothBoxY = new System.Windows.Forms.TextBox();
+ this.smoothBoxX = new System.Windows.Forms.TextBox();
this.GrowthRateActiveYLabel = new System.Windows.Forms.Label();
this.GrowthRateActiveXLabel = new System.Windows.Forms.Label();
this.DecayRateActiveYLabel = new System.Windows.Forms.Label();
@@ -145,50 +182,62 @@ namespace grapher
this.OptionSetXTitle = new System.Windows.Forms.Label();
this.constantThreeLabelY = new System.Windows.Forms.Label();
this.limitLabelY = new System.Windows.Forms.Label();
- this.offsetLabelY = new System.Windows.Forms.Label();
- this.weightLabelY = new System.Windows.Forms.Label();
- this.capLabelY = new System.Windows.Forms.Label();
+ this.inputJumpLabelY = new System.Windows.Forms.Label();
+ this.outputJumpLabelY = new System.Windows.Forms.Label();
+ this.inputOffsetLabelY = new System.Windows.Forms.Label();
+ this.outputOffsetLabelY = new System.Windows.Forms.Label();
+ this.inCapLabelYClassic = new System.Windows.Forms.Label();
this.constantOneLabelY = new System.Windows.Forms.Label();
this.ByComponentXYLock = new System.Windows.Forms.CheckBox();
this.MidpointActiveYLabel = new System.Windows.Forms.Label();
this.LimitActiveYLabel = new System.Windows.Forms.Label();
- this.OffsetActiveYLabel = new System.Windows.Forms.Label();
+ this.InputJumpActiveYLabel = new System.Windows.Forms.Label();
+ this.OutputJumpActiveYLabel = new System.Windows.Forms.Label();
+ this.InputOffsetActiveYLabel = new System.Windows.Forms.Label();
+ this.OutputOffsetActiveYLabel = new System.Windows.Forms.Label();
this.AccelerationActiveLabelY = new System.Windows.Forms.Label();
this.accelTypeDropY = new System.Windows.Forms.ComboBox();
this.midpointBoxY = new System.Windows.Forms.TextBox();
this.limitBoxY = new System.Windows.Forms.TextBox();
- this.offsetBoxY = new System.Windows.Forms.TextBox();
+ this.inputJumpBoxY = new System.Windows.Forms.TextBox();
+ this.outputJumpBoxY = new System.Windows.Forms.TextBox();
+ this.inputOffsetBoxY = new System.Windows.Forms.TextBox();
+ this.outputOffsetBoxY = new System.Windows.Forms.TextBox();
this.accelerationBoxY = new System.Windows.Forms.TextBox();
this.MidpointActiveXLabel = new System.Windows.Forms.Label();
this.LimitActiveXLabel = new System.Windows.Forms.Label();
- this.OffsetActiveXLabel = new System.Windows.Forms.Label();
- this.CapActiveYLabel = new System.Windows.Forms.Label();
- this.WeightActiveYLabel = new System.Windows.Forms.Label();
- this.WeightActiveXLabel = new System.Windows.Forms.Label();
- this.CapActiveXLabel = new System.Windows.Forms.Label();
+ this.InputJumpActiveXLabel = new System.Windows.Forms.Label();
+ this.OutputJumpActiveXLabel = new System.Windows.Forms.Label();
+ this.InputOffsetActiveXLabel = new System.Windows.Forms.Label();
+ this.OutputOffsetActiveXLabel = new System.Windows.Forms.Label();
+ this.InCapActiveYLabelClassic = new System.Windows.Forms.Label();
+ this.InCapActiveXLabelClassic = new System.Windows.Forms.Label();
this.AccelerationActiveLabelX = new System.Windows.Forms.Label();
this.AccelTypeActiveLabelX = new System.Windows.Forms.Label();
this.RotationActiveLabel = new System.Windows.Forms.Label();
- this.SensitivityActiveYLabel = new System.Windows.Forms.Label();
- this.SensitivityActiveXLabel = new System.Windows.Forms.Label();
+ this.VertHorzRatioActiveLabel = new System.Windows.Forms.Label();
+ this.SensitivityMultiplierActiveLabel = new System.Windows.Forms.Label();
this.ActiveValueTitle = new System.Windows.Forms.Label();
this.MouseLabel = new System.Windows.Forms.Label();
this.LockXYLabel = new System.Windows.Forms.Label();
this.sensXYLock = new System.Windows.Forms.CheckBox();
- this.capBoxY = new System.Windows.Forms.TextBox();
- this.sensitivityBoxY = new System.Windows.Forms.TextBox();
+ this.inCapBoxYClassic = new System.Windows.Forms.TextBox();
+ this.VertHorzRatioBox = new System.Windows.Forms.TextBox();
this.writeButton = new System.Windows.Forms.Button();
- this.offsetLabelX = new System.Windows.Forms.Label();
- this.offsetBoxX = new System.Windows.Forms.TextBox();
+ this.inputJumpLabelX = new System.Windows.Forms.Label();
+ this.outputJumpLabelX = new System.Windows.Forms.Label();
+ this.inputJumpBoxX = new System.Windows.Forms.TextBox();
+ this.outputJumpBoxX = new System.Windows.Forms.TextBox();
+ this.inputOffsetLabelX = new System.Windows.Forms.Label();
+ this.outputOffsetLabelX = new System.Windows.Forms.Label();
+ this.inputOffsetBoxX = new System.Windows.Forms.TextBox();
+ this.outputOffsetBoxX = new System.Windows.Forms.TextBox();
this.constantThreeLabelX = new System.Windows.Forms.Label();
this.midpointBoxX = new System.Windows.Forms.TextBox();
this.limitLabelX = new System.Windows.Forms.Label();
this.limitBoxX = new System.Windows.Forms.TextBox();
- this.weightBoxY = new System.Windows.Forms.TextBox();
- this.weightLabelX = new System.Windows.Forms.Label();
- this.weightBoxX = new System.Windows.Forms.TextBox();
- this.capLabelX = new System.Windows.Forms.Label();
- this.capBoxX = new System.Windows.Forms.TextBox();
+ this.inCapLabelXClassic = new System.Windows.Forms.Label();
+ this.inCapBoxXClassic = new System.Windows.Forms.TextBox();
this.constantOneLabelX = new System.Windows.Forms.Label();
this.accelerationBoxX = new System.Windows.Forms.TextBox();
this.rotationLabel = new System.Windows.Forms.Label();
@@ -209,7 +258,7 @@ namespace grapher
this.streamingModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.advancedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.AutoWriteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.UseSpecificDeviceMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.DeviceMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.chartsPanel = new System.Windows.Forms.Panel();
this.GainChartY = new System.Windows.Forms.DataVisualization.Charting.Chart();
this.VelocityChartY = new System.Windows.Forms.DataVisualization.Charting.Chart();
@@ -217,12 +266,6 @@ namespace grapher
this.GainChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
this.VelocityChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
this.AccelerationChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
- this.smoothBoxX = new System.Windows.Forms.TextBox();
- this.smoothBoxY = new System.Windows.Forms.TextBox();
- this.smoothLabelX = new System.Windows.Forms.Label();
- this.SmoothActiveXLabel = new System.Windows.Forms.Label();
- this.smoothLabelY = new System.Windows.Forms.Label();
- this.SmoothActiveYLabel = new System.Windows.Forms.Label();
this.optionsPanel.SuspendLayout();
this.DirectionalityPanel.SuspendLayout();
this.menuStrip1.SuspendLayout();
@@ -238,6 +281,37 @@ namespace grapher
// optionsPanel
//
this.optionsPanel.AutoSize = true;
+ this.optionsPanel.Controls.Add(this.OutCapActiveYLabelPower);
+ this.optionsPanel.Controls.Add(this.InCapActiveYLabelPower);
+ this.optionsPanel.Controls.Add(this.OutCapActiveXLabelPower);
+ this.optionsPanel.Controls.Add(this.InCapActiveXLabelPower);
+ this.optionsPanel.Controls.Add(this.CapTypeActiveYLabelPower);
+ this.optionsPanel.Controls.Add(this.CapTypeActiveXLabelPower);
+ this.optionsPanel.Controls.Add(this.outCapLabelYPower);
+ this.optionsPanel.Controls.Add(this.inCapLabelYPower);
+ this.optionsPanel.Controls.Add(this.CapTypeLabelYPower);
+ this.optionsPanel.Controls.Add(this.outCapLabelXPower);
+ this.optionsPanel.Controls.Add(this.inCapLabelXPower);
+ this.optionsPanel.Controls.Add(this.CapTypeLabelXPower);
+ this.optionsPanel.Controls.Add(this.outCapBoxYPower);
+ this.optionsPanel.Controls.Add(this.outCapBoxXPower);
+ this.optionsPanel.Controls.Add(this.inCapBoxYPower);
+ this.optionsPanel.Controls.Add(this.inCapBoxXPower);
+ this.optionsPanel.Controls.Add(this.CapTypeDropdownYPower);
+ this.optionsPanel.Controls.Add(this.CapTypeDropdownXPower);
+ this.optionsPanel.Controls.Add(this.CapTypeActiveYLabelClassic);
+ this.optionsPanel.Controls.Add(this.CapTypeActiveXLabelClassic);
+ this.optionsPanel.Controls.Add(this.OutCapActiveYLabelClassic);
+ this.optionsPanel.Controls.Add(this.OutCapActiveXLabelClassic);
+ this.optionsPanel.Controls.Add(this.outCapLabelYClassic);
+ this.optionsPanel.Controls.Add(this.outCapLabelXClassic);
+ this.optionsPanel.Controls.Add(this.outCapBoxYClassic);
+ this.optionsPanel.Controls.Add(this.outCapBoxXClassic);
+ this.optionsPanel.Controls.Add(this.CapTypeLabelYClassic);
+ this.optionsPanel.Controls.Add(this.CapTypeLabelXClassic);
+ this.optionsPanel.Controls.Add(this.CapTypeDropdownYClassic);
+ this.optionsPanel.Controls.Add(this.CapTypeDropdownXClassic);
+ this.optionsPanel.Controls.Add(this.VertHorzRatioLabel);
this.optionsPanel.Controls.Add(this.SmoothActiveYLabel);
this.optionsPanel.Controls.Add(this.smoothLabelY);
this.optionsPanel.Controls.Add(this.SmoothActiveXLabel);
@@ -299,50 +373,62 @@ namespace grapher
this.optionsPanel.Controls.Add(this.OptionSetXTitle);
this.optionsPanel.Controls.Add(this.constantThreeLabelY);
this.optionsPanel.Controls.Add(this.limitLabelY);
- this.optionsPanel.Controls.Add(this.offsetLabelY);
- this.optionsPanel.Controls.Add(this.weightLabelY);
- this.optionsPanel.Controls.Add(this.capLabelY);
+ this.optionsPanel.Controls.Add(this.inputJumpLabelY);
+ this.optionsPanel.Controls.Add(this.outputJumpLabelY);
+ this.optionsPanel.Controls.Add(this.inputOffsetLabelY);
+ this.optionsPanel.Controls.Add(this.outputOffsetLabelY);
+ this.optionsPanel.Controls.Add(this.inCapLabelYClassic);
this.optionsPanel.Controls.Add(this.constantOneLabelY);
this.optionsPanel.Controls.Add(this.ByComponentXYLock);
this.optionsPanel.Controls.Add(this.MidpointActiveYLabel);
this.optionsPanel.Controls.Add(this.LimitActiveYLabel);
- this.optionsPanel.Controls.Add(this.OffsetActiveYLabel);
+ this.optionsPanel.Controls.Add(this.InputJumpActiveYLabel);
+ this.optionsPanel.Controls.Add(this.OutputJumpActiveYLabel);
+ this.optionsPanel.Controls.Add(this.InputOffsetActiveYLabel);
+ this.optionsPanel.Controls.Add(this.OutputOffsetActiveYLabel);
this.optionsPanel.Controls.Add(this.AccelerationActiveLabelY);
this.optionsPanel.Controls.Add(this.accelTypeDropY);
this.optionsPanel.Controls.Add(this.midpointBoxY);
this.optionsPanel.Controls.Add(this.limitBoxY);
- this.optionsPanel.Controls.Add(this.offsetBoxY);
+ this.optionsPanel.Controls.Add(this.inputJumpBoxY);
+ this.optionsPanel.Controls.Add(this.outputJumpBoxY);
+ this.optionsPanel.Controls.Add(this.inputOffsetBoxY);
+ this.optionsPanel.Controls.Add(this.outputOffsetBoxY);
this.optionsPanel.Controls.Add(this.accelerationBoxY);
this.optionsPanel.Controls.Add(this.MidpointActiveXLabel);
this.optionsPanel.Controls.Add(this.LimitActiveXLabel);
- this.optionsPanel.Controls.Add(this.OffsetActiveXLabel);
- this.optionsPanel.Controls.Add(this.CapActiveYLabel);
- this.optionsPanel.Controls.Add(this.WeightActiveYLabel);
- this.optionsPanel.Controls.Add(this.WeightActiveXLabel);
- this.optionsPanel.Controls.Add(this.CapActiveXLabel);
+ this.optionsPanel.Controls.Add(this.InputJumpActiveXLabel);
+ this.optionsPanel.Controls.Add(this.OutputJumpActiveXLabel);
+ this.optionsPanel.Controls.Add(this.InputOffsetActiveXLabel);
+ this.optionsPanel.Controls.Add(this.OutputOffsetActiveXLabel);
+ this.optionsPanel.Controls.Add(this.InCapActiveYLabelClassic);
+ this.optionsPanel.Controls.Add(this.InCapActiveXLabelClassic);
this.optionsPanel.Controls.Add(this.AccelerationActiveLabelX);
this.optionsPanel.Controls.Add(this.AccelTypeActiveLabelX);
this.optionsPanel.Controls.Add(this.RotationActiveLabel);
- this.optionsPanel.Controls.Add(this.SensitivityActiveYLabel);
- this.optionsPanel.Controls.Add(this.SensitivityActiveXLabel);
+ this.optionsPanel.Controls.Add(this.VertHorzRatioActiveLabel);
+ this.optionsPanel.Controls.Add(this.SensitivityMultiplierActiveLabel);
this.optionsPanel.Controls.Add(this.ActiveValueTitle);
this.optionsPanel.Controls.Add(this.MouseLabel);
this.optionsPanel.Controls.Add(this.LockXYLabel);
this.optionsPanel.Controls.Add(this.sensXYLock);
- this.optionsPanel.Controls.Add(this.capBoxY);
- this.optionsPanel.Controls.Add(this.sensitivityBoxY);
+ this.optionsPanel.Controls.Add(this.inCapBoxYClassic);
+ this.optionsPanel.Controls.Add(this.VertHorzRatioBox);
this.optionsPanel.Controls.Add(this.writeButton);
- this.optionsPanel.Controls.Add(this.offsetLabelX);
- this.optionsPanel.Controls.Add(this.offsetBoxX);
+ this.optionsPanel.Controls.Add(this.inputJumpLabelX);
+ this.optionsPanel.Controls.Add(this.outputJumpLabelX);
+ this.optionsPanel.Controls.Add(this.inputJumpBoxX);
+ this.optionsPanel.Controls.Add(this.outputJumpBoxX);
+ this.optionsPanel.Controls.Add(this.inputOffsetLabelX);
+ this.optionsPanel.Controls.Add(this.outputOffsetLabelX);
+ this.optionsPanel.Controls.Add(this.inputOffsetBoxX);
+ this.optionsPanel.Controls.Add(this.outputOffsetBoxX);
this.optionsPanel.Controls.Add(this.constantThreeLabelX);
this.optionsPanel.Controls.Add(this.midpointBoxX);
this.optionsPanel.Controls.Add(this.limitLabelX);
this.optionsPanel.Controls.Add(this.limitBoxX);
- this.optionsPanel.Controls.Add(this.weightBoxY);
- this.optionsPanel.Controls.Add(this.weightLabelX);
- this.optionsPanel.Controls.Add(this.weightBoxX);
- this.optionsPanel.Controls.Add(this.capLabelX);
- this.optionsPanel.Controls.Add(this.capBoxX);
+ this.optionsPanel.Controls.Add(this.inCapLabelXClassic);
+ this.optionsPanel.Controls.Add(this.inCapBoxXClassic);
this.optionsPanel.Controls.Add(this.constantOneLabelX);
this.optionsPanel.Controls.Add(this.accelerationBoxX);
this.optionsPanel.Controls.Add(this.rotationLabel);
@@ -358,10 +444,323 @@ namespace grapher
this.optionsPanel.Size = new System.Drawing.Size(483, 956);
this.optionsPanel.TabIndex = 34;
//
+ // OutCapActiveYLabelPower
+ //
+ this.OutCapActiveYLabelPower.AutoSize = true;
+ this.OutCapActiveYLabelPower.Location = new System.Drawing.Point(414, 836);
+ this.OutCapActiveYLabelPower.Name = "OutCapActiveYLabelPower";
+ this.OutCapActiveYLabelPower.Size = new System.Drawing.Size(13, 13);
+ this.OutCapActiveYLabelPower.TabIndex = 224;
+ this.OutCapActiveYLabelPower.Text = "0";
+ //
+ // InCapActiveYLabelPower
+ //
+ this.InCapActiveYLabelPower.AutoSize = true;
+ this.InCapActiveYLabelPower.Location = new System.Drawing.Point(417, 810);
+ this.InCapActiveYLabelPower.Name = "InCapActiveYLabelPower";
+ this.InCapActiveYLabelPower.Size = new System.Drawing.Size(13, 13);
+ this.InCapActiveYLabelPower.TabIndex = 223;
+ this.InCapActiveYLabelPower.Text = "0";
+ //
+ // OutCapActiveXLabelPower
+ //
+ this.OutCapActiveXLabelPower.AutoSize = true;
+ this.OutCapActiveXLabelPower.Location = new System.Drawing.Point(200, 837);
+ this.OutCapActiveXLabelPower.Name = "OutCapActiveXLabelPower";
+ this.OutCapActiveXLabelPower.Size = new System.Drawing.Size(13, 13);
+ this.OutCapActiveXLabelPower.TabIndex = 222;
+ this.OutCapActiveXLabelPower.Text = "0";
+ //
+ // InCapActiveXLabelPower
+ //
+ this.InCapActiveXLabelPower.AutoSize = true;
+ this.InCapActiveXLabelPower.Location = new System.Drawing.Point(200, 810);
+ this.InCapActiveXLabelPower.Name = "InCapActiveXLabelPower";
+ this.InCapActiveXLabelPower.Size = new System.Drawing.Size(13, 13);
+ this.InCapActiveXLabelPower.TabIndex = 221;
+ this.InCapActiveXLabelPower.Text = "0";
+ //
+ // CapTypeActiveYLabelPower
+ //
+ this.CapTypeActiveYLabelPower.AutoSize = true;
+ this.CapTypeActiveYLabelPower.Location = new System.Drawing.Point(414, 783);
+ this.CapTypeActiveYLabelPower.Name = "CapTypeActiveYLabelPower";
+ this.CapTypeActiveYLabelPower.Size = new System.Drawing.Size(16, 13);
+ this.CapTypeActiveYLabelPower.TabIndex = 220;
+ this.CapTypeActiveYLabelPower.Text = "In";
+ //
+ // CapTypeActiveXLabelPower
+ //
+ this.CapTypeActiveXLabelPower.AutoSize = true;
+ this.CapTypeActiveXLabelPower.Location = new System.Drawing.Point(200, 788);
+ this.CapTypeActiveXLabelPower.Name = "CapTypeActiveXLabelPower";
+ this.CapTypeActiveXLabelPower.Size = new System.Drawing.Size(16, 13);
+ this.CapTypeActiveXLabelPower.TabIndex = 219;
+ this.CapTypeActiveXLabelPower.Text = "In";
+ //
+ // outCapLabelYPower
+ //
+ this.outCapLabelYPower.AutoSize = true;
+ this.outCapLabelYPower.Location = new System.Drawing.Point(262, 837);
+ this.outCapLabelYPower.Name = "outCapLabelYPower";
+ this.outCapLabelYPower.Size = new System.Drawing.Size(64, 13);
+ this.outCapLabelYPower.TabIndex = 218;
+ this.outCapLabelYPower.Text = "Cap: Output";
+ //
+ // inCapLabelYPower
+ //
+ this.inCapLabelYPower.AutoSize = true;
+ this.inCapLabelYPower.Location = new System.Drawing.Point(262, 810);
+ this.inCapLabelYPower.Name = "inCapLabelYPower";
+ this.inCapLabelYPower.Size = new System.Drawing.Size(56, 13);
+ this.inCapLabelYPower.TabIndex = 217;
+ this.inCapLabelYPower.Text = "Cap: Input";
+ //
+ // CapTypeLabelYPower
+ //
+ this.CapTypeLabelYPower.AutoSize = true;
+ this.CapTypeLabelYPower.Location = new System.Drawing.Point(262, 783);
+ this.CapTypeLabelYPower.Name = "CapTypeLabelYPower";
+ this.CapTypeLabelYPower.Size = new System.Drawing.Size(53, 13);
+ this.CapTypeLabelYPower.TabIndex = 216;
+ this.CapTypeLabelYPower.Text = "Cap Type";
+ //
+ // outCapLabelXPower
+ //
+ this.outCapLabelXPower.AutoSize = true;
+ this.outCapLabelXPower.Location = new System.Drawing.Point(35, 836);
+ this.outCapLabelXPower.Name = "outCapLabelXPower";
+ this.outCapLabelXPower.Size = new System.Drawing.Size(64, 13);
+ this.outCapLabelXPower.TabIndex = 215;
+ this.outCapLabelXPower.Text = "Cap: Output";
+ //
+ // inCapLabelXPower
+ //
+ this.inCapLabelXPower.AutoSize = true;
+ this.inCapLabelXPower.Location = new System.Drawing.Point(38, 810);
+ this.inCapLabelXPower.Name = "inCapLabelXPower";
+ this.inCapLabelXPower.Size = new System.Drawing.Size(56, 13);
+ this.inCapLabelXPower.TabIndex = 214;
+ this.inCapLabelXPower.Text = "Cap: Input";
+ //
+ // CapTypeLabelXPower
+ //
+ this.CapTypeLabelXPower.AutoSize = true;
+ this.CapTypeLabelXPower.Location = new System.Drawing.Point(40, 783);
+ this.CapTypeLabelXPower.Name = "CapTypeLabelXPower";
+ this.CapTypeLabelXPower.Size = new System.Drawing.Size(53, 13);
+ this.CapTypeLabelXPower.TabIndex = 213;
+ this.CapTypeLabelXPower.Text = "Cap Type";
+ //
+ // outCapBoxYPower
+ //
+ this.outCapBoxYPower.Location = new System.Drawing.Point(332, 834);
+ this.outCapBoxYPower.Name = "outCapBoxYPower";
+ this.outCapBoxYPower.Size = new System.Drawing.Size(76, 20);
+ this.outCapBoxYPower.TabIndex = 212;
+ //
+ // outCapBoxXPower
+ //
+ this.outCapBoxXPower.Location = new System.Drawing.Point(106, 833);
+ this.outCapBoxXPower.Name = "outCapBoxXPower";
+ this.outCapBoxXPower.Size = new System.Drawing.Size(76, 20);
+ this.outCapBoxXPower.TabIndex = 211;
+ //
+ // inCapBoxYPower
+ //
+ this.inCapBoxYPower.Location = new System.Drawing.Point(332, 807);
+ this.inCapBoxYPower.Name = "inCapBoxYPower";
+ this.inCapBoxYPower.Size = new System.Drawing.Size(76, 20);
+ this.inCapBoxYPower.TabIndex = 210;
+ //
+ // inCapBoxXPower
+ //
+ this.inCapBoxXPower.Location = new System.Drawing.Point(106, 807);
+ this.inCapBoxXPower.Name = "inCapBoxXPower";
+ this.inCapBoxXPower.Size = new System.Drawing.Size(76, 20);
+ this.inCapBoxXPower.TabIndex = 209;
+ //
+ // CapTypeDropdownYPower
+ //
+ this.CapTypeDropdownYPower.FormattingEnabled = true;
+ this.CapTypeDropdownYPower.Location = new System.Drawing.Point(332, 780);
+ this.CapTypeDropdownYPower.Name = "CapTypeDropdownYPower";
+ this.CapTypeDropdownYPower.Size = new System.Drawing.Size(76, 21);
+ this.CapTypeDropdownYPower.TabIndex = 208;
+ //
+ // CapTypeDropdownXPower
+ //
+ this.CapTypeDropdownXPower.FormattingEnabled = true;
+ this.CapTypeDropdownXPower.Location = new System.Drawing.Point(106, 780);
+ this.CapTypeDropdownXPower.Name = "CapTypeDropdownXPower";
+ this.CapTypeDropdownXPower.Size = new System.Drawing.Size(76, 21);
+ this.CapTypeDropdownXPower.TabIndex = 207;
+ //
+ // CapTypeActiveYLabelClassic
+ //
+ this.CapTypeActiveYLabelClassic.AutoSize = true;
+ this.CapTypeActiveYLabelClassic.Location = new System.Drawing.Point(415, 732);
+ this.CapTypeActiveYLabelClassic.Name = "CapTypeActiveYLabelClassic";
+ this.CapTypeActiveYLabelClassic.Size = new System.Drawing.Size(16, 13);
+ this.CapTypeActiveYLabelClassic.TabIndex = 206;
+ this.CapTypeActiveYLabelClassic.Text = "In";
+ //
+ // CapTypeActiveXLabelClassic
+ //
+ this.CapTypeActiveXLabelClassic.AutoSize = true;
+ this.CapTypeActiveXLabelClassic.Location = new System.Drawing.Point(200, 728);
+ this.CapTypeActiveXLabelClassic.Name = "CapTypeActiveXLabelClassic";
+ this.CapTypeActiveXLabelClassic.Size = new System.Drawing.Size(16, 13);
+ this.CapTypeActiveXLabelClassic.TabIndex = 205;
+ this.CapTypeActiveXLabelClassic.Text = "In";
+ //
+ // OutCapActiveYLabelClassic
+ //
+ this.OutCapActiveYLabelClassic.AutoSize = true;
+ this.OutCapActiveYLabelClassic.Location = new System.Drawing.Point(414, 757);
+ this.OutCapActiveYLabelClassic.Name = "OutCapActiveYLabelClassic";
+ this.OutCapActiveYLabelClassic.Size = new System.Drawing.Size(13, 13);
+ this.OutCapActiveYLabelClassic.TabIndex = 204;
+ this.OutCapActiveYLabelClassic.Text = "0";
+ //
+ // OutCapActiveXLabelClassic
+ //
+ this.OutCapActiveXLabelClassic.AutoSize = true;
+ this.OutCapActiveXLabelClassic.Location = new System.Drawing.Point(200, 757);
+ this.OutCapActiveXLabelClassic.Name = "OutCapActiveXLabelClassic";
+ this.OutCapActiveXLabelClassic.Size = new System.Drawing.Size(13, 13);
+ this.OutCapActiveXLabelClassic.TabIndex = 203;
+ this.OutCapActiveXLabelClassic.Text = "0";
+ //
+ // outCapLabelYClassic
+ //
+ this.outCapLabelYClassic.AutoSize = true;
+ this.outCapLabelYClassic.Location = new System.Drawing.Point(262, 757);
+ this.outCapLabelYClassic.Name = "outCapLabelYClassic";
+ this.outCapLabelYClassic.Size = new System.Drawing.Size(64, 13);
+ this.outCapLabelYClassic.TabIndex = 202;
+ this.outCapLabelYClassic.Text = "Cap: Output";
+ //
+ // outCapLabelXClassic
+ //
+ this.outCapLabelXClassic.AutoSize = true;
+ this.outCapLabelXClassic.Location = new System.Drawing.Point(35, 757);
+ this.outCapLabelXClassic.Name = "outCapLabelXClassic";
+ this.outCapLabelXClassic.Size = new System.Drawing.Size(64, 13);
+ this.outCapLabelXClassic.TabIndex = 201;
+ this.outCapLabelXClassic.Text = "Cap: Output";
+ //
+ // outCapBoxYClassic
+ //
+ this.outCapBoxYClassic.Location = new System.Drawing.Point(332, 754);
+ this.outCapBoxYClassic.Name = "outCapBoxYClassic";
+ this.outCapBoxYClassic.Size = new System.Drawing.Size(76, 20);
+ this.outCapBoxYClassic.TabIndex = 200;
+ //
+ // outCapBoxXClassic
+ //
+ this.outCapBoxXClassic.Location = new System.Drawing.Point(106, 754);
+ this.outCapBoxXClassic.Name = "outCapBoxXClassic";
+ this.outCapBoxXClassic.Size = new System.Drawing.Size(76, 20);
+ this.outCapBoxXClassic.TabIndex = 199;
+ //
+ // CapTypeLabelYClassic
+ //
+ this.CapTypeLabelYClassic.AutoSize = true;
+ this.CapTypeLabelYClassic.Location = new System.Drawing.Point(263, 729);
+ this.CapTypeLabelYClassic.Name = "CapTypeLabelYClassic";
+ this.CapTypeLabelYClassic.Size = new System.Drawing.Size(53, 13);
+ this.CapTypeLabelYClassic.TabIndex = 198;
+ this.CapTypeLabelYClassic.Text = "Cap Type";
+ //
+ // CapTypeLabelXClassic
+ //
+ this.CapTypeLabelXClassic.AutoSize = true;
+ this.CapTypeLabelXClassic.Location = new System.Drawing.Point(38, 728);
+ this.CapTypeLabelXClassic.Name = "CapTypeLabelXClassic";
+ this.CapTypeLabelXClassic.Size = new System.Drawing.Size(53, 13);
+ this.CapTypeLabelXClassic.TabIndex = 197;
+ this.CapTypeLabelXClassic.Text = "Cap Type";
+ //
+ // CapTypeDropdownYClassic
+ //
+ this.CapTypeDropdownYClassic.FormattingEnabled = true;
+ this.CapTypeDropdownYClassic.Location = new System.Drawing.Point(332, 725);
+ this.CapTypeDropdownYClassic.Name = "CapTypeDropdownYClassic";
+ this.CapTypeDropdownYClassic.Size = new System.Drawing.Size(76, 21);
+ this.CapTypeDropdownYClassic.TabIndex = 196;
+ //
+ // CapTypeDropdownXClassic
+ //
+ this.CapTypeDropdownXClassic.FormattingEnabled = true;
+ this.CapTypeDropdownXClassic.Location = new System.Drawing.Point(106, 726);
+ this.CapTypeDropdownXClassic.Name = "CapTypeDropdownXClassic";
+ this.CapTypeDropdownXClassic.Size = new System.Drawing.Size(76, 21);
+ this.CapTypeDropdownXClassic.TabIndex = 195;
+ //
+ // VertHorzRatioLabel
+ //
+ this.VertHorzRatioLabel.AutoSize = true;
+ this.VertHorzRatioLabel.Location = new System.Drawing.Point(28, 79);
+ this.VertHorzRatioLabel.Name = "VertHorzRatioLabel";
+ this.VertHorzRatioLabel.Size = new System.Drawing.Size(59, 13);
+ this.VertHorzRatioLabel.TabIndex = 194;
+ this.VertHorzRatioLabel.Text = "Y to X ratio";
+ //
+ // SmoothActiveYLabel
+ //
+ this.SmoothActiveYLabel.AutoSize = true;
+ this.SmoothActiveYLabel.Location = new System.Drawing.Point(414, 704);
+ this.SmoothActiveYLabel.Name = "SmoothActiveYLabel";
+ this.SmoothActiveYLabel.Size = new System.Drawing.Size(13, 13);
+ this.SmoothActiveYLabel.TabIndex = 193;
+ this.SmoothActiveYLabel.Text = "0";
+ //
+ // smoothLabelY
+ //
+ this.smoothLabelY.AutoSize = true;
+ this.smoothLabelY.Location = new System.Drawing.Point(266, 704);
+ this.smoothLabelY.Name = "smoothLabelY";
+ this.smoothLabelY.Size = new System.Drawing.Size(43, 13);
+ this.smoothLabelY.TabIndex = 192;
+ this.smoothLabelY.Text = "Smooth";
+ //
+ // SmoothActiveXLabel
+ //
+ this.SmoothActiveXLabel.AutoSize = true;
+ this.SmoothActiveXLabel.Location = new System.Drawing.Point(200, 704);
+ this.SmoothActiveXLabel.Name = "SmoothActiveXLabel";
+ this.SmoothActiveXLabel.Size = new System.Drawing.Size(13, 13);
+ this.SmoothActiveXLabel.TabIndex = 191;
+ this.SmoothActiveXLabel.Text = "0";
+ //
+ // smoothLabelX
+ //
+ this.smoothLabelX.AutoSize = true;
+ this.smoothLabelX.Location = new System.Drawing.Point(38, 704);
+ this.smoothLabelX.Name = "smoothLabelX";
+ this.smoothLabelX.Size = new System.Drawing.Size(43, 13);
+ this.smoothLabelX.TabIndex = 190;
+ this.smoothLabelX.Text = "Smooth";
+ //
+ // smoothBoxY
+ //
+ this.smoothBoxY.Location = new System.Drawing.Point(332, 698);
+ this.smoothBoxY.Name = "smoothBoxY";
+ this.smoothBoxY.Size = new System.Drawing.Size(76, 20);
+ this.smoothBoxY.TabIndex = 189;
+ //
+ // smoothBoxX
+ //
+ this.smoothBoxX.Location = new System.Drawing.Point(106, 699);
+ this.smoothBoxX.Name = "smoothBoxX";
+ this.smoothBoxX.Size = new System.Drawing.Size(76, 20);
+ this.smoothBoxX.TabIndex = 188;
+ //
// GrowthRateActiveYLabel
//
this.GrowthRateActiveYLabel.AutoSize = true;
- this.GrowthRateActiveYLabel.Location = new System.Drawing.Point(417, 647);
+ this.GrowthRateActiveYLabel.Location = new System.Drawing.Point(417, 674);
this.GrowthRateActiveYLabel.Name = "GrowthRateActiveYLabel";
this.GrowthRateActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.GrowthRateActiveYLabel.TabIndex = 187;
@@ -370,7 +769,7 @@ namespace grapher
// GrowthRateActiveXLabel
//
this.GrowthRateActiveXLabel.AutoSize = true;
- this.GrowthRateActiveXLabel.Location = new System.Drawing.Point(200, 647);
+ this.GrowthRateActiveXLabel.Location = new System.Drawing.Point(200, 674);
this.GrowthRateActiveXLabel.Name = "GrowthRateActiveXLabel";
this.GrowthRateActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.GrowthRateActiveXLabel.TabIndex = 186;
@@ -379,7 +778,7 @@ namespace grapher
// DecayRateActiveYLabel
//
this.DecayRateActiveYLabel.AutoSize = true;
- this.DecayRateActiveYLabel.Location = new System.Drawing.Point(417, 626);
+ this.DecayRateActiveYLabel.Location = new System.Drawing.Point(417, 653);
this.DecayRateActiveYLabel.Name = "DecayRateActiveYLabel";
this.DecayRateActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.DecayRateActiveYLabel.TabIndex = 185;
@@ -388,7 +787,7 @@ namespace grapher
// DecayRateActiveXLabel
//
this.DecayRateActiveXLabel.AutoSize = true;
- this.DecayRateActiveXLabel.Location = new System.Drawing.Point(200, 622);
+ this.DecayRateActiveXLabel.Location = new System.Drawing.Point(200, 649);
this.DecayRateActiveXLabel.Name = "DecayRateActiveXLabel";
this.DecayRateActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.DecayRateActiveXLabel.TabIndex = 184;
@@ -397,7 +796,7 @@ namespace grapher
// growthRateLabelY
//
this.growthRateLabelY.AutoSize = true;
- this.growthRateLabelY.Location = new System.Drawing.Point(263, 648);
+ this.growthRateLabelY.Location = new System.Drawing.Point(263, 675);
this.growthRateLabelY.Name = "growthRateLabelY";
this.growthRateLabelY.Size = new System.Drawing.Size(67, 13);
this.growthRateLabelY.TabIndex = 183;
@@ -406,7 +805,7 @@ namespace grapher
// growthRateLabelX
//
this.growthRateLabelX.AutoSize = true;
- this.growthRateLabelX.Location = new System.Drawing.Point(37, 648);
+ this.growthRateLabelX.Location = new System.Drawing.Point(37, 675);
this.growthRateLabelX.Name = "growthRateLabelX";
this.growthRateLabelX.Size = new System.Drawing.Size(67, 13);
this.growthRateLabelX.TabIndex = 182;
@@ -415,7 +814,7 @@ namespace grapher
// decayRateLabelY
//
this.decayRateLabelY.AutoSize = true;
- this.decayRateLabelY.Location = new System.Drawing.Point(262, 622);
+ this.decayRateLabelY.Location = new System.Drawing.Point(262, 649);
this.decayRateLabelY.Name = "decayRateLabelY";
this.decayRateLabelY.Size = new System.Drawing.Size(64, 13);
this.decayRateLabelY.TabIndex = 181;
@@ -424,7 +823,7 @@ namespace grapher
// decayRateLabelX
//
this.decayRateLabelX.AutoSize = true;
- this.decayRateLabelX.Location = new System.Drawing.Point(37, 622);
+ this.decayRateLabelX.Location = new System.Drawing.Point(35, 649);
this.decayRateLabelX.Name = "decayRateLabelX";
this.decayRateLabelX.Size = new System.Drawing.Size(64, 13);
this.decayRateLabelX.TabIndex = 180;
@@ -432,28 +831,28 @@ namespace grapher
//
// growthRateBoxY
//
- this.growthRateBoxY.Location = new System.Drawing.Point(332, 644);
+ this.growthRateBoxY.Location = new System.Drawing.Point(332, 671);
this.growthRateBoxY.Name = "growthRateBoxY";
this.growthRateBoxY.Size = new System.Drawing.Size(76, 20);
this.growthRateBoxY.TabIndex = 179;
//
// growthRateBoxX
//
- this.growthRateBoxX.Location = new System.Drawing.Point(106, 645);
+ this.growthRateBoxX.Location = new System.Drawing.Point(106, 672);
this.growthRateBoxX.Name = "growthRateBoxX";
this.growthRateBoxX.Size = new System.Drawing.Size(76, 20);
this.growthRateBoxX.TabIndex = 178;
//
// decayRateBoxY
//
- this.decayRateBoxY.Location = new System.Drawing.Point(332, 619);
+ this.decayRateBoxY.Location = new System.Drawing.Point(332, 646);
this.decayRateBoxY.Name = "decayRateBoxY";
this.decayRateBoxY.Size = new System.Drawing.Size(76, 20);
this.decayRateBoxY.TabIndex = 177;
//
// decayRateBoxX
//
- this.decayRateBoxX.Location = new System.Drawing.Point(106, 619);
+ this.decayRateBoxX.Location = new System.Drawing.Point(106, 646);
this.decayRateBoxX.Name = "decayRateBoxX";
this.decayRateBoxX.Size = new System.Drawing.Size(76, 20);
this.decayRateBoxX.TabIndex = 176;
@@ -461,7 +860,7 @@ namespace grapher
// PowerClassicActiveYLabel
//
this.PowerClassicActiveYLabel.AutoSize = true;
- this.PowerClassicActiveYLabel.Location = new System.Drawing.Point(417, 599);
+ this.PowerClassicActiveYLabel.Location = new System.Drawing.Point(417, 626);
this.PowerClassicActiveYLabel.Name = "PowerClassicActiveYLabel";
this.PowerClassicActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.PowerClassicActiveYLabel.TabIndex = 175;
@@ -470,7 +869,7 @@ namespace grapher
// PowerClassicActiveXLabel
//
this.PowerClassicActiveXLabel.AutoSize = true;
- this.PowerClassicActiveXLabel.Location = new System.Drawing.Point(200, 599);
+ this.PowerClassicActiveXLabel.Location = new System.Drawing.Point(200, 626);
this.PowerClassicActiveXLabel.Name = "PowerClassicActiveXLabel";
this.PowerClassicActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.PowerClassicActiveXLabel.TabIndex = 174;
@@ -479,7 +878,7 @@ namespace grapher
// powerLabelY
//
this.powerLabelY.AutoSize = true;
- this.powerLabelY.Location = new System.Drawing.Point(263, 599);
+ this.powerLabelY.Location = new System.Drawing.Point(263, 626);
this.powerLabelY.Name = "powerLabelY";
this.powerLabelY.Size = new System.Drawing.Size(37, 13);
this.powerLabelY.TabIndex = 173;
@@ -488,7 +887,7 @@ namespace grapher
// powerLabelX
//
this.powerLabelX.AutoSize = true;
- this.powerLabelX.Location = new System.Drawing.Point(35, 595);
+ this.powerLabelX.Location = new System.Drawing.Point(35, 622);
this.powerLabelX.Name = "powerLabelX";
this.powerLabelX.Size = new System.Drawing.Size(37, 13);
this.powerLabelX.TabIndex = 172;
@@ -496,21 +895,21 @@ namespace grapher
//
// powerBoxY
//
- this.powerBoxY.Location = new System.Drawing.Point(332, 594);
+ this.powerBoxY.Location = new System.Drawing.Point(332, 621);
this.powerBoxY.Name = "powerBoxY";
this.powerBoxY.Size = new System.Drawing.Size(76, 20);
this.powerBoxY.TabIndex = 171;
//
// powerBoxX
//
- this.powerBoxX.Location = new System.Drawing.Point(106, 595);
+ this.powerBoxX.Location = new System.Drawing.Point(106, 622);
this.powerBoxX.Name = "powerBoxX";
this.powerBoxX.Size = new System.Drawing.Size(76, 20);
this.powerBoxX.TabIndex = 170;
//
// YLutActiveValuesBox
//
- this.YLutActiveValuesBox.Location = new System.Drawing.Point(397, 369);
+ this.YLutActiveValuesBox.Location = new System.Drawing.Point(397, 396);
this.YLutActiveValuesBox.Name = "YLutActiveValuesBox";
this.YLutActiveValuesBox.Size = new System.Drawing.Size(73, 72);
this.YLutActiveValuesBox.TabIndex = 169;
@@ -518,7 +917,7 @@ namespace grapher
//
// XLutActiveValuesBox
//
- this.XLutActiveValuesBox.Location = new System.Drawing.Point(317, 369);
+ this.XLutActiveValuesBox.Location = new System.Drawing.Point(317, 396);
this.XLutActiveValuesBox.Name = "XLutActiveValuesBox";
this.XLutActiveValuesBox.Size = new System.Drawing.Size(68, 72);
this.XLutActiveValuesBox.TabIndex = 168;
@@ -527,7 +926,7 @@ namespace grapher
// LutApplyActiveYLabel
//
this.LutApplyActiveYLabel.AutoSize = true;
- this.LutApplyActiveYLabel.Location = new System.Drawing.Point(417, 565);
+ this.LutApplyActiveYLabel.Location = new System.Drawing.Point(417, 592);
this.LutApplyActiveYLabel.Name = "LutApplyActiveYLabel";
this.LutApplyActiveYLabel.Size = new System.Drawing.Size(35, 13);
this.LutApplyActiveYLabel.TabIndex = 167;
@@ -536,7 +935,7 @@ namespace grapher
// YLutApplyDropdown
//
this.YLutApplyDropdown.FormattingEnabled = true;
- this.YLutApplyDropdown.Location = new System.Drawing.Point(397, 527);
+ this.YLutApplyDropdown.Location = new System.Drawing.Point(397, 554);
this.YLutApplyDropdown.Name = "YLutApplyDropdown";
this.YLutApplyDropdown.Size = new System.Drawing.Size(73, 21);
this.YLutApplyDropdown.TabIndex = 166;
@@ -544,7 +943,7 @@ namespace grapher
// XLutApplyDropdown
//
this.XLutApplyDropdown.FormattingEnabled = true;
- this.XLutApplyDropdown.Location = new System.Drawing.Point(320, 527);
+ this.XLutApplyDropdown.Location = new System.Drawing.Point(320, 554);
this.XLutApplyDropdown.Name = "XLutApplyDropdown";
this.XLutApplyDropdown.Size = new System.Drawing.Size(65, 21);
this.XLutApplyDropdown.TabIndex = 165;
@@ -552,7 +951,7 @@ namespace grapher
// LutApplyActiveXLabel
//
this.LutApplyActiveXLabel.AutoSize = true;
- this.LutApplyActiveXLabel.Location = new System.Drawing.Point(200, 565);
+ this.LutApplyActiveXLabel.Location = new System.Drawing.Point(200, 592);
this.LutApplyActiveXLabel.Name = "LutApplyActiveXLabel";
this.LutApplyActiveXLabel.Size = new System.Drawing.Size(35, 13);
this.LutApplyActiveXLabel.TabIndex = 164;
@@ -561,7 +960,7 @@ namespace grapher
// YLutApplyLabel
//
this.YLutApplyLabel.AutoSize = true;
- this.YLutApplyLabel.Location = new System.Drawing.Point(397, 510);
+ this.YLutApplyLabel.Location = new System.Drawing.Point(397, 537);
this.YLutApplyLabel.Name = "YLutApplyLabel";
this.YLutApplyLabel.Size = new System.Drawing.Size(47, 13);
this.YLutApplyLabel.TabIndex = 163;
@@ -570,7 +969,7 @@ namespace grapher
// XLutApplyLabel
//
this.XLutApplyLabel.AutoSize = true;
- this.XLutApplyLabel.Location = new System.Drawing.Point(317, 511);
+ this.XLutApplyLabel.Location = new System.Drawing.Point(317, 538);
this.XLutApplyLabel.Name = "XLutApplyLabel";
this.XLutApplyLabel.Size = new System.Drawing.Size(47, 13);
this.XLutApplyLabel.TabIndex = 162;
@@ -578,7 +977,7 @@ namespace grapher
//
// YLutPointsBox
//
- this.YLutPointsBox.Location = new System.Drawing.Point(397, 447);
+ this.YLutPointsBox.Location = new System.Drawing.Point(397, 474);
this.YLutPointsBox.Name = "YLutPointsBox";
this.YLutPointsBox.Size = new System.Drawing.Size(73, 57);
this.YLutPointsBox.TabIndex = 161;
@@ -586,7 +985,7 @@ namespace grapher
//
// XLutPointsBox
//
- this.XLutPointsBox.Location = new System.Drawing.Point(317, 447);
+ this.XLutPointsBox.Location = new System.Drawing.Point(317, 474);
this.XLutPointsBox.Name = "XLutPointsBox";
this.XLutPointsBox.Size = new System.Drawing.Size(68, 57);
this.XLutPointsBox.TabIndex = 160;
@@ -595,7 +994,7 @@ namespace grapher
// gainSwitchActiveLabelY
//
this.gainSwitchActiveLabelY.AutoSize = true;
- this.gainSwitchActiveLabelY.Location = new System.Drawing.Point(417, 95);
+ this.gainSwitchActiveLabelY.Location = new System.Drawing.Point(417, 122);
this.gainSwitchActiveLabelY.Name = "gainSwitchActiveLabelY";
this.gainSwitchActiveLabelY.Size = new System.Drawing.Size(29, 13);
this.gainSwitchActiveLabelY.TabIndex = 157;
@@ -604,7 +1003,7 @@ namespace grapher
// gainSwitchActiveLabelX
//
this.gainSwitchActiveLabelX.AutoSize = true;
- this.gainSwitchActiveLabelX.Location = new System.Drawing.Point(200, 96);
+ this.gainSwitchActiveLabelX.Location = new System.Drawing.Point(200, 123);
this.gainSwitchActiveLabelX.Name = "gainSwitchActiveLabelX";
this.gainSwitchActiveLabelX.Size = new System.Drawing.Size(29, 13);
this.gainSwitchActiveLabelX.TabIndex = 156;
@@ -615,7 +1014,7 @@ namespace grapher
this.gainSwitchY.AutoSize = true;
this.gainSwitchY.Checked = true;
this.gainSwitchY.CheckState = System.Windows.Forms.CheckState.Checked;
- this.gainSwitchY.Location = new System.Drawing.Point(283, 116);
+ this.gainSwitchY.Location = new System.Drawing.Point(283, 143);
this.gainSwitchY.Name = "gainSwitchY";
this.gainSwitchY.Size = new System.Drawing.Size(48, 17);
this.gainSwitchY.TabIndex = 155;
@@ -627,7 +1026,7 @@ namespace grapher
this.gainSwitchX.AutoSize = true;
this.gainSwitchX.Checked = true;
this.gainSwitchX.CheckState = System.Windows.Forms.CheckState.Checked;
- this.gainSwitchX.Location = new System.Drawing.Point(38, 116);
+ this.gainSwitchX.Location = new System.Drawing.Point(38, 143);
this.gainSwitchX.Name = "gainSwitchX";
this.gainSwitchX.Size = new System.Drawing.Size(48, 17);
this.gainSwitchX.TabIndex = 154;
@@ -637,7 +1036,7 @@ namespace grapher
// LUTTextLabelY
//
this.LUTTextLabelY.AutoSize = true;
- this.LUTTextLabelY.Location = new System.Drawing.Point(266, 350);
+ this.LUTTextLabelY.Location = new System.Drawing.Point(266, 377);
this.LUTTextLabelY.Name = "LUTTextLabelY";
this.LUTTextLabelY.Size = new System.Drawing.Size(52, 13);
this.LUTTextLabelY.TabIndex = 153;
@@ -646,7 +1045,7 @@ namespace grapher
// LUTTextLabelX
//
this.LUTTextLabelX.AutoSize = true;
- this.LUTTextLabelX.Location = new System.Drawing.Point(38, 350);
+ this.LUTTextLabelX.Location = new System.Drawing.Point(38, 377);
this.LUTTextLabelX.Name = "LUTTextLabelX";
this.LUTTextLabelX.Size = new System.Drawing.Size(52, 13);
this.LUTTextLabelX.TabIndex = 152;
@@ -655,7 +1054,7 @@ namespace grapher
// FakeBox
//
this.FakeBox.AutoSize = true;
- this.FakeBox.Location = new System.Drawing.Point(31, 538);
+ this.FakeBox.Location = new System.Drawing.Point(31, 565);
this.FakeBox.Name = "FakeBox";
this.FakeBox.Size = new System.Drawing.Size(47, 17);
this.FakeBox.TabIndex = 151;
@@ -683,7 +1082,7 @@ namespace grapher
this.DirectionalityPanel.Controls.Add(this.DomainBoxY);
this.DirectionalityPanel.Controls.Add(this.DomainBoxX);
this.DirectionalityPanel.Controls.Add(this.DirectionalityLabel);
- this.DirectionalityPanel.Location = new System.Drawing.Point(12, 369);
+ this.DirectionalityPanel.Location = new System.Drawing.Point(12, 396);
this.DirectionalityPanel.Name = "DirectionalityPanel";
this.DirectionalityPanel.Size = new System.Drawing.Size(298, 135);
this.DirectionalityPanel.TabIndex = 150;
@@ -856,7 +1255,7 @@ namespace grapher
//
// toggleButton
//
- this.toggleButton.Location = new System.Drawing.Point(211, 534);
+ this.toggleButton.Location = new System.Drawing.Point(211, 561);
this.toggleButton.Name = "toggleButton";
this.toggleButton.Size = new System.Drawing.Size(104, 24);
this.toggleButton.TabIndex = 112;
@@ -866,7 +1265,7 @@ namespace grapher
// scaleLabelY
//
this.scaleLabelY.AutoSize = true;
- this.scaleLabelY.Location = new System.Drawing.Point(263, 333);
+ this.scaleLabelY.Location = new System.Drawing.Point(263, 360);
this.scaleLabelY.Name = "scaleLabelY";
this.scaleLabelY.Size = new System.Drawing.Size(34, 13);
this.scaleLabelY.TabIndex = 149;
@@ -875,7 +1274,7 @@ namespace grapher
// ScaleActiveYLabel
//
this.ScaleActiveYLabel.AutoSize = true;
- this.ScaleActiveYLabel.Location = new System.Drawing.Point(414, 333);
+ this.ScaleActiveYLabel.Location = new System.Drawing.Point(414, 360);
this.ScaleActiveYLabel.Name = "ScaleActiveYLabel";
this.ScaleActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.ScaleActiveYLabel.TabIndex = 148;
@@ -883,7 +1282,7 @@ namespace grapher
//
// scaleBoxY
//
- this.scaleBoxY.Location = new System.Drawing.Point(332, 330);
+ this.scaleBoxY.Location = new System.Drawing.Point(332, 357);
this.scaleBoxY.Name = "scaleBoxY";
this.scaleBoxY.Size = new System.Drawing.Size(76, 20);
this.scaleBoxY.TabIndex = 102;
@@ -891,7 +1290,7 @@ namespace grapher
// ScaleActiveXLabel
//
this.ScaleActiveXLabel.AutoSize = true;
- this.ScaleActiveXLabel.Location = new System.Drawing.Point(197, 333);
+ this.ScaleActiveXLabel.Location = new System.Drawing.Point(197, 360);
this.ScaleActiveXLabel.Name = "ScaleActiveXLabel";
this.ScaleActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.ScaleActiveXLabel.TabIndex = 147;
@@ -900,7 +1299,7 @@ namespace grapher
// scaleLabelX
//
this.scaleLabelX.AutoSize = true;
- this.scaleLabelX.Location = new System.Drawing.Point(37, 333);
+ this.scaleLabelX.Location = new System.Drawing.Point(37, 360);
this.scaleLabelX.Name = "scaleLabelX";
this.scaleLabelX.Size = new System.Drawing.Size(34, 13);
this.scaleLabelX.TabIndex = 146;
@@ -909,7 +1308,7 @@ namespace grapher
//
// scaleBoxX
//
- this.scaleBoxX.Location = new System.Drawing.Point(106, 330);
+ this.scaleBoxX.Location = new System.Drawing.Point(106, 357);
this.scaleBoxX.Name = "scaleBoxX";
this.scaleBoxX.Size = new System.Drawing.Size(76, 20);
this.scaleBoxX.TabIndex = 88;
@@ -917,7 +1316,7 @@ namespace grapher
// expLabelY
//
this.expLabelY.AutoSize = true;
- this.expLabelY.Location = new System.Drawing.Point(263, 276);
+ this.expLabelY.Location = new System.Drawing.Point(263, 303);
this.expLabelY.Name = "expLabelY";
this.expLabelY.Size = new System.Drawing.Size(52, 13);
this.expLabelY.TabIndex = 145;
@@ -926,7 +1325,7 @@ namespace grapher
// ExpActiveYLabel
//
this.ExpActiveYLabel.AutoSize = true;
- this.ExpActiveYLabel.Location = new System.Drawing.Point(414, 276);
+ this.ExpActiveYLabel.Location = new System.Drawing.Point(414, 303);
this.ExpActiveYLabel.Name = "ExpActiveYLabel";
this.ExpActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.ExpActiveYLabel.TabIndex = 144;
@@ -934,7 +1333,7 @@ namespace grapher
//
// expBoxY
//
- this.expBoxY.Location = new System.Drawing.Point(332, 273);
+ this.expBoxY.Location = new System.Drawing.Point(332, 300);
this.expBoxY.Name = "expBoxY";
this.expBoxY.Size = new System.Drawing.Size(76, 20);
this.expBoxY.TabIndex = 109;
@@ -942,7 +1341,7 @@ namespace grapher
// ExpActiveXLabel
//
this.ExpActiveXLabel.AutoSize = true;
- this.ExpActiveXLabel.Location = new System.Drawing.Point(197, 276);
+ this.ExpActiveXLabel.Location = new System.Drawing.Point(197, 303);
this.ExpActiveXLabel.Name = "ExpActiveXLabel";
this.ExpActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.ExpActiveXLabel.TabIndex = 143;
@@ -951,7 +1350,7 @@ namespace grapher
// expLabelX
//
this.expLabelX.AutoSize = true;
- this.expLabelX.Location = new System.Drawing.Point(37, 276);
+ this.expLabelX.Location = new System.Drawing.Point(37, 303);
this.expLabelX.Name = "expLabelX";
this.expLabelX.Size = new System.Drawing.Size(52, 13);
this.expLabelX.TabIndex = 142;
@@ -960,7 +1359,7 @@ namespace grapher
//
// expBoxX
//
- this.expBoxX.Location = new System.Drawing.Point(106, 273);
+ this.expBoxX.Location = new System.Drawing.Point(106, 300);
this.expBoxX.Name = "expBoxX";
this.expBoxX.Size = new System.Drawing.Size(76, 20);
this.expBoxX.TabIndex = 95;
@@ -977,7 +1376,7 @@ namespace grapher
// AccelTypeActiveLabelY
//
this.AccelTypeActiveLabelY.AutoSize = true;
- this.AccelTypeActiveLabelY.Location = new System.Drawing.Point(414, 116);
+ this.AccelTypeActiveLabelY.Location = new System.Drawing.Point(414, 143);
this.AccelTypeActiveLabelY.Name = "AccelTypeActiveLabelY";
this.AccelTypeActiveLabelY.Size = new System.Drawing.Size(66, 13);
this.AccelTypeActiveLabelY.TabIndex = 140;
@@ -986,7 +1385,7 @@ namespace grapher
// OptionSetYTitle
//
this.OptionSetYTitle.AutoSize = true;
- this.OptionSetYTitle.Location = new System.Drawing.Point(360, 97);
+ this.OptionSetYTitle.Location = new System.Drawing.Point(360, 124);
this.OptionSetYTitle.Name = "OptionSetYTitle";
this.OptionSetYTitle.Size = new System.Drawing.Size(14, 13);
this.OptionSetYTitle.TabIndex = 139;
@@ -995,7 +1394,7 @@ namespace grapher
// OptionSetXTitle
//
this.OptionSetXTitle.AutoSize = true;
- this.OptionSetXTitle.Location = new System.Drawing.Point(143, 97);
+ this.OptionSetXTitle.Location = new System.Drawing.Point(143, 124);
this.OptionSetXTitle.Name = "OptionSetXTitle";
this.OptionSetXTitle.Size = new System.Drawing.Size(14, 13);
this.OptionSetXTitle.TabIndex = 138;
@@ -1004,7 +1403,7 @@ namespace grapher
// constantThreeLabelY
//
this.constantThreeLabelY.AutoSize = true;
- this.constantThreeLabelY.Location = new System.Drawing.Point(263, 303);
+ this.constantThreeLabelY.Location = new System.Drawing.Point(263, 330);
this.constantThreeLabelY.Name = "constantThreeLabelY";
this.constantThreeLabelY.Size = new System.Drawing.Size(47, 13);
this.constantThreeLabelY.TabIndex = 137;
@@ -1013,43 +1412,61 @@ namespace grapher
// limitLabelY
//
this.limitLabelY.AutoSize = true;
- this.limitLabelY.Location = new System.Drawing.Point(263, 247);
+ this.limitLabelY.Location = new System.Drawing.Point(263, 274);
this.limitLabelY.Name = "limitLabelY";
this.limitLabelY.Size = new System.Drawing.Size(28, 13);
this.limitLabelY.TabIndex = 136;
this.limitLabelY.Text = "Limit";
//
- // offsetLabelY
+ // inputJumpLabelY
+ //
+ this.inputJumpLabelY.AutoSize = true;
+ this.inputJumpLabelY.Location = new System.Drawing.Point(263, 248);
+ this.inputJumpLabelY.Name = "inputJumpLabelY";
+ this.inputJumpLabelY.Size = new System.Drawing.Size(31, 13);
+ this.inputJumpLabelY.TabIndex = 135;
+ this.inputJumpLabelY.Text = "Input";
+ //
+ // outputJumpLabelY
//
- this.offsetLabelY.AutoSize = true;
- this.offsetLabelY.Location = new System.Drawing.Point(263, 221);
- this.offsetLabelY.Name = "offsetLabelY";
- this.offsetLabelY.Size = new System.Drawing.Size(35, 13);
- this.offsetLabelY.TabIndex = 135;
- this.offsetLabelY.Text = "Offset";
+ this.outputJumpLabelY.AutoSize = true;
+ this.outputJumpLabelY.Location = new System.Drawing.Point(263, 248);
+ this.outputJumpLabelY.Name = "outputJumpLabelY";
+ this.outputJumpLabelY.Size = new System.Drawing.Size(39, 13);
+ this.outputJumpLabelY.TabIndex = 135;
+ this.outputJumpLabelY.Text = "Output";
//
- // weightLabelY
+ // inputOffsetLabelY
//
- this.weightLabelY.AutoSize = true;
- this.weightLabelY.Location = new System.Drawing.Point(263, 195);
- this.weightLabelY.Name = "weightLabelY";
- this.weightLabelY.Size = new System.Drawing.Size(41, 13);
- this.weightLabelY.TabIndex = 134;
- this.weightLabelY.Text = "Weight";
+ this.inputOffsetLabelY.AutoSize = true;
+ this.inputOffsetLabelY.Location = new System.Drawing.Point(263, 248);
+ this.inputOffsetLabelY.Name = "inputOffsetLabelY";
+ this.inputOffsetLabelY.Size = new System.Drawing.Size(62, 13);
+ this.inputOffsetLabelY.TabIndex = 135;
+ this.inputOffsetLabelY.Text = "Input Offset";
//
- // capLabelY
+ // outputOffsetLabelY
//
- this.capLabelY.AutoSize = true;
- this.capLabelY.Location = new System.Drawing.Point(263, 169);
- this.capLabelY.Name = "capLabelY";
- this.capLabelY.Size = new System.Drawing.Size(26, 13);
- this.capLabelY.TabIndex = 133;
- this.capLabelY.Text = "Cap";
+ this.outputOffsetLabelY.AutoSize = true;
+ this.outputOffsetLabelY.Location = new System.Drawing.Point(263, 248);
+ this.outputOffsetLabelY.Name = "outputOffsetLabelY";
+ this.outputOffsetLabelY.Size = new System.Drawing.Size(70, 13);
+ this.outputOffsetLabelY.TabIndex = 135;
+ this.outputOffsetLabelY.Text = "Output Offset";
+ //
+ // inCapLabelYClassic
+ //
+ this.inCapLabelYClassic.AutoSize = true;
+ this.inCapLabelYClassic.Location = new System.Drawing.Point(263, 196);
+ this.inCapLabelYClassic.Name = "inCapLabelYClassic";
+ this.inCapLabelYClassic.Size = new System.Drawing.Size(56, 13);
+ this.inCapLabelYClassic.TabIndex = 133;
+ this.inCapLabelYClassic.Text = "Cap: Input";
//
// constantOneLabelY
//
this.constantOneLabelY.AutoSize = true;
- this.constantOneLabelY.Location = new System.Drawing.Point(263, 143);
+ this.constantOneLabelY.Location = new System.Drawing.Point(263, 170);
this.constantOneLabelY.Name = "constantOneLabelY";
this.constantOneLabelY.Size = new System.Drawing.Size(66, 13);
this.constantOneLabelY.TabIndex = 132;
@@ -1060,7 +1477,7 @@ namespace grapher
this.ByComponentXYLock.AutoSize = true;
this.ByComponentXYLock.Checked = true;
this.ByComponentXYLock.CheckState = System.Windows.Forms.CheckState.Checked;
- this.ByComponentXYLock.Location = new System.Drawing.Point(283, 96);
+ this.ByComponentXYLock.Location = new System.Drawing.Point(283, 123);
this.ByComponentXYLock.Name = "ByComponentXYLock";
this.ByComponentXYLock.Size = new System.Drawing.Size(15, 14);
this.ByComponentXYLock.TabIndex = 98;
@@ -1069,7 +1486,7 @@ namespace grapher
// MidpointActiveYLabel
//
this.MidpointActiveYLabel.AutoSize = true;
- this.MidpointActiveYLabel.Location = new System.Drawing.Point(414, 303);
+ this.MidpointActiveYLabel.Location = new System.Drawing.Point(414, 330);
this.MidpointActiveYLabel.Name = "MidpointActiveYLabel";
this.MidpointActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.MidpointActiveYLabel.TabIndex = 131;
@@ -1078,25 +1495,52 @@ namespace grapher
// LimitActiveYLabel
//
this.LimitActiveYLabel.AutoSize = true;
- this.LimitActiveYLabel.Location = new System.Drawing.Point(414, 247);
+ this.LimitActiveYLabel.Location = new System.Drawing.Point(414, 274);
this.LimitActiveYLabel.Name = "LimitActiveYLabel";
this.LimitActiveYLabel.Size = new System.Drawing.Size(13, 13);
this.LimitActiveYLabel.TabIndex = 130;
this.LimitActiveYLabel.Text = "0";
//
- // OffsetActiveYLabel
+ // InputJumpActiveYLabel
+ //
+ this.InputJumpActiveYLabel.AutoSize = true;
+ this.InputJumpActiveYLabel.Location = new System.Drawing.Point(414, 248);
+ this.InputJumpActiveYLabel.Name = "InputJumpActiveYLabel";
+ this.InputJumpActiveYLabel.Size = new System.Drawing.Size(13, 13);
+ this.InputJumpActiveYLabel.TabIndex = 129;
+ this.InputJumpActiveYLabel.Text = "0";
+ //
+ // OutputJumpActiveYLabel
//
- this.OffsetActiveYLabel.AutoSize = true;
- this.OffsetActiveYLabel.Location = new System.Drawing.Point(414, 221);
- this.OffsetActiveYLabel.Name = "OffsetActiveYLabel";
- this.OffsetActiveYLabel.Size = new System.Drawing.Size(13, 13);
- this.OffsetActiveYLabel.TabIndex = 129;
- this.OffsetActiveYLabel.Text = "0";
+ this.OutputJumpActiveYLabel.AutoSize = true;
+ this.OutputJumpActiveYLabel.Location = new System.Drawing.Point(414, 248);
+ this.OutputJumpActiveYLabel.Name = "OutputJumpActiveYLabel";
+ this.OutputJumpActiveYLabel.Size = new System.Drawing.Size(13, 13);
+ this.OutputJumpActiveYLabel.TabIndex = 129;
+ this.OutputJumpActiveYLabel.Text = "0";
+ //
+ // InputOffsetActiveYLabel
+ //
+ this.InputOffsetActiveYLabel.AutoSize = true;
+ this.InputOffsetActiveYLabel.Location = new System.Drawing.Point(414, 248);
+ this.InputOffsetActiveYLabel.Name = "InputOffsetActiveYLabel";
+ this.InputOffsetActiveYLabel.Size = new System.Drawing.Size(13, 13);
+ this.InputOffsetActiveYLabel.TabIndex = 129;
+ this.InputOffsetActiveYLabel.Text = "0";
+ //
+ // OutputOffsetActiveYLabel
+ //
+ this.OutputOffsetActiveYLabel.AutoSize = true;
+ this.OutputOffsetActiveYLabel.Location = new System.Drawing.Point(414, 248);
+ this.OutputOffsetActiveYLabel.Name = "OutputOffsetActiveYLabel";
+ this.OutputOffsetActiveYLabel.Size = new System.Drawing.Size(13, 13);
+ this.OutputOffsetActiveYLabel.TabIndex = 129;
+ this.OutputOffsetActiveYLabel.Text = "0";
//
// AccelerationActiveLabelY
//
this.AccelerationActiveLabelY.AutoSize = true;
- this.AccelerationActiveLabelY.Location = new System.Drawing.Point(414, 143);
+ this.AccelerationActiveLabelY.Location = new System.Drawing.Point(414, 170);
this.AccelerationActiveLabelY.Name = "AccelerationActiveLabelY";
this.AccelerationActiveLabelY.Size = new System.Drawing.Size(13, 13);
this.AccelerationActiveLabelY.TabIndex = 128;
@@ -1105,7 +1549,7 @@ namespace grapher
// accelTypeDropY
//
this.accelTypeDropY.FormattingEnabled = true;
- this.accelTypeDropY.Location = new System.Drawing.Point(332, 113);
+ this.accelTypeDropY.Location = new System.Drawing.Point(332, 138);
this.accelTypeDropY.Name = "accelTypeDropY";
this.accelTypeDropY.Size = new System.Drawing.Size(76, 21);
this.accelTypeDropY.TabIndex = 99;
@@ -1113,28 +1557,49 @@ namespace grapher
//
// midpointBoxY
//
- this.midpointBoxY.Location = new System.Drawing.Point(332, 300);
+ this.midpointBoxY.Location = new System.Drawing.Point(332, 327);
this.midpointBoxY.Name = "midpointBoxY";
this.midpointBoxY.Size = new System.Drawing.Size(76, 20);
this.midpointBoxY.TabIndex = 110;
//
// limitBoxY
//
- this.limitBoxY.Location = new System.Drawing.Point(332, 244);
+ this.limitBoxY.Location = new System.Drawing.Point(332, 271);
this.limitBoxY.Name = "limitBoxY";
this.limitBoxY.Size = new System.Drawing.Size(76, 20);
this.limitBoxY.TabIndex = 108;
//
- // offsetBoxY
+ // inputJumpBoxY
+ //
+ this.inputJumpBoxY.Location = new System.Drawing.Point(332, 245);
+ this.inputJumpBoxY.Name = "inputJumpBoxY";
+ this.inputJumpBoxY.Size = new System.Drawing.Size(76, 20);
+ this.inputJumpBoxY.TabIndex = 106;
+ //
+ // outputJumpBoxY
+ //
+ this.outputJumpBoxY.Location = new System.Drawing.Point(332, 245);
+ this.outputJumpBoxY.Name = "outputJumpBoxY";
+ this.outputJumpBoxY.Size = new System.Drawing.Size(76, 20);
+ this.outputJumpBoxY.TabIndex = 106;
+ //
+ // inputOffsetBoxY
+ //
+ this.inputOffsetBoxY.Location = new System.Drawing.Point(332, 245);
+ this.inputOffsetBoxY.Name = "inputOffsetBoxY";
+ this.inputOffsetBoxY.Size = new System.Drawing.Size(76, 20);
+ this.inputOffsetBoxY.TabIndex = 106;
+ //
+ // outputOffsetBoxY
//
- this.offsetBoxY.Location = new System.Drawing.Point(332, 218);
- this.offsetBoxY.Name = "offsetBoxY";
- this.offsetBoxY.Size = new System.Drawing.Size(76, 20);
- this.offsetBoxY.TabIndex = 106;
+ this.outputOffsetBoxY.Location = new System.Drawing.Point(332, 245);
+ this.outputOffsetBoxY.Name = "outputOffsetBoxY";
+ this.outputOffsetBoxY.Size = new System.Drawing.Size(76, 20);
+ this.outputOffsetBoxY.TabIndex = 106;
//
// accelerationBoxY
//
- this.accelerationBoxY.Location = new System.Drawing.Point(332, 140);
+ this.accelerationBoxY.Location = new System.Drawing.Point(332, 167);
this.accelerationBoxY.Name = "accelerationBoxY";
this.accelerationBoxY.Size = new System.Drawing.Size(76, 20);
this.accelerationBoxY.TabIndex = 100;
@@ -1142,7 +1607,7 @@ namespace grapher
// MidpointActiveXLabel
//
this.MidpointActiveXLabel.AutoSize = true;
- this.MidpointActiveXLabel.Location = new System.Drawing.Point(197, 303);
+ this.MidpointActiveXLabel.Location = new System.Drawing.Point(197, 330);
this.MidpointActiveXLabel.Name = "MidpointActiveXLabel";
this.MidpointActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.MidpointActiveXLabel.TabIndex = 127;
@@ -1151,61 +1616,70 @@ namespace grapher
// LimitActiveXLabel
//
this.LimitActiveXLabel.AutoSize = true;
- this.LimitActiveXLabel.Location = new System.Drawing.Point(197, 247);
+ this.LimitActiveXLabel.Location = new System.Drawing.Point(197, 274);
this.LimitActiveXLabel.Name = "LimitActiveXLabel";
this.LimitActiveXLabel.Size = new System.Drawing.Size(13, 13);
this.LimitActiveXLabel.TabIndex = 126;
this.LimitActiveXLabel.Text = "0";
//
- // OffsetActiveXLabel
+ // InputJumpActiveXLabel
//
- this.OffsetActiveXLabel.AutoSize = true;
- this.OffsetActiveXLabel.Location = new System.Drawing.Point(197, 221);
- this.OffsetActiveXLabel.Name = "OffsetActiveXLabel";
- this.OffsetActiveXLabel.Size = new System.Drawing.Size(13, 13);
- this.OffsetActiveXLabel.TabIndex = 125;
- this.OffsetActiveXLabel.Text = "0";
+ this.InputJumpActiveXLabel.AutoSize = true;
+ this.InputJumpActiveXLabel.Location = new System.Drawing.Point(197, 248);
+ this.InputJumpActiveXLabel.Name = "InputJumpActiveXLabel";
+ this.InputJumpActiveXLabel.Size = new System.Drawing.Size(13, 13);
+ this.InputJumpActiveXLabel.TabIndex = 125;
+ this.InputJumpActiveXLabel.Text = "0";
//
- // CapActiveYLabel
+ // OutputJumpActiveXLabel
//
- this.CapActiveYLabel.AutoSize = true;
- this.CapActiveYLabel.Location = new System.Drawing.Point(414, 169);
- this.CapActiveYLabel.Name = "CapActiveYLabel";
- this.CapActiveYLabel.Size = new System.Drawing.Size(13, 13);
- this.CapActiveYLabel.TabIndex = 124;
- this.CapActiveYLabel.Text = "0";
+ this.OutputJumpActiveXLabel.AutoSize = true;
+ this.OutputJumpActiveXLabel.Location = new System.Drawing.Point(197, 248);
+ this.OutputJumpActiveXLabel.Name = "OutputJumpActiveXLabel";
+ this.OutputJumpActiveXLabel.Size = new System.Drawing.Size(13, 13);
+ this.OutputJumpActiveXLabel.TabIndex = 125;
+ this.OutputJumpActiveXLabel.Text = "0";
//
- // WeightActiveYLabel
+ // InputOffsetActiveXLabel
//
- this.WeightActiveYLabel.AutoSize = true;
- this.WeightActiveYLabel.Location = new System.Drawing.Point(414, 195);
- this.WeightActiveYLabel.Name = "WeightActiveYLabel";
- this.WeightActiveYLabel.Size = new System.Drawing.Size(13, 13);
- this.WeightActiveYLabel.TabIndex = 123;
- this.WeightActiveYLabel.Text = "0";
+ this.InputOffsetActiveXLabel.AutoSize = true;
+ this.InputOffsetActiveXLabel.Location = new System.Drawing.Point(197, 248);
+ this.InputOffsetActiveXLabel.Name = "InputOffsetActiveXLabel";
+ this.InputOffsetActiveXLabel.Size = new System.Drawing.Size(13, 13);
+ this.InputOffsetActiveXLabel.TabIndex = 125;
+ this.InputOffsetActiveXLabel.Text = "0";
//
- // WeightActiveXLabel
+ // OutputOffsetActiveXLabel
//
- this.WeightActiveXLabel.AutoSize = true;
- this.WeightActiveXLabel.Location = new System.Drawing.Point(197, 195);
- this.WeightActiveXLabel.Name = "WeightActiveXLabel";
- this.WeightActiveXLabel.Size = new System.Drawing.Size(13, 13);
- this.WeightActiveXLabel.TabIndex = 122;
- this.WeightActiveXLabel.Text = "0";
+ this.OutputOffsetActiveXLabel.AutoSize = true;
+ this.OutputOffsetActiveXLabel.Location = new System.Drawing.Point(197, 248);
+ this.OutputOffsetActiveXLabel.Name = "OutputOffsetActiveXLabel";
+ this.OutputOffsetActiveXLabel.Size = new System.Drawing.Size(13, 13);
+ this.OutputOffsetActiveXLabel.TabIndex = 125;
+ this.OutputOffsetActiveXLabel.Text = "0";
//
- // CapActiveXLabel
+ // InCapActiveYLabelClassic
//
- this.CapActiveXLabel.AutoSize = true;
- this.CapActiveXLabel.Location = new System.Drawing.Point(197, 169);
- this.CapActiveXLabel.Name = "CapActiveXLabel";
- this.CapActiveXLabel.Size = new System.Drawing.Size(13, 13);
- this.CapActiveXLabel.TabIndex = 121;
- this.CapActiveXLabel.Text = "0";
+ this.InCapActiveYLabelClassic.AutoSize = true;
+ this.InCapActiveYLabelClassic.Location = new System.Drawing.Point(414, 196);
+ this.InCapActiveYLabelClassic.Name = "InCapActiveYLabelClassic";
+ this.InCapActiveYLabelClassic.Size = new System.Drawing.Size(13, 13);
+ this.InCapActiveYLabelClassic.TabIndex = 124;
+ this.InCapActiveYLabelClassic.Text = "0";
+ //
+ // InCapActiveXLabelClassic
+ //
+ this.InCapActiveXLabelClassic.AutoSize = true;
+ this.InCapActiveXLabelClassic.Location = new System.Drawing.Point(197, 196);
+ this.InCapActiveXLabelClassic.Name = "InCapActiveXLabelClassic";
+ this.InCapActiveXLabelClassic.Size = new System.Drawing.Size(13, 13);
+ this.InCapActiveXLabelClassic.TabIndex = 121;
+ this.InCapActiveXLabelClassic.Text = "0";
//
// AccelerationActiveLabelX
//
this.AccelerationActiveLabelX.AutoSize = true;
- this.AccelerationActiveLabelX.Location = new System.Drawing.Point(197, 143);
+ this.AccelerationActiveLabelX.Location = new System.Drawing.Point(197, 170);
this.AccelerationActiveLabelX.Name = "AccelerationActiveLabelX";
this.AccelerationActiveLabelX.Size = new System.Drawing.Size(13, 13);
this.AccelerationActiveLabelX.TabIndex = 120;
@@ -1214,7 +1688,7 @@ namespace grapher
// AccelTypeActiveLabelX
//
this.AccelTypeActiveLabelX.AutoSize = true;
- this.AccelTypeActiveLabelX.Location = new System.Drawing.Point(197, 116);
+ this.AccelTypeActiveLabelX.Location = new System.Drawing.Point(197, 143);
this.AccelTypeActiveLabelX.Name = "AccelTypeActiveLabelX";
this.AccelTypeActiveLabelX.Size = new System.Drawing.Size(66, 13);
this.AccelTypeActiveLabelX.TabIndex = 119;
@@ -1223,29 +1697,29 @@ namespace grapher
// RotationActiveLabel
//
this.RotationActiveLabel.AutoSize = true;
- this.RotationActiveLabel.Location = new System.Drawing.Point(197, 78);
+ this.RotationActiveLabel.Location = new System.Drawing.Point(197, 105);
this.RotationActiveLabel.Name = "RotationActiveLabel";
this.RotationActiveLabel.Size = new System.Drawing.Size(13, 13);
this.RotationActiveLabel.TabIndex = 118;
this.RotationActiveLabel.Text = "0";
//
- // SensitivityActiveYLabel
+ // VertHorzRatioActiveLabel
//
- this.SensitivityActiveYLabel.AutoSize = true;
- this.SensitivityActiveYLabel.Location = new System.Drawing.Point(217, 52);
- this.SensitivityActiveYLabel.Name = "SensitivityActiveYLabel";
- this.SensitivityActiveYLabel.Size = new System.Drawing.Size(14, 13);
- this.SensitivityActiveYLabel.TabIndex = 117;
- this.SensitivityActiveYLabel.Text = "Y";
+ this.VertHorzRatioActiveLabel.AutoSize = true;
+ this.VertHorzRatioActiveLabel.Location = new System.Drawing.Point(196, 76);
+ this.VertHorzRatioActiveLabel.Name = "VertHorzRatioActiveLabel";
+ this.VertHorzRatioActiveLabel.Size = new System.Drawing.Size(13, 13);
+ this.VertHorzRatioActiveLabel.TabIndex = 117;
+ this.VertHorzRatioActiveLabel.Text = "0";
//
- // SensitivityActiveXLabel
+ // SensitivityMultiplierActiveLabel
//
- this.SensitivityActiveXLabel.AutoSize = true;
- this.SensitivityActiveXLabel.Location = new System.Drawing.Point(188, 52);
- this.SensitivityActiveXLabel.Name = "SensitivityActiveXLabel";
- this.SensitivityActiveXLabel.Size = new System.Drawing.Size(14, 13);
- this.SensitivityActiveXLabel.TabIndex = 116;
- this.SensitivityActiveXLabel.Text = "X";
+ this.SensitivityMultiplierActiveLabel.AutoSize = true;
+ this.SensitivityMultiplierActiveLabel.Location = new System.Drawing.Point(195, 52);
+ this.SensitivityMultiplierActiveLabel.Name = "SensitivityMultiplierActiveLabel";
+ this.SensitivityMultiplierActiveLabel.Size = new System.Drawing.Size(13, 13);
+ this.SensitivityMultiplierActiveLabel.TabIndex = 116;
+ this.SensitivityMultiplierActiveLabel.Text = "0";
//
// ActiveValueTitle
//
@@ -1279,57 +1753,108 @@ namespace grapher
this.sensXYLock.AutoSize = true;
this.sensXYLock.Checked = true;
this.sensXYLock.CheckState = System.Windows.Forms.CheckState.Checked;
- this.sensXYLock.Location = new System.Drawing.Point(283, 49);
+ this.sensXYLock.Location = new System.Drawing.Point(282, 75);
this.sensXYLock.Name = "sensXYLock";
this.sensXYLock.Size = new System.Drawing.Size(15, 14);
this.sensXYLock.TabIndex = 82;
this.sensXYLock.UseVisualStyleBackColor = true;
//
- // capBoxY
+ // inCapBoxYClassic
//
- this.capBoxY.Location = new System.Drawing.Point(332, 166);
- this.capBoxY.Name = "capBoxY";
- this.capBoxY.Size = new System.Drawing.Size(76, 20);
- this.capBoxY.TabIndex = 103;
+ this.inCapBoxYClassic.Location = new System.Drawing.Point(332, 193);
+ this.inCapBoxYClassic.Name = "inCapBoxYClassic";
+ this.inCapBoxYClassic.Size = new System.Drawing.Size(76, 20);
+ this.inCapBoxYClassic.TabIndex = 103;
//
- // sensitivityBoxY
+ // VertHorzRatioBox
//
- this.sensitivityBoxY.Location = new System.Drawing.Point(148, 49);
- this.sensitivityBoxY.Name = "sensitivityBoxY";
- this.sensitivityBoxY.Size = new System.Drawing.Size(34, 20);
- this.sensitivityBoxY.TabIndex = 81;
+ this.VertHorzRatioBox.Location = new System.Drawing.Point(106, 76);
+ this.VertHorzRatioBox.Name = "VertHorzRatioBox";
+ this.VertHorzRatioBox.Size = new System.Drawing.Size(76, 20);
+ this.VertHorzRatioBox.TabIndex = 81;
//
// writeButton
//
this.writeButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
- this.writeButton.Location = new System.Drawing.Point(90, 527);
+ this.writeButton.Location = new System.Drawing.Point(90, 554);
this.writeButton.Name = "writeButton";
this.writeButton.Size = new System.Drawing.Size(92, 35);
this.writeButton.TabIndex = 111;
this.writeButton.Text = "Apply";
this.writeButton.UseVisualStyleBackColor = true;
//
- // offsetLabelX
+ // inputJumpLabelX
+ //
+ this.inputJumpLabelX.AutoSize = true;
+ this.inputJumpLabelX.Location = new System.Drawing.Point(37, 248);
+ this.inputJumpLabelX.Name = "inputJumpLabelX";
+ this.inputJumpLabelX.Size = new System.Drawing.Size(59, 13);
+ this.inputJumpLabelX.TabIndex = 107;
+ this.inputJumpLabelX.Text = "Input Jump";
+ this.inputJumpLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // outputJumpLabelX
+ //
+ this.outputJumpLabelX.AutoSize = true;
+ this.outputJumpLabelX.Location = new System.Drawing.Point(37, 248);
+ this.outputJumpLabelX.Name = "outputJumpLabelX";
+ this.outputJumpLabelX.Size = new System.Drawing.Size(67, 13);
+ this.outputJumpLabelX.TabIndex = 107;
+ this.outputJumpLabelX.Text = "Output Jump";
+ this.outputJumpLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // inputJumpBoxX
+ //
+ this.inputJumpBoxX.Location = new System.Drawing.Point(106, 245);
+ this.inputJumpBoxX.Name = "inputJumpBoxX";
+ this.inputJumpBoxX.Size = new System.Drawing.Size(76, 20);
+ this.inputJumpBoxX.TabIndex = 92;
+ //
+ // outputJumpBoxX
+ //
+ this.outputJumpBoxX.Location = new System.Drawing.Point(106, 245);
+ this.outputJumpBoxX.Name = "outputJumpBoxX";
+ this.outputJumpBoxX.Size = new System.Drawing.Size(76, 20);
+ this.outputJumpBoxX.TabIndex = 92;
//
- this.offsetLabelX.AutoSize = true;
- this.offsetLabelX.Location = new System.Drawing.Point(37, 221);
- this.offsetLabelX.Name = "offsetLabelX";
- this.offsetLabelX.Size = new System.Drawing.Size(35, 13);
- this.offsetLabelX.TabIndex = 107;
- this.offsetLabelX.Text = "Offset";
- this.offsetLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ // inputOffsetLabelX
//
- // offsetBoxX
+ this.inputOffsetLabelX.AutoSize = true;
+ this.inputOffsetLabelX.Location = new System.Drawing.Point(37, 248);
+ this.inputOffsetLabelX.Name = "inputOffsetLabelX";
+ this.inputOffsetLabelX.Size = new System.Drawing.Size(62, 13);
+ this.inputOffsetLabelX.TabIndex = 107;
+ this.inputOffsetLabelX.Text = "Input Offset";
+ this.inputOffsetLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
- this.offsetBoxX.Location = new System.Drawing.Point(106, 218);
- this.offsetBoxX.Name = "offsetBoxX";
- this.offsetBoxX.Size = new System.Drawing.Size(76, 20);
- this.offsetBoxX.TabIndex = 92;
+ // outputOffsetLabelX
+ //
+ this.outputOffsetLabelX.AutoSize = true;
+ this.outputOffsetLabelX.Location = new System.Drawing.Point(37, 248);
+ this.outputOffsetLabelX.Name = "outputOffsetLabelX";
+ this.outputOffsetLabelX.Size = new System.Drawing.Size(70, 13);
+ this.outputOffsetLabelX.TabIndex = 107;
+ this.outputOffsetLabelX.Text = "Output Offset";
+ this.outputOffsetLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // inputOffsetBoxX
+ //
+ this.inputOffsetBoxX.Location = new System.Drawing.Point(106, 245);
+ this.inputOffsetBoxX.Name = "inputOffsetBoxX";
+ this.inputOffsetBoxX.Size = new System.Drawing.Size(76, 20);
+ this.inputOffsetBoxX.TabIndex = 92;
+ //
+ // outputOffsetBoxX
+ //
+ this.outputOffsetBoxX.Location = new System.Drawing.Point(106, 245);
+ this.outputOffsetBoxX.Name = "outputOffsetBoxX";
+ this.outputOffsetBoxX.Size = new System.Drawing.Size(76, 20);
+ this.outputOffsetBoxX.TabIndex = 92;
//
// constantThreeLabelX
//
this.constantThreeLabelX.AutoSize = true;
- this.constantThreeLabelX.Location = new System.Drawing.Point(37, 303);
+ this.constantThreeLabelX.Location = new System.Drawing.Point(37, 330);
this.constantThreeLabelX.Name = "constantThreeLabelX";
this.constantThreeLabelX.Size = new System.Drawing.Size(47, 13);
this.constantThreeLabelX.TabIndex = 105;
@@ -1338,7 +1863,7 @@ namespace grapher
//
// midpointBoxX
//
- this.midpointBoxX.Location = new System.Drawing.Point(106, 300);
+ this.midpointBoxX.Location = new System.Drawing.Point(106, 327);
this.midpointBoxX.Name = "midpointBoxX";
this.midpointBoxX.Size = new System.Drawing.Size(76, 20);
this.midpointBoxX.TabIndex = 96;
@@ -1346,7 +1871,7 @@ namespace grapher
// limitLabelX
//
this.limitLabelX.AutoSize = true;
- this.limitLabelX.Location = new System.Drawing.Point(37, 247);
+ this.limitLabelX.Location = new System.Drawing.Point(37, 274);
this.limitLabelX.Name = "limitLabelX";
this.limitLabelX.Size = new System.Drawing.Size(28, 13);
this.limitLabelX.TabIndex = 101;
@@ -1355,56 +1880,32 @@ namespace grapher
//
// limitBoxX
//
- this.limitBoxX.Location = new System.Drawing.Point(106, 244);
+ this.limitBoxX.Location = new System.Drawing.Point(106, 271);
this.limitBoxX.Name = "limitBoxX";
this.limitBoxX.Size = new System.Drawing.Size(76, 20);
this.limitBoxX.TabIndex = 93;
//
- // weightBoxY
- //
- this.weightBoxY.Location = new System.Drawing.Point(332, 192);
- this.weightBoxY.Name = "weightBoxY";
- this.weightBoxY.Size = new System.Drawing.Size(76, 20);
- this.weightBoxY.TabIndex = 104;
- //
- // weightLabelX
- //
- this.weightLabelX.AutoSize = true;
- this.weightLabelX.Location = new System.Drawing.Point(37, 195);
- this.weightLabelX.Name = "weightLabelX";
- this.weightLabelX.Size = new System.Drawing.Size(41, 13);
- this.weightLabelX.TabIndex = 97;
- this.weightLabelX.Text = "Weight";
- this.weightLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // weightBoxX
+ // inCapLabelXClassic
//
- this.weightBoxX.Location = new System.Drawing.Point(106, 192);
- this.weightBoxX.Name = "weightBoxX";
- this.weightBoxX.Size = new System.Drawing.Size(76, 20);
- this.weightBoxX.TabIndex = 90;
+ this.inCapLabelXClassic.AutoSize = true;
+ this.inCapLabelXClassic.Location = new System.Drawing.Point(37, 196);
+ this.inCapLabelXClassic.Name = "inCapLabelXClassic";
+ this.inCapLabelXClassic.Size = new System.Drawing.Size(56, 13);
+ this.inCapLabelXClassic.TabIndex = 94;
+ this.inCapLabelXClassic.Text = "Cap: Input";
+ this.inCapLabelXClassic.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
- // capLabelX
+ // inCapBoxXClassic
//
- this.capLabelX.AutoSize = true;
- this.capLabelX.Location = new System.Drawing.Point(37, 169);
- this.capLabelX.Name = "capLabelX";
- this.capLabelX.Size = new System.Drawing.Size(26, 13);
- this.capLabelX.TabIndex = 94;
- this.capLabelX.Text = "Cap";
- this.capLabelX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
- //
- // capBoxX
- //
- this.capBoxX.Location = new System.Drawing.Point(106, 166);
- this.capBoxX.Name = "capBoxX";
- this.capBoxX.Size = new System.Drawing.Size(76, 20);
- this.capBoxX.TabIndex = 89;
+ this.inCapBoxXClassic.Location = new System.Drawing.Point(106, 193);
+ this.inCapBoxXClassic.Name = "inCapBoxXClassic";
+ this.inCapBoxXClassic.Size = new System.Drawing.Size(76, 20);
+ this.inCapBoxXClassic.TabIndex = 89;
//
// constantOneLabelX
//
this.constantOneLabelX.AutoSize = true;
- this.constantOneLabelX.Location = new System.Drawing.Point(37, 143);
+ this.constantOneLabelX.Location = new System.Drawing.Point(37, 170);
this.constantOneLabelX.Name = "constantOneLabelX";
this.constantOneLabelX.Size = new System.Drawing.Size(66, 13);
this.constantOneLabelX.TabIndex = 91;
@@ -1413,7 +1914,7 @@ namespace grapher
//
// accelerationBoxX
//
- this.accelerationBoxX.Location = new System.Drawing.Point(106, 140);
+ this.accelerationBoxX.Location = new System.Drawing.Point(106, 167);
this.accelerationBoxX.Name = "accelerationBoxX";
this.accelerationBoxX.Size = new System.Drawing.Size(76, 20);
this.accelerationBoxX.TabIndex = 86;
@@ -1421,7 +1922,7 @@ namespace grapher
// rotationLabel
//
this.rotationLabel.AutoSize = true;
- this.rotationLabel.Location = new System.Drawing.Point(35, 78);
+ this.rotationLabel.Location = new System.Drawing.Point(35, 105);
this.rotationLabel.Name = "rotationLabel";
this.rotationLabel.Size = new System.Drawing.Size(47, 13);
this.rotationLabel.TabIndex = 87;
@@ -1429,7 +1930,7 @@ namespace grapher
//
// rotationBox
//
- this.rotationBox.Location = new System.Drawing.Point(106, 75);
+ this.rotationBox.Location = new System.Drawing.Point(106, 102);
this.rotationBox.Name = "rotationBox";
this.rotationBox.Size = new System.Drawing.Size(76, 20);
this.rotationBox.TabIndex = 83;
@@ -1447,13 +1948,13 @@ namespace grapher
//
this.sensitivityBoxX.Location = new System.Drawing.Point(106, 49);
this.sensitivityBoxX.Name = "sensitivityBoxX";
- this.sensitivityBoxX.Size = new System.Drawing.Size(34, 20);
+ this.sensitivityBoxX.Size = new System.Drawing.Size(76, 20);
this.sensitivityBoxX.TabIndex = 80;
//
// accelTypeDropX
//
this.accelTypeDropX.FormattingEnabled = true;
- this.accelTypeDropX.Location = new System.Drawing.Point(106, 113);
+ this.accelTypeDropX.Location = new System.Drawing.Point(106, 138);
this.accelTypeDropX.Name = "accelTypeDropX";
this.accelTypeDropX.Size = new System.Drawing.Size(76, 21);
this.accelTypeDropX.TabIndex = 84;
@@ -1554,7 +2055,7 @@ namespace grapher
//
this.advancedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.AutoWriteMenuItem,
- this.UseSpecificDeviceMenuItem});
+ this.DeviceMenuItem});
this.advancedToolStripMenuItem.Name = "advancedToolStripMenuItem";
this.advancedToolStripMenuItem.Size = new System.Drawing.Size(72, 20);
this.advancedToolStripMenuItem.Text = "Advanced";
@@ -1565,14 +2066,14 @@ namespace grapher
this.AutoWriteMenuItem.CheckOnClick = true;
this.AutoWriteMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.AutoWriteMenuItem.Name = "AutoWriteMenuItem";
- this.AutoWriteMenuItem.Size = new System.Drawing.Size(210, 22);
- this.AutoWriteMenuItem.Text = "Apply Settings On Startup";
+ this.AutoWriteMenuItem.Size = new System.Drawing.Size(257, 22);
+ this.AutoWriteMenuItem.Text = "Apply Settings.json On GUI Startup";
//
- // UseSpecificDeviceMenuItem
+ // DeviceMenuItem
//
- this.UseSpecificDeviceMenuItem.Name = "UseSpecificDeviceMenuItem";
- this.UseSpecificDeviceMenuItem.Size = new System.Drawing.Size(210, 22);
- this.UseSpecificDeviceMenuItem.Text = "Use Specific Device";
+ this.DeviceMenuItem.Name = "DeviceMenuItem";
+ this.DeviceMenuItem.Size = new System.Drawing.Size(257, 22);
+ this.DeviceMenuItem.Text = "Device Menu";
//
// chartsPanel
//
@@ -1826,56 +2327,6 @@ namespace grapher
title6.Text = "Sensitivity";
this.AccelerationChart.Titles.Add(title6);
//
- // smoothBoxX
- //
- this.smoothBoxX.Location = new System.Drawing.Point(106, 672);
- this.smoothBoxX.Name = "smoothBoxX";
- this.smoothBoxX.Size = new System.Drawing.Size(76, 20);
- this.smoothBoxX.TabIndex = 188;
- //
- // smoothBoxY
- //
- this.smoothBoxY.Location = new System.Drawing.Point(332, 671);
- this.smoothBoxY.Name = "smoothBoxY";
- this.smoothBoxY.Size = new System.Drawing.Size(76, 20);
- this.smoothBoxY.TabIndex = 189;
- //
- // smoothLabelX
- //
- this.smoothLabelX.AutoSize = true;
- this.smoothLabelX.Location = new System.Drawing.Point(38, 677);
- this.smoothLabelX.Name = "smoothLabelX";
- this.smoothLabelX.Size = new System.Drawing.Size(43, 13);
- this.smoothLabelX.TabIndex = 190;
- this.smoothLabelX.Text = "Smooth";
- //
- // SmoothActiveXLabel
- //
- this.SmoothActiveXLabel.AutoSize = true;
- this.SmoothActiveXLabel.Location = new System.Drawing.Point(200, 677);
- this.SmoothActiveXLabel.Name = "SmoothActiveXLabel";
- this.SmoothActiveXLabel.Size = new System.Drawing.Size(13, 13);
- this.SmoothActiveXLabel.TabIndex = 191;
- this.SmoothActiveXLabel.Text = "0";
- //
- // smoothLabelY
- //
- this.smoothLabelY.AutoSize = true;
- this.smoothLabelY.Location = new System.Drawing.Point(266, 677);
- this.smoothLabelY.Name = "smoothLabelY";
- this.smoothLabelY.Size = new System.Drawing.Size(43, 13);
- this.smoothLabelY.TabIndex = 192;
- this.smoothLabelY.Text = "Smooth";
- //
- // SmoothActiveYLabel
- //
- this.SmoothActiveYLabel.AutoSize = true;
- this.SmoothActiveYLabel.Location = new System.Drawing.Point(414, 677);
- this.SmoothActiveYLabel.Name = "SmoothActiveYLabel";
- this.SmoothActiveYLabel.Size = new System.Drawing.Size(13, 13);
- this.SmoothActiveYLabel.TabIndex = 193;
- this.SmoothActiveYLabel.Text = "0";
- //
// RawAcceleration
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -1925,50 +2376,62 @@ namespace grapher
private System.Windows.Forms.Label OptionSetXTitle;
private System.Windows.Forms.Label constantThreeLabelY;
private System.Windows.Forms.Label limitLabelY;
- private System.Windows.Forms.Label offsetLabelY;
- private System.Windows.Forms.Label weightLabelY;
- private System.Windows.Forms.Label capLabelY;
+ private System.Windows.Forms.Label inputJumpLabelY;
+ private System.Windows.Forms.Label outputJumpLabelY;
+ private System.Windows.Forms.Label inputOffsetLabelY;
+ private System.Windows.Forms.Label outputOffsetLabelY;
+ private System.Windows.Forms.Label inCapLabelYClassic;
private System.Windows.Forms.Label constantOneLabelY;
private System.Windows.Forms.CheckBox ByComponentXYLock;
private System.Windows.Forms.Label MidpointActiveYLabel;
private System.Windows.Forms.Label LimitActiveYLabel;
- private System.Windows.Forms.Label OffsetActiveYLabel;
+ private System.Windows.Forms.Label InputJumpActiveYLabel;
+ private System.Windows.Forms.Label OutputJumpActiveYLabel;
+ private System.Windows.Forms.Label InputOffsetActiveYLabel;
+ private System.Windows.Forms.Label OutputOffsetActiveYLabel;
private System.Windows.Forms.Label AccelerationActiveLabelY;
private System.Windows.Forms.ComboBox accelTypeDropY;
private System.Windows.Forms.TextBox midpointBoxY;
private System.Windows.Forms.TextBox limitBoxY;
- private System.Windows.Forms.TextBox offsetBoxY;
+ private System.Windows.Forms.TextBox inputJumpBoxY;
+ private System.Windows.Forms.TextBox outputJumpBoxY;
+ private System.Windows.Forms.TextBox inputOffsetBoxY;
+ private System.Windows.Forms.TextBox outputOffsetBoxY;
private System.Windows.Forms.TextBox accelerationBoxY;
private System.Windows.Forms.Label MidpointActiveXLabel;
private System.Windows.Forms.Label LimitActiveXLabel;
- private System.Windows.Forms.Label OffsetActiveXLabel;
- private System.Windows.Forms.Label CapActiveYLabel;
- private System.Windows.Forms.Label WeightActiveYLabel;
- private System.Windows.Forms.Label WeightActiveXLabel;
- private System.Windows.Forms.Label CapActiveXLabel;
+ private System.Windows.Forms.Label InputJumpActiveXLabel;
+ private System.Windows.Forms.Label OutputJumpActiveXLabel;
+ private System.Windows.Forms.Label InputOffsetActiveXLabel;
+ private System.Windows.Forms.Label OutputOffsetActiveXLabel;
+ private System.Windows.Forms.Label InCapActiveYLabelClassic;
+ private System.Windows.Forms.Label InCapActiveXLabelClassic;
private System.Windows.Forms.Label AccelerationActiveLabelX;
private System.Windows.Forms.Label AccelTypeActiveLabelX;
private System.Windows.Forms.Label RotationActiveLabel;
- private System.Windows.Forms.Label SensitivityActiveYLabel;
- private System.Windows.Forms.Label SensitivityActiveXLabel;
+ private System.Windows.Forms.Label VertHorzRatioActiveLabel;
+ private System.Windows.Forms.Label SensitivityMultiplierActiveLabel;
private System.Windows.Forms.Label ActiveValueTitle;
private System.Windows.Forms.Label MouseLabel;
private System.Windows.Forms.Label LockXYLabel;
private System.Windows.Forms.CheckBox sensXYLock;
- private System.Windows.Forms.TextBox capBoxY;
- private System.Windows.Forms.TextBox sensitivityBoxY;
+ private System.Windows.Forms.TextBox inCapBoxYClassic;
+ private System.Windows.Forms.TextBox VertHorzRatioBox;
private System.Windows.Forms.Button writeButton;
- private System.Windows.Forms.Label offsetLabelX;
- private System.Windows.Forms.TextBox offsetBoxX;
+ private System.Windows.Forms.Label inputOffsetLabelX;
+ private System.Windows.Forms.Label outputOffsetLabelX;
+ private System.Windows.Forms.TextBox inputOffsetBoxX;
+ private System.Windows.Forms.TextBox outputOffsetBoxX;
+ private System.Windows.Forms.Label inputJumpLabelX;
+ private System.Windows.Forms.Label outputJumpLabelX;
+ private System.Windows.Forms.TextBox inputJumpBoxX;
+ private System.Windows.Forms.TextBox outputJumpBoxX;
private System.Windows.Forms.Label constantThreeLabelX;
private System.Windows.Forms.TextBox midpointBoxX;
private System.Windows.Forms.Label limitLabelX;
private System.Windows.Forms.TextBox limitBoxX;
- private System.Windows.Forms.TextBox weightBoxY;
- private System.Windows.Forms.Label weightLabelX;
- private System.Windows.Forms.TextBox weightBoxX;
- private System.Windows.Forms.Label capLabelX;
- private System.Windows.Forms.TextBox capBoxX;
+ private System.Windows.Forms.Label inCapLabelXClassic;
+ private System.Windows.Forms.TextBox inCapBoxXClassic;
private System.Windows.Forms.Label constantOneLabelX;
private System.Windows.Forms.TextBox accelerationBoxX;
private System.Windows.Forms.Label rotationLabel;
@@ -2016,7 +2479,7 @@ namespace grapher
private System.Windows.Forms.Label LpNormActiveValue;
private System.Windows.Forms.Label RangeActiveValueY;
private System.Windows.Forms.CheckBox FakeBox;
- private System.Windows.Forms.ToolStripMenuItem UseSpecificDeviceMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem DeviceMenuItem;
private System.Windows.Forms.Label LUTTextLabelX;
private System.Windows.Forms.Label LUTTextLabelY;
private System.Windows.Forms.CheckBox gainSwitchX;
@@ -2058,6 +2521,37 @@ namespace grapher
private System.Windows.Forms.Label smoothLabelX;
private System.Windows.Forms.TextBox smoothBoxY;
private System.Windows.Forms.TextBox smoothBoxX;
+ private System.Windows.Forms.Label VertHorzRatioLabel;
+ private System.Windows.Forms.ComboBox CapTypeDropdownYClassic;
+ private System.Windows.Forms.ComboBox CapTypeDropdownXClassic;
+ private System.Windows.Forms.Label CapTypeLabelYClassic;
+ private System.Windows.Forms.Label CapTypeLabelXClassic;
+ private System.Windows.Forms.Label outCapLabelYClassic;
+ private System.Windows.Forms.Label outCapLabelXClassic;
+ private System.Windows.Forms.TextBox outCapBoxYClassic;
+ private System.Windows.Forms.TextBox outCapBoxXClassic;
+ private System.Windows.Forms.Label OutCapActiveXLabelClassic;
+ private System.Windows.Forms.Label OutCapActiveYLabelClassic;
+ private System.Windows.Forms.Label CapTypeActiveYLabelClassic;
+ private System.Windows.Forms.Label CapTypeActiveXLabelClassic;
+ private System.Windows.Forms.ComboBox CapTypeDropdownYPower;
+ private System.Windows.Forms.ComboBox CapTypeDropdownXPower;
+ private System.Windows.Forms.Label OutCapActiveYLabelPower;
+ private System.Windows.Forms.Label InCapActiveYLabelPower;
+ private System.Windows.Forms.Label OutCapActiveXLabelPower;
+ private System.Windows.Forms.Label InCapActiveXLabelPower;
+ private System.Windows.Forms.Label CapTypeActiveYLabelPower;
+ private System.Windows.Forms.Label CapTypeActiveXLabelPower;
+ private System.Windows.Forms.Label outCapLabelYPower;
+ private System.Windows.Forms.Label inCapLabelYPower;
+ private System.Windows.Forms.Label CapTypeLabelYPower;
+ private System.Windows.Forms.Label outCapLabelXPower;
+ private System.Windows.Forms.Label inCapLabelXPower;
+ private System.Windows.Forms.Label CapTypeLabelXPower;
+ private System.Windows.Forms.TextBox outCapBoxYPower;
+ private System.Windows.Forms.TextBox outCapBoxXPower;
+ private System.Windows.Forms.TextBox inCapBoxYPower;
+ private System.Windows.Forms.TextBox inCapBoxXPower;
}
}
diff --git a/grapher/Form1.cs b/grapher/Form1.cs
index ba16a23..b36d511 100644
--- a/grapher/Form1.cs
+++ b/grapher/Form1.cs
@@ -15,6 +15,7 @@ using grapher.Models.Serialized;
using grapher.Models;
using System.Reflection;
using System.Diagnostics;
+using System.IO;
namespace grapher
{
@@ -33,14 +34,18 @@ namespace grapher
ToolStripMenuItem HelpMenuItem = new ToolStripMenuItem("&Help");
HelpMenuItem.DropDownItems.AddRange(new ToolStripItem[] {
- new ToolStripMenuItem("&About", null, (s, e) => new AboutBox(driverVersion).ShowDialog())
+ new ToolStripMenuItem("&About", null, (s, e) => {
+ using (var form = new AboutBox(driverVersion))
+ {
+ form.ShowDialog();
+ }
+ })
});
menuStrip1.Items.AddRange(new ToolStripItem[] { HelpMenuItem });
AccelGUI = AccelGUIFactory.Construct(
this,
- ManagedAccel.GetActive(),
AccelerationChart,
AccelerationChartY,
VelocityChart,
@@ -51,26 +56,40 @@ namespace grapher
accelTypeDropY,
XLutApplyDropdown,
YLutApplyDropdown,
+ CapTypeDropdownXClassic,
+ CapTypeDropdownYClassic,
+ CapTypeDropdownXPower,
+ CapTypeDropdownYPower,
writeButton,
toggleButton,
showVelocityGainToolStripMenuItem,
showLastMouseMoveToolStripMenuItem,
streamingModeToolStripMenuItem,
AutoWriteMenuItem,
- UseSpecificDeviceMenuItem,
+ DeviceMenuItem,
ScaleMenuItem,
DPITextBox,
PollRateTextBox,
DirectionalityPanel,
sensitivityBoxX,
- sensitivityBoxY,
+ VertHorzRatioBox,
rotationBox,
- weightBoxX,
- weightBoxY,
- capBoxX,
- capBoxY,
- offsetBoxX,
- offsetBoxY,
+ inCapBoxXClassic,
+ inCapBoxYClassic,
+ outCapBoxXClassic,
+ outCapBoxYClassic,
+ inCapBoxXPower,
+ inCapBoxYPower,
+ outCapBoxXPower,
+ outCapBoxYPower,
+ inputJumpBoxX,
+ inputJumpBoxY,
+ outputJumpBoxX,
+ outputJumpBoxY,
+ inputOffsetBoxX,
+ inputOffsetBoxY,
+ outputOffsetBoxX,
+ outputOffsetBoxY,
accelerationBoxX,
accelerationBoxY,
decayRateBoxX,
@@ -107,13 +126,28 @@ namespace grapher
YLutPointsBox,
LockXYLabel,
sensitivityLabel,
+ VertHorzRatioLabel,
rotationLabel,
- weightLabelX,
- weightLabelY,
- capLabelX,
- capLabelY,
- offsetLabelX,
- offsetLabelY,
+ inCapLabelXClassic,
+ inCapLabelYClassic,
+ outCapLabelXClassic,
+ outCapLabelYClassic,
+ CapTypeLabelXClassic,
+ CapTypeLabelYClassic,
+ inCapLabelXPower,
+ inCapLabelYPower,
+ outCapLabelXPower,
+ outCapLabelYPower,
+ CapTypeLabelXPower,
+ CapTypeLabelYPower,
+ inputJumpLabelX,
+ inputJumpLabelY,
+ outputJumpLabelX,
+ outputJumpLabelY,
+ inputOffsetLabelX,
+ inputOffsetLabelY,
+ outputOffsetLabelX,
+ outputOffsetLabelY,
constantOneLabelX,
constantOneLabelY,
decayRateLabelX,
@@ -136,15 +170,29 @@ namespace grapher
constantThreeLabelY,
ActiveValueTitle,
ActiveValueTitleY,
- SensitivityActiveXLabel,
- SensitivityActiveYLabel,
+ SensitivityMultiplierActiveLabel,
+ VertHorzRatioActiveLabel,
RotationActiveLabel,
- WeightActiveXLabel,
- WeightActiveYLabel,
- CapActiveXLabel,
- CapActiveYLabel,
- OffsetActiveXLabel,
- OffsetActiveYLabel,
+ InCapActiveXLabelClassic,
+ InCapActiveYLabelClassic,
+ OutCapActiveXLabelClassic,
+ OutCapActiveYLabelClassic,
+ CapTypeActiveXLabelClassic,
+ CapTypeActiveYLabelClassic,
+ InCapActiveXLabelPower,
+ InCapActiveYLabelPower,
+ OutCapActiveXLabelPower,
+ OutCapActiveYLabelPower,
+ CapTypeActiveXLabelPower,
+ CapTypeActiveYLabelPower,
+ InputJumpActiveXLabel,
+ InputJumpActiveYLabel,
+ OutputJumpActiveXLabel,
+ OutputJumpActiveYLabel,
+ InputOffsetActiveXLabel,
+ InputOffsetActiveYLabel,
+ OutputOffsetActiveXLabel,
+ OutputOffsetActiveYLabel,
AccelerationActiveLabelX,
AccelerationActiveLabelY,
DecayRateActiveXLabel,
@@ -210,7 +258,7 @@ namespace grapher
}
else if (m.Msg == 0x00fe) // WM_INPUT_DEVICE_CHANGE
{
- AccelGUI.UpdateInputManagers();
+ AccelGUI.Settings.OnDeviceChangeMessage();
}
}
@@ -243,6 +291,68 @@ namespace grapher
}
- #endregion Method
+ #endregion Method
+
+ static void MakeStartupShortcut(bool gui)
+ {
+ var startupFolder = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
+
+ if (string.IsNullOrEmpty(startupFolder))
+ {
+ throw new Exception("Startup folder does not exist");
+ }
+
+ //Windows Script Host Shell Object
+ Type t = Type.GetTypeFromCLSID(new Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8"));
+ dynamic shell = Activator.CreateInstance(t);
+
+ try
+ {
+ // Delete any other RA related startup shortcuts
+ var candidates = new[] { "rawaccel", "raw accel", "writer" };
+
+ foreach (string path in Directory.EnumerateFiles(startupFolder, "*.lnk")
+ .Where(f => candidates.Any(f.Substring(startupFolder.Length).ToLower().Contains)))
+ {
+ var link = shell.CreateShortcut(path);
+ try
+ {
+ string targetPath = link.TargetPath;
+
+ if (!(targetPath is null) &&
+ (targetPath.EndsWith("rawaccel.exe") ||
+ targetPath.EndsWith("writer.exe") &&
+ new FileInfo(targetPath).Directory.GetFiles("rawaccel.exe").Any()))
+ {
+ File.Delete(path);
+ }
+ }
+ finally
+ {
+ Marshal.FinalReleaseComObject(link);
+ }
+ }
+
+ var name = gui ? "rawaccel" : "writer";
+
+ var lnk = shell.CreateShortcut($@"{startupFolder}\{name}.lnk");
+
+ try
+ {
+ if (!gui) lnk.Arguments = Constants.DefaultSettingsFileName;
+ lnk.TargetPath = $@"{Application.StartupPath}\{name}.exe";
+ lnk.Save();
+ }
+ finally
+ {
+ Marshal.FinalReleaseComObject(lnk);
+ }
+
+ }
+ finally
+ {
+ Marshal.FinalReleaseComObject(shell);
+ }
+ }
}
}
diff --git a/grapher/Layouts/ClassicLayout.cs b/grapher/Layouts/ClassicLayout.cs
index fb8fa02..cb09fba 100644
--- a/grapher/Layouts/ClassicLayout.cs
+++ b/grapher/Layouts/ClassicLayout.cs
@@ -11,21 +11,22 @@ namespace grapher.Layouts
Mode = AccelMode.classic;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(true, Acceleration);
+ ClassicCapLayout = new OptionLayout(true, CapType);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(true, Cap);
- WeightLayout = new OptionLayout(false, string.Empty);
- OffsetLayout = new OptionLayout(true, Offset);
+ InputOffsetLayout = new OptionLayout(true, InputOffset);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(true, PowerClassic);
ExponentLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/DefaultLayout.cs b/grapher/Layouts/DefaultLayout.cs
index 29d28f7..357c36f 100644
--- a/grapher/Layouts/DefaultLayout.cs
+++ b/grapher/Layouts/DefaultLayout.cs
@@ -12,21 +12,22 @@ namespace grapher.Layouts
LogarithmicCharts = false;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(true, Acceleration);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(true, DecayRate);
GrowthRateLayout = new OptionLayout(true, GrowthRate);
SmoothLayout = new OptionLayout(true, Smooth);
- ScaleLayout = new OptionLayout(true, Scale);
- CapLayout = new OptionLayout(true, Cap);
- WeightLayout = new OptionLayout(true, Weight);
- OffsetLayout = new OptionLayout(true, Offset);
+ InputOffsetLayout = new OptionLayout(true, InputOffset);
LimitLayout = new OptionLayout(true, Limit);
PowerClassicLayout = new OptionLayout(true, PowerClassic);
ExponentLayout = new OptionLayout(true, Exponent);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(true, Midpoint);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/JumpLayout.cs b/grapher/Layouts/JumpLayout.cs
index 277297c..453a2c7 100644
--- a/grapher/Layouts/JumpLayout.cs
+++ b/grapher/Layouts/JumpLayout.cs
@@ -12,21 +12,22 @@ namespace grapher.Layouts
LogarithmicCharts = false;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(false, string.Empty);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(true, Smooth);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(true, Cap);
- WeightLayout = new OptionLayout(false, Weight);
- OffsetLayout = new OptionLayout(true, Offset);
+ InputOffsetLayout = new OptionLayout(false, InputOffset);
LimitLayout = new OptionLayout(false, Limit);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(true, Input);
+ OutputJumpLayout = new OptionLayout(true, Output);
}
}
}
diff --git a/grapher/Layouts/LUTLayout.cs b/grapher/Layouts/LUTLayout.cs
index 5848adb..8aa0dd5 100644
--- a/grapher/Layouts/LUTLayout.cs
+++ b/grapher/Layouts/LUTLayout.cs
@@ -20,21 +20,22 @@ namespace grapher.Layouts
Mode = AccelMode.lut;
GainSwitchOptionLayout = new OptionLayout(false, string.Empty);
- AccelLayout = new OptionLayout(false, Acceleration);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(false, Cap);
- WeightLayout = new OptionLayout(false, Weight);
- OffsetLayout = new OptionLayout(false, Offset);
+ InputOffsetLayout = new OptionLayout(false, string.Empty);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, Exponent);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(true, string.Empty);
LutPanelLayout = new OptionLayout(true, string.Empty);
LutApplyOptionsLayout = new OptionLayout(true, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
public override string ActiveName => LUTActiveName;
diff --git a/grapher/Layouts/LayoutBase.cs b/grapher/Layouts/LayoutBase.cs
index 66260eb..e53b37e 100644
--- a/grapher/Layouts/LayoutBase.cs
+++ b/grapher/Layouts/LayoutBase.cs
@@ -9,29 +9,33 @@ namespace grapher.Layouts
public const string DecayRate = "Decay Rate";
public const string Scale = "Scale";
public const string Exponent = "Exponent";
+ public const string OutputOffset = "Output Offset";
public const string PowerClassic = "Power";
public const string Limit = "Limit";
public const string Midpoint = "Midpoint";
public const string Motivity = "Motivity";
- public const string Offset = "Offset";
- public const string Cap = "Cap";
+ public const string InputOffset = "Input Offset";
+ public const string CapType = "Cap Type";
public const string Weight = "Weight";
public const string Smooth = "Smooth";
public const string Gain = "Gain";
+ public const string Input = "Input";
+ public const string Output = "Output";
public LayoutBase()
{
- AccelLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(false, string.Empty);
- WeightLayout = new OptionLayout(false, string.Empty);
- OffsetLayout = new OptionLayout(false, string.Empty);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ InputOffsetLayout = new OptionLayout(false, string.Empty);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
@@ -49,21 +53,19 @@ namespace grapher.Layouts
public bool LogarithmicCharts { get; protected set; }
- protected OptionLayout AccelLayout { get; set; }
-
protected OptionLayout DecayRateLayout { get; set; }
protected OptionLayout GrowthRateLayout { get; set; }
protected OptionLayout SmoothLayout { get; set; }
- protected OptionLayout ScaleLayout { get; set; }
+ protected OptionLayout ClassicCapLayout { get; set; }
- protected OptionLayout CapLayout { get; set; }
+ protected OptionLayout PowerCapLayout { get; set; }
- protected OptionLayout WeightLayout { get; set; }
+ protected OptionLayout InputJumpLayout { get; set; }
- protected OptionLayout OffsetLayout { get; set; }
+ protected OptionLayout InputOffsetLayout { get; set; }
protected OptionLayout LimitLayout { get; set; }
@@ -71,6 +73,10 @@ namespace grapher.Layouts
protected OptionLayout ExponentLayout { get; set; }
+ protected OptionLayout OutputJumpLayout { get; set; }
+
+ protected OptionLayout OutputOffsetLayout { get; set; }
+
protected OptionLayout MidpointLayout { get; set; }
protected OptionLayout LutTextLayout { get; set; }
@@ -88,17 +94,18 @@ namespace grapher.Layouts
public void Layout(
IOption gainSwitchOption,
- IOption accelOption,
+ IOption classicCapOption,
+ IOption powerCapOption,
IOption decayRateOption,
IOption growthRateOption,
IOption smoothOption,
- IOption scaleOption,
- IOption capOption,
- IOption weightOption,
- IOption offsetOption,
+ IOption inputJumpOption,
+ IOption inputOffsetOption,
IOption limitOption,
IOption powerClassicOption,
IOption expOption,
+ IOption outputJumpOption,
+ IOption outputOffsetOption,
IOption midpointOption,
IOption lutTextOption,
IOption lutPanelOption,
@@ -110,17 +117,18 @@ namespace grapher.Layouts
foreach (var option in new (OptionLayout, IOption)[] {
(GainSwitchOptionLayout, gainSwitchOption),
- (AccelLayout, accelOption),
+ (ClassicCapLayout, classicCapOption),
+ (PowerCapLayout, powerCapOption),
(DecayRateLayout, decayRateOption),
(GrowthRateLayout, growthRateOption),
(SmoothLayout, smoothOption),
- (ScaleLayout, scaleOption),
- (CapLayout, capOption),
- (WeightLayout, weightOption),
- (OffsetLayout, offsetOption),
+ (InputJumpLayout, inputJumpOption),
+ (InputOffsetLayout, inputOffsetOption),
(LimitLayout, limitOption),
(PowerClassicLayout, powerClassicOption),
(ExponentLayout, expOption),
+ (OutputJumpLayout, outputJumpOption),
+ (OutputOffsetLayout, outputOffsetOption),
(MidpointLayout, midpointOption),
(LutTextLayout, lutTextOption),
(LutPanelLayout, lutPanelOption),
@@ -146,39 +154,41 @@ namespace grapher.Layouts
public void Layout(
IOption gainSwitchOption,
- IOption accelOption,
+ IOption classicCapOption,
+ IOption powerCapOption,
IOption decayRateOption,
IOption growthRateOption,
IOption smoothOption,
- IOption scaleOption,
- IOption capOption,
- IOption weightOption,
- IOption offsetOption,
+ IOption inputJumpOption,
+ IOption inputOffsetOption,
IOption limitOption,
IOption powerClassicOption,
IOption expOption,
+ IOption outputJumpOption,
+ IOption outputOffsetOption,
IOption midpointOption,
IOption lutTextOption,
IOption lutPanelOption,
IOption lutApplyOption)
{
Layout(gainSwitchOption,
- accelOption,
+ classicCapOption,
+ powerCapOption,
decayRateOption,
growthRateOption,
smoothOption,
- scaleOption,
- capOption,
- weightOption,
- offsetOption,
+ inputJumpOption,
+ inputOffsetOption,
limitOption,
powerClassicOption,
expOption,
+ outputJumpOption,
+ outputOffsetOption,
midpointOption,
lutTextOption,
lutPanelOption,
lutApplyOption,
- accelOption.Top);
+ gainSwitchOption.Top);
}
}
}
diff --git a/grapher/Layouts/LinearLayout.cs b/grapher/Layouts/LinearLayout.cs
index 6108a0b..ebace66 100644
--- a/grapher/Layouts/LinearLayout.cs
+++ b/grapher/Layouts/LinearLayout.cs
@@ -11,24 +11,24 @@ namespace grapher.Layouts
{
Name = LinearName;
Mode = AccelMode.classic;
- LogarithmicCharts = false;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(true, Acceleration);
+ ClassicCapLayout = new OptionLayout(true, CapType);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(true, Cap);
- WeightLayout = new OptionLayout(false, Weight);
- OffsetLayout = new OptionLayout(true, Offset);
+ InputOffsetLayout = new OptionLayout(true, InputOffset);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/MotivityLayout.cs b/grapher/Layouts/MotivityLayout.cs
index 5443715..d4fd99c 100644
--- a/grapher/Layouts/MotivityLayout.cs
+++ b/grapher/Layouts/MotivityLayout.cs
@@ -17,21 +17,22 @@ namespace grapher.Layouts
LogarithmicCharts = true;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(false, string.Empty);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(true, GrowthRate);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(false, string.Empty);
- WeightLayout = new OptionLayout(false, string.Empty);
- OffsetLayout = new OptionLayout(false, string.Empty);
+ InputOffsetLayout = new OptionLayout(false, string.Empty);
LimitLayout = new OptionLayout(true, Motivity);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(true, Midpoint);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/NaturalLayout.cs b/grapher/Layouts/NaturalLayout.cs
index 15166cb..03f2f82 100644
--- a/grapher/Layouts/NaturalLayout.cs
+++ b/grapher/Layouts/NaturalLayout.cs
@@ -12,21 +12,22 @@ namespace grapher.Layouts
LogarithmicCharts = false;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(false, string.Empty);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(true, DecayRate);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(false, string.Empty);
- WeightLayout = new OptionLayout(false, string.Empty);
- OffsetLayout = new OptionLayout(true, Offset);
+ InputOffsetLayout = new OptionLayout(true, InputOffset);
LimitLayout = new OptionLayout(true, Limit);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/OffLayout.cs b/grapher/Layouts/OffLayout.cs
index d742ef8..482f87a 100644
--- a/grapher/Layouts/OffLayout.cs
+++ b/grapher/Layouts/OffLayout.cs
@@ -12,21 +12,22 @@ namespace grapher.Layouts
LogarithmicCharts = false;
GainSwitchOptionLayout = new OptionLayout(false, string.Empty);
- AccelLayout = new OptionLayout(false, string.Empty);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(false, string.Empty);
- WeightLayout = new OptionLayout(false, string.Empty);
- OffsetLayout = new OptionLayout(false, string.Empty);
+ InputOffsetLayout = new OptionLayout(false, string.Empty);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/PowerLayout.cs b/grapher/Layouts/PowerLayout.cs
index 03d9efa..fb88ab0 100644
--- a/grapher/Layouts/PowerLayout.cs
+++ b/grapher/Layouts/PowerLayout.cs
@@ -10,21 +10,22 @@
LogarithmicCharts = false;
GainSwitchOptionLayout = new OptionLayout(true, Gain);
- AccelLayout = new OptionLayout(false, string.Empty);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(true, CapType);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(true, Scale);
- CapLayout = new OptionLayout(false, string.Empty);
- WeightLayout = new OptionLayout(true, Weight);
- OffsetLayout = new OptionLayout(false, string.Empty);
+ InputOffsetLayout = new OptionLayout(false, string.Empty);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(true, Exponent);
+ OutputOffsetLayout = new OptionLayout(true, OutputOffset);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(false, string.Empty);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
}
diff --git a/grapher/Layouts/UnsupportedLayout.cs b/grapher/Layouts/UnsupportedLayout.cs
index 4a401a4..a2d7ab5 100644
--- a/grapher/Layouts/UnsupportedLayout.cs
+++ b/grapher/Layouts/UnsupportedLayout.cs
@@ -17,21 +17,22 @@ namespace grapher.Layouts
Mode = AccelMode.noaccel + 1;
GainSwitchOptionLayout = new OptionLayout(false, string.Empty);
- AccelLayout = new OptionLayout(false, Acceleration);
+ ClassicCapLayout = new OptionLayout(false, string.Empty);
+ PowerCapLayout = new OptionLayout(false, string.Empty);
DecayRateLayout = new OptionLayout(false, string.Empty);
GrowthRateLayout = new OptionLayout(false, string.Empty);
SmoothLayout = new OptionLayout(false, string.Empty);
- ScaleLayout = new OptionLayout(false, string.Empty);
- CapLayout = new OptionLayout(false, Cap);
- WeightLayout = new OptionLayout(false, Weight);
- OffsetLayout = new OptionLayout(false, Offset);
+ InputOffsetLayout = new OptionLayout(false, string.Empty);
LimitLayout = new OptionLayout(false, string.Empty);
PowerClassicLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, Exponent);
+ OutputOffsetLayout = new OptionLayout(false, string.Empty);
MidpointLayout = new OptionLayout(false, string.Empty);
LutTextLayout = new OptionLayout(true, LUTLayoutText);
LutPanelLayout = new OptionLayout(false, string.Empty);
LutApplyOptionsLayout = new OptionLayout(false, string.Empty);
+ InputJumpLayout = new OptionLayout(false, string.Empty);
+ OutputJumpLayout = new OptionLayout(false, string.Empty);
}
}
} \ No newline at end of file
diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs
index 4ce6ed8..23d5017 100644
--- a/grapher/Models/AccelGUI.cs
+++ b/grapher/Models/AccelGUI.cs
@@ -4,6 +4,7 @@ using grapher.Models.Mouse;
using grapher.Models.Options;
using grapher.Models.Serialized;
using System;
+using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
@@ -25,7 +26,7 @@ namespace grapher
ButtonBase resetButton,
MouseWatcher mouseWatcher,
ToolStripMenuItem scaleMenuItem,
- DeviceIDManager deviceIDManager)
+ ToolStripMenuItem deviceMenuItem)
{
AccelForm = accelForm;
AccelCalculator = accelCalculator;
@@ -34,18 +35,19 @@ namespace grapher
WriteButton = writeButton;
ResetButton = (CheckBox)resetButton;
ScaleMenuItem = scaleMenuItem;
+ DeviceMenuItem = deviceMenuItem;
Settings = settings;
DefaultButtonFont = WriteButton.Font;
SmallButtonFont = new Font(WriteButton.Font.Name, WriteButton.Font.Size * Constants.SmallButtonSizeFactor);
MouseWatcher = mouseWatcher;
- DeviceIDManager = deviceIDManager;
+ DeviceMenuItem.Click += DeviceMenuItemClick;
ScaleMenuItem.Click += new System.EventHandler(OnScaleMenuItemClick);
WriteButton.Click += new System.EventHandler(OnWriteButtonClick);
ResetButton.Click += new System.EventHandler(ResetDriverEventHandler);
AccelForm.FormClosing += new FormClosingEventHandler(SaveGUISettingsOnClose);
- ButtonTimerInterval = Convert.ToInt32(DriverSettings.WriteDelayMs);
+ ButtonTimerInterval = Convert.ToInt32(DriverConfig.WriteDelayMs);
ButtonTimer = new Timer();
ButtonTimer.Tick += new System.EventHandler(OnButtonTimerTick);
@@ -85,7 +87,7 @@ namespace grapher
public ToolStripMenuItem ScaleMenuItem { get; }
- public DeviceIDManager DeviceIDManager { get; }
+ public ToolStripMenuItem DeviceMenuItem { get; }
private Timer ChartRefresh { get; }
@@ -112,21 +114,23 @@ namespace grapher
}
}
- public DriverSettings MakeSettingsFromFields()
+ public Profile MakeSettingsFromFields()
{
- var settings = new DriverSettings();
+ var settings = new Profile();
settings.rotation = ApplyOptions.Rotation.Field.Data;
- settings.sensitivity = new Vec2<double>
- {
- x = ApplyOptions.Sensitivity.Fields.X,
- y = ApplyOptions.Sensitivity.Fields.Y
- };
+ settings.sensitivity = ApplyOptions.Sensitivity.Field.Data;
+
+ // TODO - separate sensitivity fields, add new label for ratio
+ settings.yxSensRatio = ApplyOptions.YToXRatio.Value;
settings.combineMagnitudes = ApplyOptions.IsWhole;
- ApplyOptions.SetArgs(ref settings.args);
- settings.domainArgs = ApplyOptions.Directionality.GetDomainArgs();
+ ApplyOptions.SetArgsFromActiveValues(ref settings.argsX, ref settings.argsY);
+
+ var (domWeights, lpNorm) = ApplyOptions.Directionality.GetDomainArgs();
+ settings.domainXY = domWeights;
+ settings.lpNorm = lpNorm;
+
settings.rangeXY = ApplyOptions.Directionality.GetRangeXY();
- settings.deviceID = DeviceIDManager.ID;
Settings.SetHiddenOptions(settings);
@@ -141,16 +145,15 @@ namespace grapher
{
ButtonDelay(WriteButton);
- var settings = MakeSettingsFromFields();
- SettingsErrors errors = Settings.TryActivate(settings);
- if (errors.Empty())
+ if (!Settings.TryActivate(MakeSettingsFromFields(), out string errors))
{
- RefreshActive();
- return;
+ error_message = errors.ToString();
}
else
{
- error_message = errors.ToString();
+ RefreshActive();
+ Settings.SetActiveHandles();
+ return;
}
}
catch (ApplicationException e)
@@ -158,37 +161,30 @@ namespace grapher
error_message = e.Message;
}
- new MessageDialog(error_message, "bad input").ShowDialog();
- }
-
-
- public void UpdateInputManagers()
- {
- MouseWatcher.UpdateHandles(Settings.ActiveSettings.baseSettings.deviceID);
- DeviceIDManager.Update(Settings.ActiveSettings.baseSettings.deviceID);
+ using (var form = new MessageDialog(error_message, "bad input"))
+ {
+ form.ShowDialog();
+ }
}
public void RefreshActive()
{
- UpdateShownActiveValues(Settings.UserSettings);
+ UpdateShownActiveValues(Settings.ActiveProfile);
UpdateGraph();
- UpdateInputManagers();
}
public void RefreshUser()
{
- UpdateShownActiveValues(Settings.UserSettings);
+ UpdateShownActiveValues(Settings.UserProfile);
}
public void UpdateGraph()
{
- AccelCharts.Calculate(
- Settings.ActiveAccel,
- Settings.ActiveSettings.baseSettings);
+ AccelCharts.Calculate(Settings.ActiveAccel, Settings.ActiveProfile);
AccelCharts.Bind();
}
- public void UpdateShownActiveValues(DriverSettings args)
+ public void UpdateShownActiveValues(Profile args)
{
AccelForm.ResetAutoScroll();
AccelCharts.ShowActive(args);
@@ -207,7 +203,7 @@ namespace grapher
private void SetupButtons()
{
WriteButton.Top = Constants.SensitivityChartAloneHeight - Constants.ButtonVerticalOffset;
-
+
ResetButton.Appearance = Appearance.Button;
ResetButton.FlatStyle = FlatStyle.System;
ResetButton.TextAlign = ContentAlignment.MiddleCenter;
@@ -243,7 +239,7 @@ namespace grapher
private void ResetDriverEventHandler(object sender, EventArgs e)
{
ButtonDelay(ResetButton);
- Settings.DisableDriver();
+ Settings.ResetDriver();
RefreshActive();
}
@@ -251,10 +247,12 @@ namespace grapher
{
ButtonTimer.Stop();
SetButtonDefaults();
+ DeviceMenuItem.Enabled = true;
}
private void StartButtonTimer()
{
+ DeviceMenuItem.Enabled = false;
ButtonTimer.Interval = ButtonTimerInterval;
ButtonTimer.Start();
}
@@ -279,6 +277,18 @@ namespace grapher
MouseWatcher.UpdateLastMove();
}
+ private void DeviceMenuItemClick(object sender, EventArgs e)
+ {
+ using (var devMenu = new DeviceMenuForm(Settings))
+ {
+ if (devMenu.ShowDialog() == DialogResult.OK)
+ {
+ Settings.Submit(devMenu.defaultConfig, devMenu.Items);
+ UpdateActiveSettingsFromFields();
+ }
+ }
+ }
+
#endregion Methods
}
diff --git a/grapher/Models/AccelGUIFactory.cs b/grapher/Models/AccelGUIFactory.cs
index 7e5ae9b..5fc7b8b 100644
--- a/grapher/Models/AccelGUIFactory.cs
+++ b/grapher/Models/AccelGUIFactory.cs
@@ -2,6 +2,7 @@
using grapher.Models.Devices;
using grapher.Models.Mouse;
using grapher.Models.Options;
+using grapher.Models.Options.Cap;
using grapher.Models.Options.Directionality;
using grapher.Models.Options.LUT;
using grapher.Models.Serialized;
@@ -17,7 +18,6 @@ namespace grapher.Models
public static AccelGUI Construct(
RawAcceleration form,
- ManagedAccel activeAccel,
Chart accelerationChart,
Chart accelerationChartY,
Chart velocityChart,
@@ -28,13 +28,17 @@ namespace grapher.Models
ComboBox accelTypeDropY,
ComboBox lutApplyDropdownX,
ComboBox lutApplyDropdownY,
+ ComboBox capTypeDropdownXClassic,
+ ComboBox capTypeDropdownYClassic,
+ ComboBox capTypeDropdownXPower,
+ ComboBox capTypeDropdownYPower,
Button writeButton,
ButtonBase toggleButton,
ToolStripMenuItem showVelocityGainToolStripMenuItem,
ToolStripMenuItem showLastMouseMoveMenuItem,
ToolStripMenuItem streamingModeToolStripMenuItem,
ToolStripMenuItem autoWriteMenuItem,
- ToolStripMenuItem useSpecificDeviceMenuItem,
+ ToolStripMenuItem deviceMenuItem,
ToolStripMenuItem scaleMenuItem,
ToolStripTextBox dpiTextBox,
ToolStripTextBox pollRateTextBox,
@@ -42,12 +46,22 @@ namespace grapher.Models
TextBox sensitivityBoxX,
TextBox sensitivityBoxY,
TextBox rotationBox,
- TextBox weightBoxX,
- TextBox weightBoxY,
- TextBox capBoxX,
- TextBox capBoxY,
- TextBox offsetBoxX,
- TextBox offsetBoxY,
+ TextBox inCapBoxXClassic,
+ TextBox inCapBoxYClassic,
+ TextBox outCapBoxXClassic,
+ TextBox outCapBoxYClassic,
+ TextBox inCapBoxXPower,
+ TextBox inCapBoxYPower,
+ TextBox outCapBoxXPower,
+ TextBox outCapBoxYPower,
+ TextBox inputJumpBoxX,
+ TextBox inputJumpBoxY,
+ TextBox outputJumpBoxX,
+ TextBox outputJumpBoxY,
+ TextBox inputOffsetBoxX,
+ TextBox inputOffsetBoxY,
+ TextBox outputOffsetBoxX,
+ TextBox outputOffsetBoxY,
TextBox accelerationBoxX,
TextBox accelerationBoxY,
TextBox decayRateBoxX,
@@ -84,13 +98,28 @@ namespace grapher.Models
RichTextBox yLutPointsBox,
Label lockXYLabel,
Label sensitivityLabel,
+ Label yxRatioLabel,
Label rotationLabel,
- Label weightLabelX,
- Label weightLabelY,
- Label capLabelX,
- Label capLabelY,
- Label offsetLabelX,
- Label offsetLabelY,
+ Label inCapLabelXClassic,
+ Label inCapLabelYClassic,
+ Label outCapLabelXClassic,
+ Label outCapLabelYClassic,
+ Label capTypeLabelXClassic,
+ Label capTypeLabelYClassic,
+ Label inCapLabelXPower,
+ Label inCapLabelYPower,
+ Label outCapLabelXPower,
+ Label outCapLabelYPower,
+ Label capTypeLabelXPower,
+ Label capTypeLabelYPower,
+ Label inputJumpLabelX,
+ Label inputJumpLabelY,
+ Label outputJumpLabelX,
+ Label outputJumpLabelY,
+ Label inputOffsetLabelX,
+ Label inputOffsetLabelY,
+ Label outputOffsetLabelX,
+ Label outputOffsetLabelY,
Label constantOneLabelX,
Label constantOneLabelY,
Label decayRateLabelX,
@@ -113,15 +142,29 @@ namespace grapher.Models
Label constantThreeLabelY,
Label activeValueTitleX,
Label activeValueTitleY,
- Label sensitivityActiveXLabel,
- Label sensitivityActiveYLabel,
+ Label sensitivityActiveLabel,
+ Label yxRatioActiveLabel,
Label rotationActiveLabel,
- Label weightActiveXLabel,
- Label weightActiveYLabel,
- Label capActiveXLabel,
- Label capActiveYLabel,
- Label offsetActiveLabelX,
- Label offsetActiveLabelY,
+ Label inCapActiveXLabelClassic,
+ Label inCapActiveYLabelClassic,
+ Label outCapActiveXLabelClassic,
+ Label outCapActiveYLabelClassic,
+ Label capTypeActiveXLabelClassic,
+ Label capTypeActiveYLabelClassic,
+ Label inCapActiveXLabelPower,
+ Label inCapActiveYLabelPower,
+ Label outCapActiveXLabelPower,
+ Label outCapActiveYLabelPower,
+ Label capTypeActiveXLabelPower,
+ Label capTypeActiveYLabelPower,
+ Label inputJumpActiveLabelX,
+ Label inputJumpActiveLabelY,
+ Label outputJumpActiveLabelX,
+ Label outputJumpActiveLabelY,
+ Label inputOffsetActiveLabelX,
+ Label inputOffsetActiveLabelY,
+ Label outputOffsetActiveLabelX,
+ Label outputOffsetActiveLabelY,
Label accelerationActiveLabelX,
Label accelerationActiveLabelY,
Label decayRateActiveLabelX,
@@ -182,18 +225,27 @@ namespace grapher.Models
writeButton,
accelCalculator);
- var sensitivity = new OptionXY(
+ var sensitivity = new Option(
sensitivityBoxX,
- sensitivityBoxY,
- sensXYLock,
form,
1,
sensitivityLabel,
- new ActiveValueLabelXY(
- new ActiveValueLabel(sensitivityActiveXLabel, activeValueTitleX),
- new ActiveValueLabel(sensitivityActiveYLabel, activeValueTitleX)),
+ 0,
+ new ActiveValueLabel(sensitivityActiveLabel, activeValueTitleX),
"Sens Multiplier");
+ var yxRatio = new LockableOption(
+ new Option(
+ sensitivityBoxY,
+ form,
+ 1,
+ yxRatioLabel,
+ 0,
+ new ActiveValueLabel(yxRatioActiveLabel, activeValueTitleX),
+ "Y/X Ratio"),
+ sensXYLock,
+ 1);
+
var rotation = new Option(
rotationBox,
form,
@@ -207,58 +259,76 @@ namespace grapher.Models
var directionalityLeft = directionalityPanel.Left;
- var weightX = new Option(
- weightBoxX,
+ var inputJumpX = new Option(
+ inputJumpBoxX,
form,
- 1,
- weightLabelX,
0,
- new ActiveValueLabel(weightActiveXLabel, activeValueTitleX),
- "Weight");
+ inputJumpLabelX,
+ 0,
+ new ActiveValueLabel(inputJumpActiveLabelX, activeValueTitleX),
+ "Jump");
- var weightY = new Option(
- weightBoxY,
+ var inputJumpY = new Option(
+ inputJumpBoxY,
form,
- 1,
- weightLabelY,
+ 0,
+ inputJumpLabelY,
optionSetYLeft,
- new ActiveValueLabel(weightActiveYLabel, activeValueTitleY),
- "Weight");
+ new ActiveValueLabel(inputJumpActiveLabelY, activeValueTitleY),
+ "Jump");
- var capX = new Option(
- capBoxX,
+ var outputJumpX = new Option(
+ outputJumpBoxX,
form,
0,
- capLabelX,
+ outputJumpLabelX,
0,
- new ActiveValueLabel(capActiveXLabel, activeValueTitleX),
- "Cap");
+ new ActiveValueLabel(outputJumpActiveLabelX, activeValueTitleX),
+ "Jump");
- var capY = new Option(
- capBoxY,
+ var outputJumpY = new Option(
+ outputJumpBoxY,
form,
0,
- capLabelY,
+ outputJumpLabelY,
optionSetYLeft,
- new ActiveValueLabel(capActiveYLabel, activeValueTitleY),
- "Cap");
+ new ActiveValueLabel(outputJumpActiveLabelY, activeValueTitleY),
+ "Jump");
- var offsetX = new Option(
- offsetBoxX,
+ var inputOffsetX = new Option(
+ inputOffsetBoxX,
form,
0,
- offsetLabelX,
+ inputOffsetLabelX,
0,
- new ActiveValueLabel(offsetActiveLabelX, activeValueTitleX),
+ new ActiveValueLabel(inputOffsetActiveLabelX, activeValueTitleX),
"Offset");
- var offsetY = new Option(
- offsetBoxY,
+ var inputOffsetY = new Option(
+ inputOffsetBoxY,
form,
0,
- offsetLabelY,
+ inputOffsetLabelY,
optionSetYLeft,
- new ActiveValueLabel(offsetActiveLabelY, activeValueTitleY),
+ new ActiveValueLabel(inputOffsetActiveLabelY, activeValueTitleY),
+ "Offset");
+
+ var outputOffsetX = new Option(
+ outputOffsetBoxX,
+ form,
+ 0,
+ outputOffsetLabelX,
+ 0,
+ new ActiveValueLabel(outputOffsetActiveLabelX, activeValueTitleX),
+ "Offset");
+
+ var outputOffsetY = new Option(
+ outputOffsetBoxY,
+ form,
+ 0,
+ outputOffsetLabelY,
+ optionSetYLeft,
+ new ActiveValueLabel(outputOffsetActiveLabelY, activeValueTitleY),
"Offset");
var accelerationX = new Option(
@@ -369,6 +439,114 @@ namespace grapher.Models
new ActiveValueLabel(midpointActiveLabelY, activeValueTitleY),
optionSetYLeft);
+ var inCapXClassic = new Option(
+ inCapBoxXClassic,
+ form,
+ 0,
+ inCapLabelXClassic,
+ 0,
+ new ActiveValueLabel(inCapActiveXLabelClassic, activeValueTitleX),
+ "Cap: Input");
+
+ var inCapYClassic = new Option(
+ inCapBoxYClassic,
+ form,
+ 0,
+ inCapLabelYClassic,
+ optionSetYLeft,
+ new ActiveValueLabel(inCapActiveYLabelClassic, activeValueTitleY),
+ "Cap");
+
+ var outCapXClassic = new Option(
+ outCapBoxXClassic,
+ form,
+ 0,
+ outCapLabelXClassic,
+ 0,
+ new ActiveValueLabel(outCapActiveXLabelClassic, activeValueTitleX),
+ "Cap: Input");
+
+ var outCapYClassic = new Option(
+ outCapBoxYClassic,
+ form,
+ 0,
+ outCapLabelYClassic,
+ optionSetYLeft,
+ new ActiveValueLabel(outCapActiveYLabelClassic, activeValueTitleY),
+ "Cap");
+
+ var capTypeXClassic = new CapTypeOptions(
+ capTypeLabelXClassic,
+ capTypeDropdownXClassic,
+ new ActiveValueLabel(capTypeActiveXLabelClassic, activeValueTitleX),
+ 0);
+
+ var capTypeYClassic = new CapTypeOptions(
+ capTypeLabelYClassic,
+ capTypeDropdownYClassic,
+ new ActiveValueLabel(capTypeActiveYLabelClassic, activeValueTitleY),
+ optionSetYLeft);
+
+ var classicCapOptionsX = new CapOptions(
+ capTypeXClassic,
+ inCapXClassic,
+ outCapXClassic,
+ accelerationX);
+
+ var classicCapOptionsY = new CapOptions(
+ capTypeYClassic,
+ inCapYClassic,
+ outCapYClassic,
+ accelerationY);
+
+ var inCapXPower = new Option(
+ inCapBoxXPower,
+ form,
+ 0,
+ inCapLabelXPower,
+ 0,
+ new ActiveValueLabel(inCapActiveXLabelPower, activeValueTitleX),
+ "Cap: Input");
+
+ var inCapYPower = new Option(
+ inCapBoxYPower,
+ form,
+ 0,
+ inCapLabelYPower,
+ optionSetYLeft,
+ new ActiveValueLabel(inCapActiveYLabelPower, activeValueTitleY),
+ "Cap");
+
+ var outCapXPower = new Option(
+ outCapBoxXPower,
+ form,
+ 0,
+ outCapLabelXPower,
+ 0,
+ new ActiveValueLabel(outCapActiveXLabelPower, activeValueTitleX),
+ "Cap: Input");
+
+ var outCapYPower = new Option(
+ outCapBoxYPower,
+ form,
+ 0,
+ outCapLabelYPower,
+ optionSetYLeft,
+ new ActiveValueLabel(outCapActiveYLabelPower, activeValueTitleY),
+ "Cap");
+
+ var capTypeXPower = new CapTypeOptions(
+ capTypeLabelXPower,
+ capTypeDropdownXPower,
+ new ActiveValueLabel(capTypeActiveXLabelPower, activeValueTitleX),
+ 0);
+
+ var capTypeYPower = new CapTypeOptions(
+ capTypeLabelYPower,
+ capTypeDropdownYPower,
+ new ActiveValueLabel(capTypeActiveYLabelPower, activeValueTitleY),
+ optionSetYLeft);
+
var lpNorm = new Option(
new Field(lpNormBox, form, 2),
lpNormLabel,
@@ -409,17 +587,34 @@ namespace grapher.Models
gainSwitchY,
new ActiveValueLabel(gainSwitchActiveLabelY, activeValueTitleY));
+ var powerCapOptionsX = new CapOptions(
+ capTypeXPower,
+ inCapXPower,
+ outCapXPower,
+ scaleX,
+ outputOffsetX,
+ gainSwitchOptionX);
+
+ var powerCapOptionsY = new CapOptions(
+ capTypeYPower,
+ inCapYPower,
+ outCapYPower,
+ scaleY,
+ outputOffsetY,
+ gainSwitchOptionY);
+
var accelerationOptionsX = new AccelTypeOptions(
accelTypeDropX,
gainSwitchOptionX,
- accelerationX,
+ classicCapOptionsX,
+ powerCapOptionsX,
+ outputJumpX,
+ outputOffsetX,
decayRateX,
growthRateX,
smoothX,
- scaleX,
- capX,
- weightX,
- offsetX,
+ inputJumpX,
+ inputOffsetX,
limitX,
powerClassicX,
exponentX,
@@ -436,14 +631,15 @@ namespace grapher.Models
var accelerationOptionsY = new AccelTypeOptions(
accelTypeDropY,
gainSwitchOptionY,
- accelerationY,
+ classicCapOptionsY,
+ powerCapOptionsY,
+ outputJumpY,
+ outputOffsetY,
decayRateY,
growthRateY,
smoothY,
- scaleY,
- capY,
- weightY,
- offsetY,
+ inputJumpY,
+ inputOffsetY,
limitY,
powerClassicY,
exponentY,
@@ -488,21 +684,18 @@ namespace grapher.Models
optionsSetY,
directionalOptions,
sensitivity,
+ yxRatio,
rotation,
lockXYLabel,
accelCharts);
- var deviceIdManager = new DeviceIDManager(useSpecificDeviceMenuItem);
-
var settings = new SettingsManager(
- activeAccel,
accelCalculator.DPI,
accelCalculator.PollRate,
autoWriteMenuItem,
showLastMouseMoveMenuItem,
showVelocityGainToolStripMenuItem,
- streamingModeToolStripMenuItem,
- deviceIdManager);
+ streamingModeToolStripMenuItem);
var mouseWatcher = new MouseWatcher(form, mouseLabel, accelCharts, settings);
@@ -516,7 +709,7 @@ namespace grapher.Models
toggleButton,
mouseWatcher,
scaleMenuItem,
- deviceIdManager);
+ deviceMenuItem);
}
#endregion Methods
diff --git a/grapher/Models/Calculations/AccelCalculator.cs b/grapher/Models/Calculations/AccelCalculator.cs
index 574f55a..6b9cbf3 100644
--- a/grapher/Models/Calculations/AccelCalculator.cs
+++ b/grapher/Models/Calculations/AccelCalculator.cs
@@ -107,7 +107,7 @@ namespace grapher.Models.Calculations
continue;
}
- var output = accel.Accelerate(simulatedInputDatum.x, simulatedInputDatum.y, simulatedInputDatum.time);
+ var output = accel.Accelerate(simulatedInputDatum.x, simulatedInputDatum.y, 1, simulatedInputDatum.time);
var outMagnitude = DecimalCheck(Velocity(output.Item1, output.Item2, simulatedInputDatum.time));
var inDiff = Math.Round(simulatedInputDatum.velocity - lastInputMagnitude, 5);
var outDiff = Math.Round(outMagnitude - lastOutputMagnitude, 5);
@@ -193,7 +193,7 @@ namespace grapher.Models.Calculations
data.MinGain = minSlope;
}
- public void CalculateDirectional(AccelChartData[] dataByAngle, ManagedAccel accel, DriverSettings settings, IReadOnlyCollection<IReadOnlyCollection<SimulatedMouseInput>> simulatedInputData)
+ public void CalculateDirectional(AccelChartData[] dataByAngle, ManagedAccel accel, Profile settings, IReadOnlyCollection<IReadOnlyCollection<SimulatedMouseInput>> simulatedInputData)
{
double maxRatio = 0.0;
double minRatio = Double.MaxValue;
@@ -219,7 +219,7 @@ namespace grapher.Models.Calculations
continue;
}
- var output = accel.Accelerate(simulatedInputDatum.x, simulatedInputDatum.y, simulatedInputDatum.time);
+ var output = accel.Accelerate(simulatedInputDatum.x, simulatedInputDatum.y, 1, simulatedInputDatum.time);
var magnitude = DecimalCheck(Velocity(output.Item1, output.Item2, simulatedInputDatum.time));
var inDiff = Math.Round(simulatedInputDatum.velocity - lastInputMagnitude, 5);
var outDiff = Math.Round(magnitude - lastOutputMagnitude, 5);
@@ -246,7 +246,7 @@ namespace grapher.Models.Calculations
}
var ratio = DecimalCheck(magnitude / simulatedInputDatum.velocity);
- var slope = DecimalCheck(inDiff > 0 ? outDiff / inDiff : settings.sensitivity.x);
+ var slope = DecimalCheck(inDiff > 0 ? outDiff / inDiff : settings.sensitivity);
bool indexToMeasureExtrema = (angleIndex == 0) || (angleIndex == (Constants.AngleDivisions - 1));
@@ -477,16 +477,16 @@ namespace grapher.Models.Calculations
return Magnitude(x, y) / time;
}
- public static bool ShouldStripSens(ref DriverSettings settings) =>
- settings.sensitivity.x != settings.sensitivity.y;
+ public static bool ShouldStripSens(Profile settings) =>
+ settings.yxSensRatio != 1;
- public static bool ShouldStripRot(ref DriverSettings settings) =>
+ public static bool ShouldStripRot(Profile settings) =>
settings.rotation > 0;
- public static (double, double) GetSens(ref DriverSettings settings) =>
- (settings.sensitivity.x, settings.sensitivity.y);
+ public static (double, double) GetSens(Profile settings) =>
+ (settings.sensitivity, settings.sensitivity * settings.yxSensRatio);
- public static (double, double) GetRotVector(ref DriverSettings settings) =>
+ public static (double, double) GetRotVector(Profile settings) =>
(Math.Cos(settings.rotation), Math.Sin(settings.rotation));
public static (double, double) StripSens(double outputX, double outputY, double sensitivityX, double sensitivityY) =>
diff --git a/grapher/Models/Calculations/Data/AccelDataCombined.cs b/grapher/Models/Calculations/Data/AccelDataCombined.cs
index 8efb9ac..025a344 100644
--- a/grapher/Models/Calculations/Data/AccelDataCombined.cs
+++ b/grapher/Models/Calculations/Data/AccelDataCombined.cs
@@ -40,10 +40,10 @@ namespace grapher.Models.Calculations.Data
X.Clear();
}
- public void CreateGraphData(ManagedAccel accel, DriverSettings settings)
+ public void CreateGraphData(ManagedAccel accel, Profile settings)
{
Clear();
- Calculator.Calculate(X, accel, settings.sensitivity.x, Calculator.SimulatedInputCombined);
+ Calculator.Calculate(X, accel, settings.sensitivity, Calculator.SimulatedInputCombined);
}
}
}
diff --git a/grapher/Models/Calculations/Data/AccelDataXYComponential.cs b/grapher/Models/Calculations/Data/AccelDataXYComponential.cs
index 6231eb3..f954230 100644
--- a/grapher/Models/Calculations/Data/AccelDataXYComponential.cs
+++ b/grapher/Models/Calculations/Data/AccelDataXYComponential.cs
@@ -54,11 +54,12 @@ namespace grapher.Models.Calculations.Data
Y.Clear();
}
- public void CreateGraphData(ManagedAccel accel, DriverSettings settings)
+ public void CreateGraphData(ManagedAccel accel, Profile settings)
{
Clear();
- Calculator.Calculate(X, accel, settings.sensitivity.x, Calculator.SimulatedInputX);
- Calculator.Calculate(Y, accel, settings.sensitivity.y, Calculator.SimulatedInputY);
+ var sensY = settings.sensitivity * settings.yxSensRatio;
+ Calculator.Calculate(X, accel, settings.sensitivity, Calculator.SimulatedInputX);
+ Calculator.Calculate(Y, accel, sensY, Calculator.SimulatedInputY);
}
}
}
diff --git a/grapher/Models/Calculations/Data/AccelDataXYDirectional.cs b/grapher/Models/Calculations/Data/AccelDataXYDirectional.cs
index 8bd889d..b139719 100644
--- a/grapher/Models/Calculations/Data/AccelDataXYDirectional.cs
+++ b/grapher/Models/Calculations/Data/AccelDataXYDirectional.cs
@@ -67,7 +67,7 @@ namespace grapher.Models.Calculations.Data
}
}
- public void CreateGraphData(ManagedAccel accel, DriverSettings settings)
+ public void CreateGraphData(ManagedAccel accel, Profile settings)
{
Clear();
Calculator.CalculateDirectional(AngleToData, accel, settings, Calculator.SimulatedDirectionalInput);
diff --git a/grapher/Models/Calculations/Data/IAccelData.cs b/grapher/Models/Calculations/Data/IAccelData.cs
index 576e6df..2ae6716 100644
--- a/grapher/Models/Calculations/Data/IAccelData.cs
+++ b/grapher/Models/Calculations/Data/IAccelData.cs
@@ -10,7 +10,7 @@ namespace grapher.Models.Calculations.Data
{
void CalculateDots(double x, double y, double timeInMs);
- void CreateGraphData(ManagedAccel accel, DriverSettings settings);
+ void CreateGraphData(ManagedAccel accel, Profile settings);
void Clear();
diff --git a/grapher/Models/Charts/AccelCharts.cs b/grapher/Models/Charts/AccelCharts.cs
index 631c2e2..93c9218 100644
--- a/grapher/Models/Charts/AccelCharts.cs
+++ b/grapher/Models/Charts/AccelCharts.cs
@@ -121,9 +121,9 @@ namespace grapher
ChartState.Bind();
}
- public void ShowActive(DriverSettings driverSettings)
+ public void ShowActive(Profile args)
{
- ChartState = ChartStateManager.DetermineState(driverSettings);
+ ChartState = ChartStateManager.DetermineState(args);
ChartState.Activate();
Bind();
}
@@ -134,9 +134,9 @@ namespace grapher
ChartState.Redraw();
}
- public void Calculate(ManagedAccel accel, DriverSettings settings)
+ public void Calculate(ManagedAccel accel, Profile settings)
{
- ChartState.SetUpCalculate(settings);
+ ChartState.SetUpCalculate();
ChartState.Calculate(accel, settings);
}
diff --git a/grapher/Models/Charts/ChartState/ChartState.cs b/grapher/Models/Charts/ChartState/ChartState.cs
index a50eaf0..eca2e43 100644
--- a/grapher/Models/Charts/ChartState/ChartState.cs
+++ b/grapher/Models/Charts/ChartState/ChartState.cs
@@ -35,7 +35,7 @@ namespace grapher.Models.Charts.ChartState
public AccelCalculator Calculator { get; }
- public virtual DriverSettings Settings { get; set; }
+ public virtual Profile Settings { get; set; }
internal bool TwoDotsPerGraph { get; set; }
@@ -48,7 +48,7 @@ namespace grapher.Models.Charts.ChartState
public abstract void Activate();
- public virtual void Calculate(ManagedAccel accel, DriverSettings settings)
+ public virtual void Calculate(ManagedAccel accel, Profile settings)
{
Data.CreateGraphData(accel, settings);
}
@@ -60,7 +60,7 @@ namespace grapher.Models.Charts.ChartState
GainChart.Update();
}
- public virtual void SetUpCalculate(DriverSettings settings)
+ public virtual void SetUpCalculate()
{
Data.Clear();
Calculator.ScaleByMouseSettings();
diff --git a/grapher/Models/Charts/ChartState/ChartStateManager.cs b/grapher/Models/Charts/ChartState/ChartStateManager.cs
index 3d4bbec..1e5386c 100644
--- a/grapher/Models/Charts/ChartState/ChartStateManager.cs
+++ b/grapher/Models/Charts/ChartState/ChartStateManager.cs
@@ -50,14 +50,14 @@ namespace grapher.Models.Charts.ChartState
private XYTwoGraphState XYTwoGraphState { get; }
- public ChartState DetermineState(DriverSettings settings)
+ public ChartState DetermineState(Profile settings)
{
ChartState chartState;
if (settings.combineMagnitudes)
{
- if (settings.sensitivity.x != settings.sensitivity.y ||
- settings.domainArgs.domainXY.x != settings.domainArgs.domainXY.y ||
+ if (settings.yxSensRatio != 1 ||
+ settings.domainXY.x != settings.domainXY.y ||
settings.rangeXY.x != settings.rangeXY.y)
{
chartState = XYOneGraphState;
diff --git a/grapher/Models/Charts/ChartState/XYTwoGraphState.cs b/grapher/Models/Charts/ChartState/XYTwoGraphState.cs
index 5b6c2b8..387d1b1 100644
--- a/grapher/Models/Charts/ChartState/XYTwoGraphState.cs
+++ b/grapher/Models/Charts/ChartState/XYTwoGraphState.cs
@@ -23,7 +23,7 @@ namespace grapher.Models.Charts.ChartState
Data = new AccelDataXYComponential(xPoints, yPoints, accelCalculator);
}
- public override DriverSettings Settings { get; set; }
+ public override Profile Settings { get; set; }
public override void Activate()
{
diff --git a/grapher/Models/Devices/DeviceDialogItem.cs b/grapher/Models/Devices/DeviceDialogItem.cs
new file mode 100644
index 0000000..9ca5528
--- /dev/null
+++ b/grapher/Models/Devices/DeviceDialogItem.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace grapher.Models.Devices
+{
+ public class DeviceDialogItem
+ {
+ public MultiHandleDevice device;
+ public DeviceSettings oldSettings;
+ public DeviceConfig newConfig;
+ public string newProfile;
+ public bool overrideDefaultConfig;
+
+ public override string ToString()
+ {
+ return string.IsNullOrWhiteSpace(device.name) ?
+ device.id :
+ device.name;
+ }
+ }
+}
diff --git a/grapher/Models/Devices/DeviceIDItem.cs b/grapher/Models/Devices/DeviceIDItem.cs
deleted file mode 100644
index 8f1587b..0000000
--- a/grapher/Models/Devices/DeviceIDItem.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace grapher.Models.Devices
-{
- public class DeviceIDItem
- {
- public DeviceIDItem(string name, string id, DeviceIDManager manager)
- {
- Name = name;
- ID = id;
- Manager = manager;
- DeviceIDMenuItem = new ToolStripMenuItem();
- DeviceIDMenuItem.Checked = false;
- DeviceIDMenuItem.Text = MenuItemText();
- DeviceIDMenuItem.Click += OnClicked;
- manager.DeviceIDsMenuItem.DropDownItems.Add(DeviceIDMenuItem);
- }
-
- private ToolStripMenuItem DeviceIDMenuItem { get; }
-
- public string Name { get; }
-
- public string ID { get; }
-
- private DeviceIDManager Manager { get; }
-
- public void SetActivated()
- {
- DeviceIDMenuItem.Checked = true;
- }
-
- public void SetDeactivated()
- {
- DeviceIDMenuItem.Checked = false;
- }
-
- private string MenuItemText() => string.IsNullOrEmpty(ID) ? $"{Name}" : ID.Replace("&", "&&");
-
- private string DisconnectedText() => $"Disconnected: {ID}";
-
- public void SetDisconnected()
- {
- DeviceIDMenuItem.ForeColor = Color.DarkGray;
- DeviceIDMenuItem.Text = DisconnectedText();
- }
-
- public void OnClicked(object sender, EventArgs e)
- {
- Manager.SetActive(this);
- }
-
- public override bool Equals(object obj)
- {
- return obj is DeviceIDItem item &&
- Name == item.Name &&
- ID == item.ID;
- }
-
- public override int GetHashCode()
- {
- int hashCode = -1692744877;
- hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
- hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(ID);
- return hashCode;
- }
- }
-}
diff --git a/grapher/Models/Devices/DeviceIDManager.cs b/grapher/Models/Devices/DeviceIDManager.cs
deleted file mode 100644
index 39856a1..0000000
--- a/grapher/Models/Devices/DeviceIDManager.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Management;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace grapher.Models.Devices
-{
- public class DeviceIDManager
- {
- public DeviceIDManager(ToolStripMenuItem deviceIDs)
- {
- DeviceIDsMenuItem = deviceIDs;
- DeviceIDsMenuItem.Checked = false;
- }
-
- public ToolStripMenuItem DeviceIDsMenuItem { get; }
-
- public string ID { get => SelectedDeviceID.ID; }
-
- public DeviceIDItem SelectedDeviceID { get; private set; }
-
- public Dictionary<string, DeviceIDItem> DeviceIDs { get; private set; }
-
- public void SetActive(DeviceIDItem deviceIDItem)
- {
- if (SelectedDeviceID != null)
- {
- SelectedDeviceID.SetDeactivated();
- }
-
- SelectedDeviceID = deviceIDItem;
- SelectedDeviceID.SetActivated();
- }
-
- public void Update(string devID)
- {
- DeviceIDsMenuItem.DropDownItems.Clear();
-
- bool found = string.IsNullOrEmpty(devID);
-
- var anyDevice = new DeviceIDItem("Any", string.Empty, this);
-
- if (found) SetActive(anyDevice);
-
- foreach (string id in RawInputInterop.GetDeviceIDs())
- {
- var deviceItem = new DeviceIDItem(string.Empty, id, this);
- if (!found && deviceItem.ID.Equals(devID))
- {
- SetActive(deviceItem);
- found = true;
- }
- }
-
- if (!found)
- {
- var deviceItem = new DeviceIDItem(string.Empty, devID, this);
- deviceItem.SetDisconnected();
- SetActive(deviceItem);
- }
- }
-
- }
-}
diff --git a/grapher/Models/Mouse/MouseWatcher.cs b/grapher/Models/Mouse/MouseWatcher.cs
index c5c2ae5..fb34dd6 100644
--- a/grapher/Models/Mouse/MouseWatcher.cs
+++ b/grapher/Models/Mouse/MouseWatcher.cs
@@ -691,7 +691,9 @@ namespace grapher.Models.Mouse
AccelCharts = accelCharts;
SettingsManager = setMngr;
MouseData = new MouseData();
- DeviceHandles = new List<IntPtr>();
+
+ LastMoveDisplayFormat = Constants.MouseMoveDefaultFormat;
+ LastMoveNormalized = false;
RAWINPUTDEVICE device = new RAWINPUTDEVICE();
device.WindowHandle = ContainingForm.Handle;
@@ -722,9 +724,9 @@ namespace grapher.Models.Mouse
private Stopwatch Stopwatch { get; }
- private List<IntPtr> DeviceHandles { get; }
+ private string LastMoveDisplayFormat { get; set; }
- private bool AnyDevice { get; set; }
+ private bool LastMoveNormalized { get; set; }
private double PollTime
{
@@ -735,20 +737,10 @@ namespace grapher.Models.Mouse
#region Methods
- public void UpdateHandles(string devID)
- {
- DeviceHandles.Clear();
- AnyDevice = string.IsNullOrEmpty(devID);
- if (!AnyDevice)
- {
- RawInputInterop.AddHandlesFromID(devID, DeviceHandles);
- }
- }
-
public void UpdateLastMove()
{
MouseData.Get(out var x, out var y);
- Display.Text = $"Last (x, y): ({x}, {y})";
+ Display.Text = string.Format(LastMoveDisplayFormat, x, y);
}
public void ReadMouseMove(Message message)
@@ -758,7 +750,25 @@ namespace grapher.Models.Mouse
_ = GetRawInputData(message.LParam, RawInputCommand.Input, out rawInput, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER)));
bool relative = !rawInput.Data.Mouse.Flags.HasFlag(RawMouseFlags.MoveAbsolute);
- bool deviceMatch = AnyDevice || DeviceHandles.Contains(rawInput.Header.Device);
+
+ bool deviceMatch = false;
+ foreach (var (handle, normalized) in SettingsManager.ActiveNormTaggedHandles)
+ {
+ if (handle == rawInput.Header.Device)
+ {
+ deviceMatch = true;
+
+ if (normalized != LastMoveNormalized)
+ {
+ LastMoveDisplayFormat = normalized ?
+ Constants.MouseMoveNormalizedFormat :
+ Constants.MouseMoveDefaultFormat;
+ LastMoveNormalized = normalized;
+ }
+
+ break;
+ }
+ }
if (relative && deviceMatch && (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0))
{
@@ -772,8 +782,11 @@ namespace grapher.Models.Mouse
// strip negative directional multipliers, charts calculated from positive input
- Vec2<double> dirMults = SettingsManager.ActiveSettings.baseSettings
- .directionalMultipliers;
+ Vec2<double> dirMults = new Vec2<double>
+ {
+ x = SettingsManager.ActiveProfile.lrSensRatio,
+ y = SettingsManager.ActiveProfile.udSensRatio
+ };
if (dirMults.x > 0 && x < 0)
{
diff --git a/grapher/Models/Options/AccelOptionSet.cs b/grapher/Models/Options/AccelOptionSet.cs
index 75eb017..3451402 100644
--- a/grapher/Models/Options/AccelOptionSet.cs
+++ b/grapher/Models/Options/AccelOptionSet.cs
@@ -99,7 +99,7 @@ namespace grapher.Models.Options
Options.Top = TopAnchor;
}
- public void SetArgs(ref AccelArgs args)
+ public void SetArgsFromActiveValues(ref AccelArgs args)
{
Options.SetArgs(ref args);
}
diff --git a/grapher/Models/Options/AccelTypeOptions.cs b/grapher/Models/Options/AccelTypeOptions.cs
index 44c9ea8..359b6b8 100644
--- a/grapher/Models/Options/AccelTypeOptions.cs
+++ b/grapher/Models/Options/AccelTypeOptions.cs
@@ -1,10 +1,8 @@
using grapher.Layouts;
using grapher.Models.Options;
+using grapher.Models.Options.Cap;
using grapher.Models.Options.LUT;
-using grapher.Models.Serialized;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Windows.Forms;
namespace grapher
@@ -21,7 +19,6 @@ namespace grapher
public static readonly LayoutBase Power = new PowerLayout();
public static readonly LayoutBase LUT = new LUTLayout();
public static readonly LayoutBase Off = new OffLayout();
- public static readonly LayoutBase Unsupported = new UnsupportedLayout();
#endregion Fields
@@ -30,14 +27,15 @@ namespace grapher
public AccelTypeOptions(
ComboBox accelDropdown,
CheckBoxOption gainSwitch,
- Option acceleration,
+ CapOptions classicCap,
+ CapOptions powerCap,
+ Option outputJump,
+ Option outputOffset,
Option decayRate,
Option growthRate,
Option smooth,
- Option scale,
- Option cap,
- Option weight,
- Option offset,
+ Option inputJump,
+ Option inputOffset,
Option limit,
Option powerClassic,
Option exponent,
@@ -66,17 +64,18 @@ namespace grapher
AccelDropdown.SelectedIndexChanged += new System.EventHandler(OnIndexChanged);
GainSwitch = gainSwitch;
- Acceleration = acceleration;
DecayRate = decayRate;
GrowthRate = growthRate;
Smooth = smooth;
- Scale = scale;
- Cap = cap;
- Weight = weight;
- Offset = offset;
+ ClassicCap = classicCap;
+ PowerCap = powerCap;
+ InputJump = inputJump;
+ InputOffset = inputOffset;
Limit = limit;
PowerClassic = powerClassic;
Exponent = exponent;
+ OutputJump = outputJump;
+ OutputOffset = outputOffset;
Midpoint = midpoint;
WriteButton = writeButton;
AccelTypeActiveValue = accelTypeActiveValue;
@@ -86,7 +85,7 @@ namespace grapher
AccelTypeActiveValue.Left = AccelDropdown.Left + AccelDropdown.Width;
AccelTypeActiveValue.Height = AccelDropdown.Height;
- GainSwitch.Left = Acceleration.Field.Left;
+ GainSwitch.Left = DecayRate.Field.Left;
LutPanel.Left = AccelDropdown.Left;
LutPanel.Width = AccelDropdown.Width + AccelTypeActiveValue.Width;
@@ -109,21 +108,23 @@ namespace grapher
public ActiveValueLabel AccelTypeActiveValue { get; }
- public Option Acceleration { get; }
-
public Option DecayRate { get; }
public Option GrowthRate { get; }
public Option Smooth { get; }
- public Option Scale { get; }
+ public CapOptions ClassicCap { get; }
+
+ public CapOptions PowerCap { get; }
+
+ public Option InputJump { get; }
- public Option Cap { get; }
+ public Option OutputJump { get; }
- public Option Weight { get; }
+ public Option InputOffset { get; }
- public Option Offset { get; }
+ public Option OutputOffset { get; }
public Option Limit { get; }
@@ -229,14 +230,15 @@ namespace grapher
AccelTypeActiveValue.Hide();
GainSwitch.Hide();
- Acceleration.Hide();
DecayRate.Hide();
GrowthRate.Hide();
Smooth.Hide();
- Scale.Hide();
- Cap.Hide();
- Weight.Hide();
- Offset.Hide();
+ ClassicCap.Hide();
+ PowerCap.Hide();
+ OutputOffset.Hide();
+ InputOffset.Hide();
+ InputJump.Hide();
+ OutputJump.Hide();
Limit.Hide();
PowerClassic.Hide();
Exponent.Hide();
@@ -262,21 +264,30 @@ namespace grapher
{
AccelerationType = AccelTypeFromSettings(ref args);
AccelTypeActiveValue.SetValue(AccelerationType.ActiveName);
- GainSwitch.SetActiveValue(args.legacy);
- Weight.SetActiveValue(args.weight);
- Cap.SetActiveValue(args.cap);
- Offset.SetActiveValue(args.offset);
- Acceleration.SetActiveValue(args.accelClassic);
+ GainSwitch.SetActiveValue(args.gain);
+ ClassicCap.SetActiveValues(
+ args.acceleration,
+ args.cap.x,
+ args.cap.y,
+ args.capMode);
+ PowerCap.SetActiveValues(
+ args.scale,
+ args.cap.x,
+ args.cap.y,
+ args.capMode);
+ InputJump.SetActiveValue(args.cap.x);
+ OutputJump.SetActiveValue(args.cap.y);
+ OutputOffset.SetActiveValue(args.outputOffset);
+ InputOffset.SetActiveValue(args.inputOffset);
DecayRate.SetActiveValue(args.decayRate);
GrowthRate.SetActiveValue(args.growthRate);
Smooth.SetActiveValue(args.smooth);
- Scale.SetActiveValue(args.scale);
Limit.SetActiveValue((args.mode == AccelMode.motivity) ? args.motivity : args.limit);
- PowerClassic.SetActiveValue(args.power);
- Exponent.SetActiveValue(args.exponent);
+ PowerClassic.SetActiveValue(args.exponentClassic);
+ Exponent.SetActiveValue(args.exponentPower);
Midpoint.SetActiveValue(args.midpoint);
- LutPanel.SetActiveValues(args.tableData.points, args.tableData.length);
- LutApply.SetActiveValue(args.tableData.velocity);
+ LutPanel.SetActiveValues(args.data, args.length, args.mode);
+ LutApply.SetActiveValue(args.gain);
}
public void ShowFull()
@@ -286,8 +297,8 @@ namespace grapher
AccelDropdown.Text = Constants.AccelDropDownDefaultFullText;
}
- Left = Acceleration.Left + Constants.DropDownLeftSeparation;
- Width = Acceleration.Width - Constants.DropDownLeftSeparation;
+ Left = DecayRate.Left + Constants.DropDownLeftSeparation;
+ Width = DecayRate.Width - Constants.DropDownLeftSeparation;
LutText.Expand();
HandleLUTOptionsOnResize();
@@ -300,25 +311,38 @@ namespace grapher
AccelDropdown.Text = Constants.AccelDropDownDefaultShortText;
}
- Left = Acceleration.Field.Left;
- Width = Acceleration.Field.Width;
+ Left = DecayRate.Field.Left;
+ Width = DecayRate.Field.Width;
LutText.Shorten();
}
public void SetArgs(ref AccelArgs args)
{
- if (AccelerationType == Unsupported) throw new NotImplementedException();
-
args.mode = AccelerationType.Mode;
- args.legacy = !GainSwitch.CheckBox.Checked;
+ args.gain = LutPanel.Visible ?
+ LutApply.ApplyType == LutApplyOptions.LutApplyType.Velocity :
+ GainSwitch.CheckBox.Checked;
- if (Acceleration.Visible) args.accelClassic = Acceleration.Field.Data;
if (DecayRate.Visible) args.decayRate = DecayRate.Field.Data;
if (GrowthRate.Visible) args.growthRate = GrowthRate.Field.Data;
if (Smooth.Visible) args.smooth = Smooth.Field.Data;
- if (Scale.Visible) args.scale = Scale.Field.Data;
- if (Cap.Visible) args.cap = Cap.Field.Data;
+ if (ClassicCap.Visible)
+ {
+ args.acceleration = ClassicCap.Slope.Field.Data;
+ args.cap.x = ClassicCap.In.Field.Data;
+ args.cap.y = ClassicCap.Out.Field.Data;
+ args.capMode = ClassicCap.CapTypeOptions.GetSelectedCapMode();
+ }
+ if (PowerCap.Visible)
+ {
+ args.scale = PowerCap.Slope.Field.Data;
+ args.cap.x = PowerCap.In.Field.Data;
+ args.cap.y = PowerCap.Out.Field.Data;
+ args.capMode = PowerCap.CapTypeOptions.GetSelectedCapMode();
+ }
+ if (InputJump.Visible) args.cap.x = InputJump.Field.Data;
+ if (OutputJump.Visible) args.cap.y = OutputJump.Field.Data;
if (Limit.Visible)
{
if (args.mode == AccelMode.motivity)
@@ -328,34 +352,43 @@ namespace grapher
else
{
args.limit = Limit.Field.Data;
- }
+ }
}
- if (PowerClassic.Visible) args.power = PowerClassic.Field.Data;
- if (Exponent.Visible)args.exponent = Exponent.Field.Data;
- if (Offset.Visible) args.offset = Offset.Field.Data;
+ if (PowerClassic.Visible) args.exponentClassic = PowerClassic.Field.Data;
+ if (Exponent.Visible) args.exponentPower = Exponent.Field.Data;
+ if (InputOffset.Visible) args.inputOffset = InputOffset.Field.Data;
+ if (OutputOffset.Visible) args.outputOffset = OutputOffset.Field.Data;
+
if (Midpoint.Visible) args.midpoint = Midpoint.Field.Data;
- if (Weight.Visible) args.weight = Weight.Field.Data;
if (LutPanel.Visible)
{
(var points, var length) = LutPanel.GetPoints();
- args.tableData.points = points;
- args.tableData.length = length;
+ args.length = length * 2;
+
+ for (int i = 0; i < length; i++)
+ {
+ ref var p = ref points[i];
+ var data_idx = i * 2;
+ args.data[data_idx] = p.x;
+ args.data[data_idx + 1] = p.y;
+ }
}
- if (LutApply.Visible) args.tableData.velocity = LutApply.ApplyType == LutApplyOptions.LutApplyType.Velocity;
+
}
public override void AlignActiveValues()
{
AccelTypeActiveValue.Align();
GainSwitch.AlignActiveValues();
- Acceleration.AlignActiveValues();
DecayRate.AlignActiveValues();
GrowthRate.AlignActiveValues();
Smooth.AlignActiveValues();
- Scale.AlignActiveValues();
- Cap.AlignActiveValues();
- Offset.AlignActiveValues();
- Weight.AlignActiveValues();
+ ClassicCap.AlignActiveValues();
+ PowerCap.AlignActiveValues();
+ OutputOffset.AlignActiveValues();
+ InputOffset.AlignActiveValues();
+ OutputJump.AlignActiveValues();
+ InputJump.AlignActiveValues();
Limit.AlignActiveValues();
PowerClassic.AlignActiveValues();
Exponent.AlignActiveValues();
@@ -367,7 +400,7 @@ namespace grapher
{
LutText.Left = AccelDropdown.Left;
LutPanel.Left = GainSwitch.Left - 100;
- LutPanel.Width = Acceleration.ActiveValueLabel.CenteringLabel.Right - LutPanel.Left;
+ LutPanel.Width = DecayRate.ActiveValueLabel.CenteringLabel.Right - LutPanel.Left;
LutApply.Left = LutPanel.Left;
LutApply.Width = AccelDropdown.Right - LutPanel.Left;
}
@@ -387,17 +420,18 @@ namespace grapher
AccelerationType.Layout(
GainSwitch,
- Acceleration,
+ ClassicCap,
+ PowerCap,
DecayRate,
GrowthRate,
Smooth,
- Scale,
- Cap,
- Weight,
- Offset,
+ InputJump,
+ InputOffset,
Limit,
PowerClassic,
Exponent,
+ OutputJump,
+ OutputOffset,
Midpoint,
LutText,
LutPanel,
@@ -407,19 +441,9 @@ namespace grapher
private LayoutBase AccelTypeFromSettings(ref AccelArgs args)
{
- if (args.spacedTableArgs.mode != SpacedTableMode.off)
- {
- if (!AccelDropdown.Items.Contains(Unsupported))
- {
- AccelDropdown.Items.Add(Unsupported);
- }
-
- return Unsupported;
- }
-
switch (args.mode)
{
- case AccelMode.classic: return (args.power == 2) ? Linear : Classic;
+ case AccelMode.classic: return (args.exponentClassic == 2) ? Linear : Classic;
case AccelMode.jump: return Jump;
case AccelMode.natural: return Natural;
case AccelMode.motivity: return Motivity;
diff --git a/grapher/Models/Options/ApplyOptions.cs b/grapher/Models/Options/ApplyOptions.cs
index 06854b8..4946414 100644
--- a/grapher/Models/Options/ApplyOptions.cs
+++ b/grapher/Models/Options/ApplyOptions.cs
@@ -15,7 +15,8 @@ namespace grapher.Models.Options
AccelOptionSet optionSetX,
AccelOptionSet optionSetY,
DirectionalityOptions directionalityOptions,
- OptionXY sensitivity,
+ Option sensitivity,
+ LockableOption yxRatio,
Option rotation,
Label lockXYLabel,
AccelCharts accelCharts)
@@ -34,6 +35,7 @@ namespace grapher.Models.Options
OptionSetX = optionSetX;
OptionSetY = optionSetY;
Sensitivity = sensitivity;
+ YToXRatio = yxRatio;
Rotation = rotation;
LockXYLabel = lockXYLabel;
AccelCharts = accelCharts;
@@ -44,7 +46,8 @@ namespace grapher.Models.Options
ByComponentVectorXYLock.CheckedChanged += new System.EventHandler(OnByComponentXYLockChecked);
ByComponentVectorXYLock.Checked = true;
- Rotation.SnapTo(Sensitivity);
+ YToXRatio.SnapTo(Sensitivity);
+ Rotation.SnapTo(YToXRatio);
EnableWholeApplication();
}
@@ -65,7 +68,9 @@ namespace grapher.Models.Options
public DirectionalityOptions Directionality { get; }
- public OptionXY Sensitivity { get; }
+ public Option Sensitivity { get; }
+
+ public LockableOption YToXRatio { get; }
public Option Rotation { get; }
@@ -81,30 +86,31 @@ namespace grapher.Models.Options
#region Methods
- public void SetArgs(ref Vec2<AccelArgs> args)
+ public void SetArgsFromActiveValues(ref AccelArgs argsX, ref AccelArgs argsY)
{
- OptionSetX.SetArgs(ref args.x);
+ OptionSetX.SetArgsFromActiveValues(ref argsX);
if (ByComponentVectorXYLock.Checked)
{
- OptionSetX.SetArgs(ref args.y);
+ OptionSetX.SetArgsFromActiveValues(ref argsY);
}
else
{
- OptionSetY.SetArgs(ref args.y);
+ OptionSetY.SetArgsFromActiveValues(ref argsY);
}
}
- public void SetActiveValues(DriverSettings settings)
+ public void SetActiveValues(Profile settings)
{
- Sensitivity.SetActiveValues(settings.sensitivity.x, settings.sensitivity.y);
+ Sensitivity.SetActiveValue(settings.sensitivity);
+ YToXRatio.SetActiveValue(settings.yxSensRatio);
Rotation.SetActiveValue(settings.rotation);
WholeVectorCheckBox.Checked = settings.combineMagnitudes;
ByComponentVectorCheckBox.Checked = !settings.combineMagnitudes;
- ByComponentVectorXYLock.Checked = settings.args.x.Equals(settings.args.y);
- OptionSetX.SetActiveValues(ref settings.args.x);
- OptionSetY.SetActiveValues(ref settings.args.y);
+ ByComponentVectorXYLock.Checked = settings.argsX.Equals(settings.argsY);
+ OptionSetX.SetActiveValues(ref settings.argsX);
+ OptionSetY.SetActiveValues(ref settings.argsY);
Directionality.SetActiveValues(settings);
@@ -210,8 +216,8 @@ namespace grapher.Models.Options
LockXYLabel.Width = (AccelCharts.Left - OptionSetX.ActiveValuesTitle.Left) / 2;
OptionSetX.ActiveValuesTitle.Width = LockXYLabel.Width;
LockXYLabel.Left = OptionSetX.ActiveValuesTitle.Left + OptionSetX.ActiveValuesTitle.Width;
- Sensitivity.Fields.LockCheckBox.Left = LockXYLabel.Left + LockXYLabel.Width / 2 - Sensitivity.Fields.LockCheckBox.Width / 2;
- ByComponentVectorXYLock.Left = Sensitivity.Fields.LockCheckBox.Left;
+ YToXRatio.LockBox.Left = LockXYLabel.Left + LockXYLabel.Width / 2 - YToXRatio.LockBox.Width / 2;
+ ByComponentVectorXYLock.Left = YToXRatio.LockBox.Left;
AlignActiveValues();
}
diff --git a/grapher/Models/Options/Cap/CapOptions.cs b/grapher/Models/Options/Cap/CapOptions.cs
new file mode 100644
index 0000000..68326e5
--- /dev/null
+++ b/grapher/Models/Options/Cap/CapOptions.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Windows.Forms;
+using static grapher.Models.Options.Cap.CapTypeOptions;
+
+namespace grapher.Models.Options.Cap
+{
+ public class CapOptions : OptionBase
+ {
+ #region Constants
+
+ public const string InCapLabel = "Cap: Input";
+ public const string OutCapLabel = "Cap: Output";
+
+ #endregion Constants
+
+ #region Fields
+
+ private int _top;
+
+ #endregion Fields
+
+ #region Constructors
+
+ public CapOptions(
+ CapTypeOptions capTypeOptions,
+ Option capIn,
+ Option capOut,
+ Option slope,
+ Option disableOptionInBoth = null,
+ CheckBoxOption disableInBoth = null)
+ {
+ CapTypeOptions = capTypeOptions;
+ In = capIn;
+ Out = capOut;
+ Slope = slope;
+ DisableOptionInBoth = disableOptionInBoth;
+ DisableInBoth = disableInBoth;
+
+ ShouldShow = true;
+ _top = Slope.Top;
+ BottomElement = In;
+ CapTypeOptions.OptionsDropdown.SelectedIndexChanged += OnCapTypeDropdownSelectedItemChanged;
+ CapTypeOptions.SelectedCapOption = InCap;
+
+ if (DisableInBoth != null)
+ {
+ DisableInBoth.CheckBox.CheckedChanged += OnDisableInBothCheckedChange;
+ }
+ }
+
+ #endregion Constructors
+
+ #region Properties
+
+ public CapTypeOptions CapTypeOptions { get; }
+
+ public Option In { get; }
+
+ public Option Out { get; }
+
+ public Option Slope { get; }
+
+ private Option DisableOptionInBoth { get; }
+
+ private CheckBoxOption DisableInBoth { get; }
+
+ public override int Left
+ {
+ get => In.Left;
+
+ set
+ {
+ In.Left = value;
+ Out.Left = value;
+ Slope.Left = value;
+ }
+ }
+
+ public override int Top
+ {
+ get => _top;
+ set
+ {
+ _top = value;
+ Layout(value);
+ }
+ }
+
+ public override int Height
+ {
+ get => BottomElement.Top + BottomElement.Height - Top;
+ }
+
+ public override int Width
+ {
+ get => CapTypeOptions.Width;
+
+ set
+ {
+ CapTypeOptions.Width = value;
+ In.Width = value;
+ Out.Width = value;
+ Slope.Width = value;
+ }
+ }
+
+ public override bool Visible
+ {
+ get => ShouldShow;
+ }
+
+ private bool ShouldShow { get; set; }
+
+ private IOption BottomElement { get; set; }
+
+ #endregion Properties
+
+ #region Methods
+
+ public override void AlignActiveValues()
+ {
+ Slope.AlignActiveValues();
+ CapTypeOptions.AlignActiveValues();
+ In.AlignActiveValues();
+ Out.AlignActiveValues();
+ }
+
+ public override void Show(string name)
+ {
+ ShouldShow = true;
+ Layout(Top, name);
+ }
+
+ public override void Hide()
+ {
+ ShouldShow = false;
+ CapTypeOptions.Hide();
+ Slope.Hide();
+ In.Hide();
+ Out.Hide();
+ }
+
+ public void SetActiveValues(
+ double scale,
+ double inCap,
+ double outCap,
+ CapMode capMode)
+ {
+ Slope.SetActiveValue(scale);
+ In.SetActiveValue(inCap);
+ Out.SetActiveValue(outCap);
+ CapTypeOptions.SetActiveValue(capMode);
+ }
+
+ private void Layout(int top, string name = null)
+ {
+ switch (CapTypeOptions.SelectedCapType)
+ {
+ case CapType.Input:
+ if (ShouldShow)
+ {
+ Slope.Show();
+ CapTypeOptions.Show(name);
+ ShowInCap();
+ Out.Hide();
+ }
+
+ Slope.Top = top;
+ CapTypeOptions.SnapTo(Slope);
+ In.SnapTo(CapTypeOptions);
+
+ BottomElement = In;
+ break;
+ case CapType.Output:
+ if (ShouldShow)
+ {
+ Slope.Show();
+ CapTypeOptions.Show(name);
+ In.Hide();
+ ShowOutCap();
+ }
+
+ Slope.Top = top;
+ CapTypeOptions.SnapTo(Slope);
+ Out.SnapTo(CapTypeOptions);
+
+ BottomElement = Out;
+ break;
+ case CapType.Both:
+ if (ShouldShow)
+ {
+ CapTypeOptions.Show(name);
+ Slope.Hide();
+ ShowInCap();
+ ShowOutCap();
+ }
+
+ CapTypeOptions.Top = top;
+ In.SnapTo(CapTypeOptions);
+ Out.SnapTo(In);
+
+ BottomElement = Out;
+ break;
+ }
+
+ DisableBuggedOptionIfApplicable();
+ }
+
+ private void DisableBuggedOptionIfApplicable()
+ {
+ if (DisableOptionInBoth != null)
+ {
+ if (CapTypeOptions.SelectedCapType == CapType.Both &&
+ DisableInBoth != null &&
+ !DisableInBoth.CheckBox.Checked)
+ {
+ DisableOptionInBoth.Field.SetToUnavailable();
+ }
+ else
+ {
+ DisableOptionInBoth.Field.SetToDefault();
+ }
+ }
+ }
+
+ private void ShowInCap()
+ {
+ In.Show(InCapLabel);
+ }
+
+ private void ShowOutCap()
+ {
+ Out.Show(OutCapLabel);
+ }
+
+ private void OnCapTypeDropdownSelectedItemChanged(object sender, EventArgs e)
+ {
+ Layout(Top);
+ CapTypeOptions.CheckIfDefault();
+ }
+
+ private void OnDisableInBothCheckedChange(object sender, EventArgs e)
+ {
+ DisableBuggedOptionIfApplicable();
+ }
+
+ #endregion Methods
+ }
+}
diff --git a/grapher/Models/Options/Cap/CapTypeOptions.cs b/grapher/Models/Options/Cap/CapTypeOptions.cs
new file mode 100644
index 0000000..6447feb
--- /dev/null
+++ b/grapher/Models/Options/Cap/CapTypeOptions.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace grapher.Models.Options.Cap
+{
+ public class CapTypeOptions : ComboBoxOptionsBase
+ {
+ #region Enum
+
+ public enum CapType
+ {
+ Input,
+ Output,
+ Both,
+ }
+
+ #endregion Enum
+
+ #region Classes
+
+ public class CapTypeOption
+ {
+ public CapType Type { get; set; }
+
+ public string Name => Type.ToString();
+
+ public override string ToString() => Name;
+ }
+
+ #endregion Classes
+
+ #region Static
+
+ public static readonly CapTypeOption InCap = new CapTypeOption
+ {
+ Type = CapType.Input,
+ };
+
+ public static readonly CapTypeOption OutCap = new CapTypeOption
+ {
+ Type = CapType.Output,
+ };
+
+ public static readonly CapTypeOption BothCap = new CapTypeOption
+ {
+ Type = CapType.Both,
+ };
+
+ public static readonly CapTypeOption[] AllCapTypeOptions = new CapTypeOption[]
+ {
+ InCap,
+ OutCap,
+ BothCap
+ };
+
+ #endregion Static
+
+ #region Constructors
+
+ public CapTypeOptions(
+ Label label,
+ ComboBox dropdown,
+ ActiveValueLabel activeValueLabel,
+ int left)
+ : base(
+ label,
+ dropdown,
+ activeValueLabel)
+ {
+ OptionsDropdown.Items.AddRange(
+ new CapTypeOption[]
+ {
+ InCap,
+ OutCap,
+ BothCap
+ });
+
+ Default = OutCap;
+
+ label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ label.Left = left;
+ label.Width = OptionsDropdown.Left - left - Constants.OptionLabelBoxSeperation;
+ label.Height = OptionsDropdown.Height;
+ }
+
+ #endregion Constructors
+
+ #region Properties
+
+ public CapType SelectedCapType => SelectedCapOption.Type;
+
+ public CapTypeOption SelectedCapOption
+ {
+ get
+ {
+ return OptionsDropdown.SelectedItem as CapTypeOption;
+ }
+ set
+ {
+ OptionsDropdown.SelectedItem = value;
+ }
+ }
+
+ private CapTypeOption Default { get; set; }
+
+ public CapMode GetSelectedCapMode()
+ {
+ switch(SelectedCapType)
+ {
+ case CapType.Output: return CapMode.output;
+ case CapType.Both: return CapMode.in_out;
+ case CapType.Input:
+ default: return CapMode.input;
+ }
+ }
+
+ #endregion Properties
+
+ #region Methods
+
+ public static CapTypeOption CapTypeOptionFromSettings(CapMode capMode)
+ {
+ switch (capMode)
+ {
+ case CapMode.output:
+ return OutCap;
+ case CapMode.in_out:
+ return BothCap;
+ case CapMode.input:
+ default:
+ return InCap;
+ }
+ }
+
+ public void SetActiveValue(CapMode capMode)
+ {
+ Default = CapTypeOptionFromSettings(capMode);
+ SelectedCapOption = Default;
+ ActiveValueLabel.SetValue(SelectedCapOption.Name);
+ }
+
+ public void CheckIfDefault()
+ {
+ if (SelectedCapOption.Equals(Default))
+ {
+ OptionsDropdown.ForeColor = System.Drawing.Color.Gray;
+ }
+ else
+ {
+ OptionsDropdown.ForeColor = System.Drawing.Color.Black;
+ }
+ }
+
+ #endregion Methods
+ }
+}
diff --git a/grapher/Models/Options/CheckBoxOption.cs b/grapher/Models/Options/CheckBoxOption.cs
index abf96d3..8c125ec 100644
--- a/grapher/Models/Options/CheckBoxOption.cs
+++ b/grapher/Models/Options/CheckBoxOption.cs
@@ -2,6 +2,9 @@
namespace grapher.Models.Options
{
+ /// <summary>
+ /// This is an option type that is just a checkbox.
+ /// </summary>
public class CheckBoxOption : OptionBase
{
public CheckBoxOption(
@@ -99,10 +102,10 @@ namespace grapher.Models.Options
ActiveValueLabel.Show();
}
- public void SetActiveValue(bool legacy)
+ public void SetActiveValue(bool gain)
{
- CheckBox.Checked = !legacy;
- var activeValueString = legacy ? "Legacy" : "Gain";
+ CheckBox.Checked = gain;
+ var activeValueString = gain ? "Gain" : "Legacy";
ActiveValueLabel.SetValue(activeValueString);
}
}
diff --git a/grapher/Models/Options/ComboBoxOptionsBase.cs b/grapher/Models/Options/ComboBoxOptionsBase.cs
new file mode 100644
index 0000000..6999e99
--- /dev/null
+++ b/grapher/Models/Options/ComboBoxOptionsBase.cs
@@ -0,0 +1,124 @@
+using System.Windows.Forms;
+
+namespace grapher.Models.Options
+{
+ public abstract class ComboBoxOptionsBase : OptionBase
+ {
+ #region Constructors
+
+ public ComboBoxOptionsBase(
+ Label label,
+ ComboBox dropdown,
+ ActiveValueLabel activeValueLabel)
+ {
+ OptionsDropdown = dropdown;
+ OptionsDropdown.Items.Clear();
+
+ Label = label;
+ Label.AutoSize = false;
+ Label.Width = 50;
+
+ ActiveValueLabel = activeValueLabel;
+ }
+
+ #endregion Constructors
+
+ #region Properties
+
+ public Label Label { get; }
+
+ public ActiveValueLabel ActiveValueLabel { get; }
+
+ public ComboBox OptionsDropdown { get; }
+
+ public override bool Visible
+ {
+ get
+ {
+ return Label.Visible || ShouldShow;
+ }
+ }
+
+ public override int Left
+ {
+ get
+ {
+ return Label.Left;
+ }
+ set
+ {
+ Label.Left = value;
+ OptionsDropdown.Left = Label.Left + Label.Width + Constants.OptionVerticalSeperation;
+ }
+ }
+
+ public override int Height
+ {
+ get
+ {
+ return OptionsDropdown.Height;
+ }
+ }
+
+ public override int Top
+ {
+ get
+ {
+ return OptionsDropdown.Top;
+ }
+ set
+ {
+ OptionsDropdown.Top = value;
+ Label.Top = (OptionsDropdown.Height - Label.Height) / 2 + OptionsDropdown.Top;
+ ActiveValueLabel.Top = value;
+ }
+ }
+
+ public override int Width
+ {
+ get
+ {
+ return Label.Width;
+ }
+ set
+ {
+ OptionsDropdown.Width = value - Label.Width - Constants.OptionLabelBoxSeperation;
+ }
+ }
+
+ protected bool ShouldShow { get; set; }
+
+ #endregion Properties
+
+ #region Methods
+
+ public override void Hide()
+ {
+ Label.Hide();
+ OptionsDropdown.Hide();
+ ActiveValueLabel.Hide();
+ ShouldShow = false;
+ }
+
+ public override void Show(string labelText)
+ {
+ Label.Show();
+
+ if (!string.IsNullOrWhiteSpace(labelText))
+ {
+ Label.Text = labelText;
+ }
+
+ OptionsDropdown.Show();
+ ActiveValueLabel.Show();
+ ShouldShow = true;
+ }
+
+ public override void AlignActiveValues()
+ {
+ ActiveValueLabel.Align();
+ }
+
+ #endregion Methods
+ }
+}
diff --git a/grapher/Models/Options/Directionality/DirectionalityOptions.cs b/grapher/Models/Options/Directionality/DirectionalityOptions.cs
index 9288132..35d2575 100644
--- a/grapher/Models/Options/Directionality/DirectionalityOptions.cs
+++ b/grapher/Models/Options/Directionality/DirectionalityOptions.cs
@@ -70,17 +70,16 @@ namespace grapher.Models.Options.Directionality
private bool IsHidden { get; set; }
- public DomainArgs GetDomainArgs()
+ public Tuple<Vec2<double>, double> GetDomainArgs()
{
- return new DomainArgs
+ var weights = new Vec2<double>
{
- domainXY = new Vec2<double>
- {
- x = Domain.Fields.X,
- y = Domain.Fields.Y,
- },
- lpNorm = ByComponentCheckBox.Checked ? 2 : LpNorm.Field.Data
+ x = Domain.Fields.X,
+ y = Domain.Fields.Y
};
+ double p = ByComponentCheckBox.Checked ? 2 : LpNorm.Field.Data;
+
+ return new Tuple<Vec2<double>, double>(weights, p);
}
public Vec2<double> GetRangeXY()
@@ -92,14 +91,14 @@ namespace grapher.Models.Options.Directionality
};
}
- public void SetActiveValues(DriverSettings settings)
+ public void SetActiveValues(Profile settings)
{
- Domain.SetActiveValues(settings.domainArgs.domainXY.x, settings.domainArgs.domainXY.y);
+ Domain.SetActiveValues(settings.domainXY.x, settings.domainXY.y);
Range.SetActiveValues(settings.rangeXY.x, settings.rangeXY.y);
if (settings.combineMagnitudes)
{
- LpNorm.SetActiveValue(settings.domainArgs.lpNorm);
+ LpNorm.SetActiveValue(settings.lpNorm);
}
else
{
diff --git a/grapher/Models/Options/LUT/LUTPanelOptions.cs b/grapher/Models/Options/LUT/LUTPanelOptions.cs
index 3690c76..eedcfa8 100644
--- a/grapher/Models/Options/LUT/LUTPanelOptions.cs
+++ b/grapher/Models/Options/LUT/LUTPanelOptions.cs
@@ -111,15 +111,26 @@ namespace grapher.Models.Options.LUT
// Nothing to do here.
}
- public void SetActiveValues(IEnumerable<Vec2<float>> activePoints, int length)
+ public void SetActiveValues(IEnumerable<float> rawData, int length, AccelMode mode)
{
- if (length > 0 && activePoints.First().x != 0)
+ if (mode == AccelMode.lut && length > 1 && rawData.First() != 0)
{
- ActiveValuesTextBox.Text = PointsToActiveValuesText(activePoints, length);
+ var pointsLen = length / 2;
+ var points = new Vec2<float>[pointsLen];
+ for (int i = 0; i < pointsLen; i++)
+ {
+ var data_idx = i * 2;
+ points[i] = new Vec2<float>
+ {
+ x = rawData.ElementAt(data_idx),
+ y = rawData.ElementAt(data_idx + 1)
+ };
+ }
+ ActiveValuesTextBox.Text = PointsToActiveValuesText(points, pointsLen);
if (string.IsNullOrWhiteSpace(PointsTextBox.Text))
{
- PointsTextBox.Text = PointsToEntryTextBoxText(activePoints, length);
+ PointsTextBox.Text = PointsToEntryTextBoxText(points, pointsLen);
}
}
else
@@ -135,14 +146,12 @@ namespace grapher.Models.Options.LUT
private static (Vec2<float>[], int length) UserTextToPoints(string userText)
{
- const int MaxPoints = 256;
-
if (string.IsNullOrWhiteSpace(userText))
{
throw new ApplicationException("Text must be entered in text box to fill Look Up Table.");
}
- Vec2<float>[] points = new Vec2<float>[MaxPoints];
+ Vec2<float>[] points = new Vec2<float>[AccelArgs.MaxLutPoints];
var userTextSplit = userText.Trim().Trim(';').Split(';');
int index = 0;
@@ -155,9 +164,9 @@ namespace grapher.Models.Options.LUT
throw new ApplicationException("At least 2 points required");
}
- if (pointsCount > MaxPoints)
+ if (pointsCount > AccelArgs.MaxLutPoints)
{
- throw new ApplicationException($"Number of points exceeds max ({MaxPoints})");
+ throw new ApplicationException($"Number of points exceeds max ({AccelArgs.MaxLutPoints})");
}
foreach(var pointEntry in userTextSplit)
diff --git a/grapher/Models/Options/LUT/LutApplyOptions.cs b/grapher/Models/Options/LUT/LutApplyOptions.cs
index 7d8c737..61cae61 100644
--- a/grapher/Models/Options/LUT/LutApplyOptions.cs
+++ b/grapher/Models/Options/LUT/LutApplyOptions.cs
@@ -7,10 +7,9 @@ using System.Windows.Forms;
namespace grapher.Models.Options.LUT
{
- public class LutApplyOptions : OptionBase
+ public class LutApplyOptions : ComboBoxOptionsBase
{
- public const string LUTApplyOptionsLabelText = "Apply as:";
- public const int LUTApplyLabelDropdownSeparation = 4;
+ #region Enum
public enum LutApplyType
{
@@ -18,6 +17,10 @@ namespace grapher.Models.Options.LUT
Velocity
}
+ #endregion Enum
+
+ #region Classes
+
public class LutApplyOption
{
public LutApplyType Type { get; set; }
@@ -27,6 +30,10 @@ namespace grapher.Models.Options.LUT
public override string ToString() => Name;
}
+ #endregion Classes
+
+ #region Static
+
public static readonly LutApplyOption Sensitivity = new LutApplyOption
{
Type = LutApplyType.Sensitivity,
@@ -37,129 +44,58 @@ namespace grapher.Models.Options.LUT
Type = LutApplyType.Velocity,
};
+ #endregion Static
+
+ #region Constructors
+
public LutApplyOptions(
Label label,
ComboBox applyOptionsDropdown,
ActiveValueLabel lutApplyActiveValue)
+ : base(
+ label,
+ applyOptionsDropdown,
+ lutApplyActiveValue)
{
- ApplyOptions = applyOptionsDropdown;
- ApplyOptions.Items.Clear();
- ApplyOptions.Items.AddRange(
+ OptionsDropdown.Items.AddRange(
new LutApplyOption[]
{
Sensitivity,
Velocity,
});
+ }
- Label = label;
- Label.Text = LUTApplyOptionsLabelText;
- Label.AutoSize = false;
- Label.Width = 50;
+ #endregion Constructors
- ActiveValueLabel = lutApplyActiveValue;
- }
+ #region Properties
public LutApplyType ApplyType { get => ApplyOption.Type; }
public LutApplyOption ApplyOption {
get
{
- return ApplyOptions.SelectedItem as LutApplyOption;
- }
- set
- {
- ApplyOptions.SelectedItem = value;
- }
- }
-
- public Label Label { get; }
-
- public ActiveValueLabel ActiveValueLabel { get; }
-
- public ComboBox ApplyOptions { get; }
-
- public override bool Visible
- {
- get
- {
- return Label.Visible || ShouldShow;
- }
- }
-
- public override int Left
- {
- get
- {
- return Label.Left;
+ return OptionsDropdown.SelectedItem as LutApplyOption;
}
set
{
- Label.Left = value;
- ApplyOptions.Left = Label.Left + Label.Width + LUTApplyLabelDropdownSeparation;
+ OptionsDropdown.SelectedItem = value;
}
}
- public override int Height
- {
- get
- {
- return Label.Height;
- }
- }
+ #endregion Properties
- public override int Top
- {
- get
- {
- return Label.Top;
- }
- set
- {
- ApplyOptions.Top = value;
- Label.Top = (ApplyOptions.Height - Label.Height) / 2 + ApplyOptions.Top;
- ActiveValueLabel.Top = value;
- }
- }
+ #region Methods
- public override int Width
+ public static LutApplyOption ApplyOptionFromSettings(bool applyAsVelocity)
{
- get
- {
- return Label.Width;
- }
- set
+ if (applyAsVelocity)
{
- ApplyOptions.Width = value - Label.Width - Constants.OptionLabelBoxSeperation;
+ return Velocity;
}
- }
-
- private bool ShouldShow { get; set; }
-
- public override void Hide()
- {
- Label.Hide();
- ApplyOptions.Hide();
- ActiveValueLabel.Hide();
- ShouldShow = false;
- }
-
- public override void Show(string labelText)
- {
- Label.Show();
-
- if (!string.IsNullOrWhiteSpace(labelText))
+ else
{
- Label.Text = labelText;
+ return Sensitivity;
}
-
- ApplyOptions.Show();
- ActiveValueLabel.Show();
- ShouldShow = true;
- }
-
- public override void AlignActiveValues()
- {
- ActiveValueLabel.Align();
}
public void SetActiveValue(bool applyAsVelocity)
@@ -168,16 +104,6 @@ namespace grapher.Models.Options.LUT
ActiveValueLabel.SetValue(ApplyOption.Name);
}
- public LutApplyOption ApplyOptionFromSettings(bool applyAsVelocity)
- {
- if (applyAsVelocity)
- {
- return Velocity;
- }
- else
- {
- return Sensitivity;
- }
- }
+ #endregion Methods
}
}
diff --git a/grapher/Models/Options/LockableOption.cs b/grapher/Models/Options/LockableOption.cs
new file mode 100644
index 0000000..6e78783
--- /dev/null
+++ b/grapher/Models/Options/LockableOption.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace grapher.Models.Options
+{
+ /// <summary>
+ /// This is an option type that is a regular option with a checkbox that disables it.
+ /// </summary>
+ public class LockableOption : OptionBase
+ {
+ public LockableOption(
+ Option option,
+ CheckBox checkBox,
+ int lockedvalue)
+ {
+ Option = option;
+ LockBox = checkBox;
+ LockedValue = lockedvalue;
+
+ LockBox.Click += OnLockedBoxClicked;
+ LockBox.AutoCheck = false;
+
+ Option.Field.SetNewDefault(LockedValue);
+ SetLocked();
+ }
+
+ public Option Option { get; }
+
+ public CheckBox LockBox { get; }
+
+ public int LockedValue { get; }
+
+ public override int Left
+ {
+ get => Option.Left;
+
+ set
+ {
+ Option.Left = value;
+ }
+ }
+
+ public override int Top
+ {
+ get => Option.Top;
+
+ set
+ {
+ Option.Top = value;
+ LockBox.Top = value;
+ }
+ }
+
+ public override int Width
+ {
+ get => Option.Width;
+
+ set
+ {
+ Option.Width = value;
+ }
+ }
+
+ public override int Height
+ {
+ get => Option.Height;
+ }
+
+ public override bool Visible
+ {
+ get => Option.Visible;
+ }
+
+ public double Value
+ {
+ get => LockBox.Checked ? LockedValue : Option.Field.Data;
+ }
+
+ public void SetActiveValue(double activeValue)
+ {
+ Option.SetActiveValue(activeValue);
+
+ if (activeValue == LockedValue)
+ {
+ SetLocked();
+ }
+ else
+ {
+ SetUnlocked();
+ }
+ }
+
+ public override void AlignActiveValues()
+ {
+ Option.AlignActiveValues();
+ }
+
+ public override void Hide()
+ {
+ Option.Hide();
+ LockBox.Hide();
+ }
+
+ public override void Show(string Name)
+ {
+ Option.Show(Name);
+ LockBox.Show();
+ }
+ private void SetLocked()
+ {
+ LockBox.Checked = true;
+ Option.Field.SetToUnavailable();
+ }
+
+ private void SetUnlocked()
+ {
+ LockBox.Checked = false;
+ Option.Field.SetToDefault();
+ }
+
+ private void OnLockedBoxClicked(object sender, EventArgs e)
+ {
+ if (LockBox.Checked)
+ {
+ SetUnlocked();
+ }
+ else
+ {
+ SetLocked();
+ }
+ }
+ }
+}
diff --git a/grapher/Models/Options/SwitchOption.cs b/grapher/Models/Options/SwitchOption.cs
new file mode 100644
index 0000000..79991c1
--- /dev/null
+++ b/grapher/Models/Options/SwitchOption.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace grapher.Models.Options
+{
+ public class SwitchOption : OptionBase
+ {
+
+ #region Constructors
+
+ public SwitchOption(
+ Label label,
+ CheckBox firstCheckBox,
+ CheckBox secondCheckBox,
+ ActiveValueLabel activeValueLabel,
+ int left)
+ {
+ Label = label;
+ First = firstCheckBox;
+ Second = secondCheckBox;
+ ActiveValueLabel = activeValueLabel;
+ Left = left;
+
+ label.AutoSize = false;
+ label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ label.Width = First.Left - left - Constants.OptionLabelBoxSeperation;
+ label.Height = First.Height;
+
+ ActiveValueLabel.Height = First.Height;
+
+ First.CheckedChanged += OnFirstCheckedChange;
+ Second.CheckedChanged += OnSecondCheckedChange;
+
+ First.Checked = true;
+ Second.Left = First.Left + First.Width + Constants.OptionLabelBoxSeperation;
+ Show(string.Empty);
+ }
+
+ #endregion Constructors
+
+ #region Properties
+
+ public Label Label { get; }
+
+ public CheckBox First { get; }
+
+ public CheckBox Second { get; }
+
+ public ActiveValueLabel ActiveValueLabel { get; }
+
+ public override int Height
+ {
+ get => Label.Height;
+ }
+
+ public override int Left
+ {
+ get => Label.Left;
+ set
+ {
+ Label.Left = value;
+ }
+ }
+
+ public override bool Visible
+ {
+ get => ShouldShow;
+ }
+
+ public override int Width
+ {
+ get => Second.Left + Second.Width - Label.Left;
+ set
+ {
+ }
+ }
+
+ public override int Top
+ {
+ get => Label.Top;
+ set
+ {
+ Label.Top = value;
+ First.Top = value;
+ Second.Top = value;
+ ActiveValueLabel.Top = value;
+ }
+ }
+
+ private bool ShouldShow { get; set; }
+
+ #endregion Properties
+
+ #region Methods
+
+ public override void AlignActiveValues()
+ {
+ ActiveValueLabel.Align();
+ }
+
+ public override void Hide()
+ {
+ ShouldShow = false;
+
+ Label.Hide();
+ First.Hide();
+ Second.Hide();
+ ActiveValueLabel.Hide();
+ }
+
+ public override void Show(string name)
+ {
+ ShouldShow = true;
+
+ if (!string.IsNullOrWhiteSpace(name))
+ {
+ Label.Text = name;
+ }
+
+ Label.Show();
+ First.Show();
+ Second.Show();
+ ActiveValueLabel.Show();
+ }
+
+ public void SetActiveValue(bool shouldFirstBeChecked)
+ {
+ if (shouldFirstBeChecked)
+ {
+ First.Checked = true;
+ ActiveValueLabel.SetValue(First.Text);
+ }
+ else
+ {
+ Second.Checked = true;
+ ActiveValueLabel.SetValue(Second.Text);
+ }
+ }
+
+ private void OnFirstCheckedChange(object sender, EventArgs e)
+ {
+ if (First.Checked)
+ {
+ Second.Checked = false;
+ }
+ }
+
+ private void OnSecondCheckedChange(object sender, EventArgs e)
+ {
+ if (Second.Checked)
+ {
+ First.Checked = false;
+ }
+ }
+
+ #endregion Methods
+ }
+}
diff --git a/grapher/Models/Serialized/SettingsManager.cs b/grapher/Models/Serialized/SettingsManager.cs
index 346bc9b..43550c5 100644
--- a/grapher/Models/Serialized/SettingsManager.cs
+++ b/grapher/Models/Serialized/SettingsManager.cs
@@ -6,6 +6,8 @@ using System.Threading;
using System.Text;
using System.Drawing;
using grapher.Models.Devices;
+using System.Collections.Generic;
+using System.Linq;
namespace grapher.Models.Serialized
{
@@ -14,14 +16,12 @@ namespace grapher.Models.Serialized
#region Constructors
public SettingsManager(
- ManagedAccel activeAccel,
Field dpiField,
Field pollRateField,
ToolStripMenuItem autoWrite,
ToolStripMenuItem showLastMouseMove,
ToolStripMenuItem showVelocityAndGain,
- ToolStripMenuItem streamingMode,
- DeviceIDManager deviceIDManager)
+ ToolStripMenuItem streamingMode)
{
DpiField = dpiField;
PollRateField = pollRateField;
@@ -29,9 +29,9 @@ namespace grapher.Models.Serialized
ShowLastMouseMoveMenuItem = showLastMouseMove;
ShowVelocityAndGainMoveMenuItem = showVelocityAndGain;
StreamingModeMenuItem = streamingMode;
- DeviceIDManager = deviceIDManager;
- SetActiveFields(activeAccel);
+ SystemDevices = new List<MultiHandleDevice>();
+ ActiveNormTaggedHandles = new List<(IntPtr, bool)>();
GuiSettings = GUISettings.MaybeLoad();
@@ -45,43 +45,92 @@ namespace grapher.Models.Serialized
UpdateFieldsFromGUISettings();
}
- UserSettings = InitUserSettings();
+ UserConfigField = InitActiveAndGetUserConfig();
}
#endregion Constructors
+ #region Fields
+
+ private EventHandler DeviceChangeField;
+
+ private DriverConfig ActiveConfigField;
+ private DriverConfig UserConfigField;
+
+ #endregion Fields
+
#region Properties
public GUISettings GuiSettings { get; private set; }
- public ManagedAccel ActiveAccel { get; private set; }
+ public event EventHandler DeviceChange
+ {
+ add => DeviceChangeField += value;
+ remove => DeviceChangeField -= value;
+ }
+
+ public DriverConfig ActiveConfig
+ {
+ get => ActiveConfigField;
+
+ private set
+ {
+ if (ActiveConfigField != value)
+ {
+ ActiveConfigField = value;
+ ActiveProfileNamesSet = new HashSet<string>(value.profiles.Select(p => p.name));
+ }
+ }
+ }
- public ExtendedSettings ActiveSettings { get; private set; }
+ public Profile ActiveProfile
+ {
+ get => ActiveConfigField.profiles[0];
+ private set => ActiveConfigField.SetProfileAt(0, value);
+ }
- public DriverSettings UserSettings { get; private set; }
+ public ManagedAccel ActiveAccel
+ {
+ get => ActiveConfig.accels[0];
+ }
+
+ public DriverConfig UserConfig
+ {
+ get => UserConfigField;
+ private set => UserConfigField = value;
+ }
+
+ public Profile UserProfile
+ {
+ get => UserConfigField.profiles[0];
+ private set => UserConfigField.SetProfileAt(0, value);
+ }
+
+ public HashSet<string> ActiveProfileNamesSet { get; private set; }
public Field DpiField { get; private set; }
public Field PollRateField { get; private set; }
- public DeviceIDManager DeviceIDManager { get; }
+ public IList<MultiHandleDevice> SystemDevices { get; private set; }
+
+ public List<(IntPtr, bool)> ActiveNormTaggedHandles { get; }
private ToolStripMenuItem AutoWriteMenuItem { get; set; }
private ToolStripMenuItem ShowLastMouseMoveMenuItem { get; set; }
private ToolStripMenuItem ShowVelocityAndGainMoveMenuItem { get; set; }
+
private ToolStripMenuItem StreamingModeMenuItem{ get; set; }
#endregion Properties
#region Methods
- public void DisableDriver()
+ public void ResetDriver()
{
- var defaultSettings = new ExtendedSettings();
- ActiveSettings = defaultSettings;
- ActiveAccel.Settings = defaultSettings;
- new Thread(() => ActiveAccel.Activate()).Start();
+ ActiveConfig = DriverConfig.GetDefault();
+ new Thread(() => DriverConfig.Deactivate()).Start();
}
public void UpdateFieldsFromGUISettings()
@@ -94,36 +143,44 @@ namespace grapher.Models.Serialized
AutoWriteMenuItem.Checked = GuiSettings.AutoWriteToDriverOnStartup;
}
- public SettingsErrors TryActivate(DriverSettings settings)
+ public bool TryActivate(Profile settings, out string errors)
{
- var errors = new SettingsErrors(settings);
+ var old = UserProfile;
+ UserProfile = settings;
+ bool success = TryActivate(UserConfig, out errors);
+ if (!success)
+ {
+ UserProfile = old;
+ }
+ return success;
+ }
+
+ public bool TryActivate(DriverConfig settings, out string errors)
+ {
+ errors = settings.Errors();
- if (errors.Empty())
+ if (errors == null)
{
GuiSettings = MakeGUISettingsFromFields();
GuiSettings.Save();
- UserSettings = settings;
- File.WriteAllText(Constants.DefaultSettingsFileName, RaConvert.Settings(settings));
+ UserConfig = settings;
+ ActiveConfig = settings;
+ File.WriteAllText(Constants.DefaultSettingsFileName, settings.ToJSON());
- ActiveSettings = new ExtendedSettings(settings);
- ActiveAccel.Settings = ActiveSettings;
-
- new Thread(() => ActiveAccel.Activate()).Start();
+ new Thread(() => ActiveConfig.Activate()).Start();
}
- return errors;
+ return errors == null;
}
- public void SetHiddenOptions(DriverSettings settings)
+ public void SetHiddenOptions(Profile settings)
{
- settings.snap = UserSettings.snap;
- settings.maximumSpeed = UserSettings.maximumSpeed;
- settings.minimumSpeed = UserSettings.minimumSpeed;
- settings.minimumTime = UserSettings.minimumTime;
- settings.maximumTime = UserSettings.maximumTime;
- settings.ignore = UserSettings.ignore;
- settings.directionalMultipliers = UserSettings.directionalMultipliers;
+ settings.snap = UserProfile.snap;
+ settings.maximumSpeed = UserProfile.maximumSpeed;
+ settings.minimumSpeed = UserProfile.minimumSpeed;
+ settings.lrSensRatio = UserProfile.lrSensRatio;
+ settings.udSensRatio = UserProfile.udSensRatio;
}
public GUISettings MakeGUISettingsFromFields()
@@ -139,33 +196,108 @@ namespace grapher.Models.Serialized
};
}
- public bool TableActive()
+ public void SetActiveHandles()
{
- return ActiveSettings.tables.x != null || ActiveSettings.tables.y != null;
+ ActiveNormTaggedHandles.Clear();
+
+ bool ActiveProfileIsFirst = ActiveProfile == ActiveConfig.profiles[0];
+
+ foreach (var sysDev in SystemDevices)
+ {
+ void AddHandlesFromSysDev(bool normalized)
+ {
+ ActiveNormTaggedHandles.AddRange(sysDev.handles.Select(h => (h, normalized)));
+ }
+
+ var settings = ActiveConfig.devices.Find(d => d.id == sysDev.id);
+
+ if (settings is null)
+ {
+ if (ActiveProfileIsFirst && !ActiveConfig.defaultDeviceConfig.disable)
+ {
+ AddHandlesFromSysDev(ActiveConfig.defaultDeviceConfig.dpi > 0);
+ }
+ }
+ else if (!settings.config.disable &&
+ ((ActiveProfileIsFirst &&
+ (string.IsNullOrEmpty(settings.profile) ||
+ !ActiveProfileNamesSet.Contains(settings.profile))) ||
+ ActiveProfile.name == settings.profile))
+ {
+ AddHandlesFromSysDev(settings.config.dpi > 0);
+ }
+ }
+ }
+
+ public void Submit(DeviceConfig newDefaultConfig, DeviceDialogItem[] items)
+ {
+ UserConfig.defaultDeviceConfig = newDefaultConfig;
+ foreach (var item in items)
+ {
+ if (item.overrideDefaultConfig)
+ {
+ if (item.oldSettings is null)
+ {
+ UserConfig.devices.Add(
+ new DeviceSettings
+ {
+ name = item.device.name,
+ profile = item.newProfile,
+ id = item.device.id,
+ config = item.newConfig
+ });
+ }
+ else
+ {
+ item.oldSettings.config = item.newConfig;
+ item.oldSettings.profile = item.newProfile;
+ }
+ }
+ else if (!(item.oldSettings is null))
+ {
+ UserConfig.devices.Remove(item.oldSettings);
+ }
+ }
}
- public void SetActiveFields(ManagedAccel activeAccel)
+ public void OnProfileSelectionChange()
{
- ActiveAccel = activeAccel;
- ActiveSettings = activeAccel.Settings;
+ SetActiveHandles();
}
- private DriverSettings InitUserSettings()
+ public void OnDeviceChangeMessage()
+ {
+ SystemDevices = MultiHandleDevice.GetList();
+ SetActiveHandles();
+
+ DeviceChangeField?.Invoke(this, EventArgs.Empty);
+ }
+
+ private DriverConfig InitActiveAndGetUserConfig()
{
var path = Constants.DefaultSettingsFileName;
if (File.Exists(path))
{
try
{
- DriverSettings settings = RaConvert.Settings(File.ReadAllText(path));
+ var (cfg, err) = DriverConfig.Convert(File.ReadAllText(path));
- if (!GuiSettings.AutoWriteToDriverOnStartup ||
- TableActive() ||
- TryActivate(settings).Empty())
+ if (err == null)
{
- return settings;
+ if (GuiSettings.AutoWriteToDriverOnStartup)
+ {
+ if (!TryActivate(cfg, out string _))
+ {
+ throw new Exception("deserialization succeeded but TryActivate failed");
+ }
+ }
+ else
+ {
+ ActiveConfig = DriverConfig.GetActive();
+ }
+
+ return cfg;
}
-
}
catch (JsonException e)
{
@@ -173,17 +305,9 @@ namespace grapher.Models.Serialized
}
}
- if (!TableActive())
- {
- File.WriteAllText(path, RaConvert.Settings(ActiveSettings.baseSettings));
- return ActiveSettings.baseSettings;
- }
- else
- {
- var defaultSettings = new DriverSettings();
- File.WriteAllText(path, RaConvert.Settings(defaultSettings));
- return defaultSettings;
- }
+ ActiveConfig = DriverConfig.GetActive();
+ File.WriteAllText(path, ActiveConfig.ToJSON());
+ return ActiveConfig;
}
#endregion Methods
diff --git a/grapher/grapher.csproj b/grapher/grapher.csproj
index 7b0ab02..51c7fb6 100644
--- a/grapher/grapher.csproj
+++ b/grapher/grapher.csproj
@@ -78,6 +78,9 @@
<DependentUpon>AboutBox.cs</DependentUpon>
</Compile>
<Compile Include="Constants\Constants.cs" />
+ <Compile Include="DeviceMenuForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
<Compile Include="Layouts\LUTLayout.cs" />
<Compile Include="Layouts\MotivityLayout.cs" />
<Compile Include="Layouts\JumpLayout.cs" />
@@ -103,8 +106,7 @@
<Compile Include="Models\Charts\EstimatedPoints.cs" />
<Compile Include="Models\Charts\ChartState\XYOneGraphState.cs" />
<Compile Include="Models\Charts\ChartState\XYTwoGraphState.cs" />
- <Compile Include="Models\Devices\DeviceIDItem.cs" />
- <Compile Include="Models\Devices\DeviceIDManager.cs" />
+ <Compile Include="Models\Devices\DeviceDialogItem.cs" />
<Compile Include="Models\Mouse\MouseData.cs" />
<Compile Include="Models\Mouse\MouseWatcher.cs" />
<Compile Include="Models\Mouse\PointData.cs" />
@@ -129,8 +131,12 @@
<Compile Include="Layouts\NaturalLayout.cs" />
<Compile Include="Layouts\OffLayout.cs" />
<Compile Include="Layouts\PowerLayout.cs" />
+ <Compile Include="Models\Options\Cap\CapOptions.cs" />
+ <Compile Include="Models\Options\Cap\CapTypeOptions.cs" />
<Compile Include="Models\Options\CheckBoxOption.cs" />
+ <Compile Include="Models\Options\ComboBoxOptionsBase.cs" />
<Compile Include="Models\Options\Directionality\DirectionalityOptions.cs" />
+ <Compile Include="Models\Options\LockableOption.cs" />
<Compile Include="Models\Options\LUT\LutApplyOptions.cs" />
<Compile Include="Models\Options\IOption.cs" />
<Compile Include="Models\Options\LUT\LUTPanelOptions.cs" />
@@ -139,6 +145,7 @@
<Compile Include="Layouts\OptionLayout.cs" />
<Compile Include="Models\Options\OptionBase.cs" />
<Compile Include="Models\Options\OptionXY.cs" />
+ <Compile Include="Models\Options\SwitchOption.cs" />
<Compile Include="Models\Options\TextOption.cs" />
<Compile Include="Models\Serialized\GUISettings.cs" />
<Compile Include="Models\Serialized\SettingsManager.cs" />
diff --git a/installer/installer.cpp b/installer/installer.cpp
index 279fefc..27c9414 100644
--- a/installer/installer.cpp
+++ b/installer/installer.cpp
@@ -3,24 +3,16 @@
#include <utility-install.hpp>
#include <VersionHelpers.h>
-void add_service(const fs::path& target) {
- SC_HANDLE schSCManager = OpenSCManager(
- NULL, // local computer
- NULL, // ServicesActive database
- SC_MANAGER_ALL_ACCESS // full access rights
- );
-
- if (schSCManager == NULL) throw std::runtime_error("OpenSCManager failed");
-
- SC_HANDLE schService = CreateService(
- schSCManager, // SCM database
+void add_service(SC_HANDLE srv_manager) {
+ SC_HANDLE srv = CreateServiceW(
+ srv_manager, // SCM database
DRIVER_NAME.c_str(), // name of service
DRIVER_NAME.c_str(), // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_KERNEL_DRIVER, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
- target.c_str(), // path to service's binary
+ DRIVER_ENV_PATH.c_str(), // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
@@ -28,45 +20,76 @@ void add_service(const fs::path& target) {
NULL // no password
);
- if (schService) {
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- return;
- }
+ if (srv) CloseServiceHandle(srv);
+ else throw sys_error("CreateService failed");
+}
- if (auto err = GetLastError(); err != ERROR_SERVICE_EXISTS) {
- CloseServiceHandle(schSCManager);
- throw std::runtime_error("CreateService failed");
- }
+BOOL update_service(SC_HANDLE srv) {
+ return ChangeServiceConfigW(
+ srv, // service handle
+ SERVICE_KERNEL_DRIVER, // service type
+ SERVICE_DEMAND_START, // start type
+ SERVICE_ERROR_NORMAL, // error control type
+ DRIVER_ENV_PATH.c_str(), // path to service's binary
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ NULL, // no dependencies
+ NULL, // LocalSystem account
+ NULL, // no password
+ DRIVER_NAME.c_str() // service name to display
+ );
}
int main() {
+ SC_HANDLE srv_manager = NULL;
+
try {
- if (!IsWindows7OrGreater()) {
- throw std::runtime_error("OS not supported, you need at least Windows 7");
+ if (!IsWindows10OrGreater()) {
+ throw std::runtime_error("OS not supported, you need at least Windows 10");
}
+
fs::path source = fs::path(L"driver") / DRIVER_FILE_NAME;
if (!fs::exists(source)) {
throw std::runtime_error(source.generic_string() + " does not exist");
}
- fs::path target = get_target_path();
-
+ fs::path target = expand(DRIVER_ENV_PATH);
+
if (fs::exists(target)) {
std::cout << "Driver already installed. Removing previous installation.\n";
- }
- add_service(target);
+ fs::path tmp = make_temp_path(target);
- fs::path tmp = make_temp_path(target);
+ // schedule tmp to be deleted if rename target -> tmp is successful
+ if (MoveFileExW(target.c_str(), tmp.c_str(), MOVEFILE_REPLACE_EXISTING)) {
+ MoveFileExW(tmp.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+ }
+ }
- // schedule tmp to be deleted if rename target -> tmp is successful
- if (MoveFileExW(target.c_str(), tmp.c_str(), MOVEFILE_REPLACE_EXISTING)) {
- MoveFileExW(tmp.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+ if (!fs::copy_file(source, target, fs::copy_options::overwrite_existing)) {
+ throw sys_error("copy_file failed");
}
- fs::copy_file(source, target, fs::copy_options::overwrite_existing);
+ srv_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (srv_manager == NULL) throw sys_error("OpenSCManager failed");
+
+ SC_HANDLE srv = OpenServiceW(srv_manager, DRIVER_NAME.c_str(), SC_MANAGER_ALL_ACCESS);
+
+ if (srv != NULL) {
+ BOOL success = update_service(srv);
+ CloseServiceHandle(srv);
+ if (!success) throw sys_error("ChangeServiceConfig failed");
+ }
+ else {
+ auto error_code = GetLastError();
+ if (error_code == ERROR_SERVICE_DOES_NOT_EXIST) {
+ add_service(srv_manager);
+ }
+ else {
+ throw sys_error("OpenService failed", error_code);
+ }
+ }
modify_upper_filters([](std::vector<std::wstring>& filters) {
auto driver_pos = std::find(filters.begin(), filters.end(), DRIVER_NAME);
@@ -86,6 +109,8 @@ int main() {
std::cerr << "Error: " << e.what() << '\n';
}
+ if (srv_manager) CloseServiceHandle(srv_manager);
+
std::cout << "Press any key to close this window . . .\n";
_getwch();
}
diff --git a/signed/driver/rawaccel.sys b/signed/driver/rawaccel.sys
index b399578..c0224e4 100644
--- a/signed/driver/rawaccel.sys
+++ b/signed/driver/rawaccel.sys
Binary files differ
diff --git a/signed/installer.exe b/signed/installer.exe
index 99f1d32..321350b 100644
--- a/signed/installer.exe
+++ b/signed/installer.exe
Binary files differ
diff --git a/signed/uninstaller.exe b/signed/uninstaller.exe
index cfbf0dd..4dd8788 100644
--- a/signed/uninstaller.exe
+++ b/signed/uninstaller.exe
Binary files differ
diff --git a/uninstaller/uninstaller.cpp b/uninstaller/uninstaller.cpp
index bd9c564..3434cb7 100644
--- a/uninstaller/uninstaller.cpp
+++ b/uninstaller/uninstaller.cpp
@@ -14,22 +14,22 @@ int main() {
}
});
- fs::path target = get_target_path();
+ fs::path target = expand(DRIVER_ENV_PATH);
fs::path tmp = make_temp_path(target);
- if (fs::exists(target) || fs::exists(tmp)) {
+ if (fs::exists(target)) {
reboot_required = true;
- }
- // schedule tmp to be deleted if rename target -> tmp is successful
- if (MoveFileExW(target.c_str(), tmp.c_str(), MOVEFILE_REPLACE_EXISTING)) {
- MoveFileExW(tmp.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
- }
- else { // tmp is in use and delete is already scheduled
- if (fs::exists(target)) fs::remove(target);
+ // schedule tmp to be deleted if rename target -> tmp is successful
+ if (MoveFileExW(target.c_str(), tmp.c_str(), MOVEFILE_REPLACE_EXISTING)) {
+ MoveFileExW(tmp.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+ }
+ else { // tmp is in use and delete is already scheduled
+ fs::remove(target);
+ }
}
- if (reboot_required) {
+ if (reboot_required || fs::exists(tmp)) {
std::cout << "Removal complete, change will take effect after restart.\n";
}
else {
diff --git a/wrapper/input.cpp b/wrapper/input.cpp
index 3ce257a..334a0ec 100644
--- a/wrapper/input.cpp
+++ b/wrapper/input.cpp
@@ -1,79 +1,91 @@
#include "input.h"
-#include "interop-exception.h"
-
-#include <msclr\marshal_cppstd.h>
-#include <algorithm>
using namespace System;
using namespace System::Collections::Generic;
+using namespace System::Runtime::InteropServices;
-std::vector<HANDLE> rawinput_handles_from_id(const std::wstring& device_id)
-{
- std::vector<HANDLE> handles;
+[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
+public ref struct RawInputDevice {
+ System::IntPtr handle;
- rawinput_foreach([&](const auto& dev) {
- if (dev.id == device_id) handles.push_back(dev.handle);
- });
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_NAME_LEN)]
+ System::String^ name;
- return handles;
-}
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)]
+ System::String^ id;
+};
-std::vector<std::wstring> rawinput_id_list()
+static int CompareByID(RawInputDevice^ x, RawInputDevice^ y)
{
- std::vector<std::wstring> ids;
-
- rawinput_foreach([&](const auto& dev) {
- ids.push_back(dev.id);
- });
-
- std::sort(ids.begin(), ids.end());
- ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
- return ids;
+ return String::Compare(x->id, y->id);
}
-public ref struct RawInputInteropException : InteropException {
- RawInputInteropException(System::String^ what) :
- InteropException(what) {}
- RawInputInteropException(const char* what) :
- InteropException(what) {}
- RawInputInteropException(const std::exception& e) :
- InteropException(e) {}
-};
+public ref struct MultiHandleDevice {
+ System::String^ name;
+ System::String^ id;
+ List<System::IntPtr>^ handles;
-public ref struct RawInputInterop
-{
- static void AddHandlesFromID(String^ deviceID, List<IntPtr>^ rawInputHandles)
+ // Returned list represents the current connected raw input devices,
+ // where each device has a distinct device id
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-ids
+ static IList<MultiHandleDevice^>^ GetList()
{
- try
- {
- std::vector<HANDLE> nativeHandles = rawinput_handles_from_id(
- msclr::interop::marshal_as<std::wstring>(deviceID));
+ return ListMaker::MakeList()->AsReadOnly();
+ }
- for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh));
- }
- catch (const std::exception& e)
+ ref class ListMaker {
+ List<RawInputDevice^>^ devices = gcnew List<RawInputDevice^>();
+
+ delegate void NativeDevHandler(rawinput_device&);
+
+ void Add(rawinput_device& dev)
{
- throw gcnew RawInputInteropException(e);
+ devices->Add(Marshal::PtrToStructure<RawInputDevice^>(IntPtr(&dev)));
}
- }
- static List<String^>^ GetDeviceIDs()
- {
- try
+ ListMaker() {}
+ public:
+ static List<MultiHandleDevice^>^ MakeList()
{
- auto ids = gcnew List<String^>();
+ auto maker = gcnew ListMaker();
+ NativeDevHandler^ del = gcnew NativeDevHandler(maker, &Add);
+ GCHandle gch = GCHandle::Alloc(del);
+ auto fp = static_cast<void (*)(rawinput_device&)>(
+ Marshal::GetFunctionPointerForDelegate(del).ToPointer());
+ rawinput_foreach(fp);
+ gch.Free();
- for (auto&& name : rawinput_id_list())
- {
- ids->Add(msclr::interop::marshal_as<String^>(name));
+ auto ret = gcnew List<MultiHandleDevice^>();
+ auto count = maker->devices->Count;
+ auto first = 0;
+ auto last = 0;
+
+ if (count > 0) {
+ maker->devices->Sort(gcnew Comparison<RawInputDevice^>(&CompareByID));
+ while (++last != count) {
+ if (!String::Equals(maker->devices[first]->id, maker->devices[last]->id)) {
+ auto range = maker->devices->GetRange(first, last - first);
+ ret->Add(gcnew MultiHandleDevice(range));
+ first = last;
+ }
+ }
+ auto range = maker->devices->GetRange(first, last - first);
+ ret->Add(gcnew MultiHandleDevice(range));
}
- return ids;
+ return ret;
}
- catch (const std::exception& e)
- {
- throw gcnew RawInputInteropException(e);
+ };
+
+private:
+ MultiHandleDevice(IEnumerable<RawInputDevice^>^ seq)
+ {
+ auto it = seq->GetEnumerator();
+ if (it->MoveNext()) {
+ name = it->Current->name;
+ id = it->Current->id;
+ handles = gcnew List<IntPtr>();
+ do handles->Add(it->Current->handle); while (it->MoveNext());
}
}
-
};
diff --git a/wrapper/input.h b/wrapper/input.h
index c83dca8..a931904 100644
--- a/wrapper/input.h
+++ b/wrapper/input.h
@@ -1,77 +1,127 @@
#pragma once
#pragma comment(lib, "cfgmgr32.lib")
+#pragma comment(lib, "hid.lib")
+#pragma comment(lib, "User32.lib")
-#include <string>
-#include <system_error>
+#include <string_view>
#include <vector>
#include <Windows.h>
#include <cfgmgr32.h>
#include <initguid.h> // needed for devpkey.h to parse properly
#include <devpkey.h>
+#include <hidsdi.h>
+
+inline constexpr size_t MAX_DEV_ID_LEN = 200;
+inline constexpr size_t MAX_NAME_LEN = 256;
+inline constexpr UINT RI_ERROR = -1;
struct rawinput_device {
- HANDLE handle;
- std::wstring id;
+ HANDLE handle = nullptr; // rawinput handle
+ WCHAR name[MAX_NAME_LEN] = {}; // manufacturer + product
+ WCHAR id[MAX_DEV_ID_LEN] = {}; // hwid formatted device id
};
template <typename Func>
void rawinput_foreach(Func fn, DWORD device_type = RIM_TYPEMOUSE)
{
- const UINT RI_ERROR = -1;
-
- // get number of devices
- UINT num_devs = 0;
- if (GetRawInputDeviceList(NULL, &num_devs, sizeof(RAWINPUTDEVICELIST)) != 0) {
- throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceList failed");
- }
-
- auto dev_list = std::vector<RAWINPUTDEVICELIST>(num_devs);
+ const size_t HID_STR_MAX_LEN = 127;
+
+ auto starts_with = [](auto&& a, auto&& b) {
+ return b.size() <= a.size() && std::equal(b.begin(), b.end(), a.begin());
+ };
+
+ auto get_dev_list = []() -> std::vector<RAWINPUTDEVICELIST> {
+ UINT elem_size = sizeof(RAWINPUTDEVICELIST);
+ UINT num_devs = 0;
+
+ if (GetRawInputDeviceList(NULL, &num_devs, elem_size) == 0) {
+ auto dev_list = std::vector<RAWINPUTDEVICELIST>(num_devs);
+
+ if (GetRawInputDeviceList(&dev_list[0], &num_devs, elem_size) != RI_ERROR) {
+ return dev_list;
+ }
+ }
- if (GetRawInputDeviceList(&dev_list[0], &num_devs, sizeof(RAWINPUTDEVICELIST)) == RI_ERROR) {
- return;
- }
+ return {};
+ };
- std::wstring name;
+ std::wstring interface_name;
rawinput_device dev;
DEVPROPTYPE prop_type;
CONFIGRET cm_res;
+ WCHAR product_str_buf[HID_STR_MAX_LEN] = {};
- for (auto [handle, dev_type] : dev_list) {
+ for (auto [handle, dev_type] : get_dev_list()) {
if (dev_type != device_type) continue;
- // get interface name length
+ dev.handle = handle;
+
+ // get interface name
UINT name_len = 0;
if (GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, NULL, &name_len) == RI_ERROR) {
continue;
}
- name.resize(name_len);
+ interface_name.resize(name_len);
- if (GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, &name[0], &name_len) == RI_ERROR) {
+ if (GetRawInputDeviceInfoW(handle, RIDI_DEVICENAME, &interface_name[0], &name_len) == RI_ERROR) {
continue;
}
- // get sizeof device instance id
+ // make name from vendor + product
+ HANDLE hid_dev_object = CreateFileW(
+ &interface_name[0], 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+
+ if (hid_dev_object != INVALID_HANDLE_VALUE) {
+
+ if (HidD_GetProductString(hid_dev_object, product_str_buf, HID_STR_MAX_LEN)) {
+ auto product_sv = std::wstring_view(product_str_buf);
+
+ if (HidD_GetManufacturerString(hid_dev_object, dev.name, HID_STR_MAX_LEN)) {
+ auto manufacturer_sv = std::wstring_view(dev.name);
+
+ if (starts_with(product_sv, manufacturer_sv)) {
+ wcsncpy_s(dev.name, product_str_buf, HID_STR_MAX_LEN);
+ }
+ else {
+ auto last = manufacturer_sv.size();
+ dev.name[last] = L' ';
+ wcsncpy_s(dev.name + last + 1, HID_STR_MAX_LEN, product_str_buf, HID_STR_MAX_LEN);
+ }
+ }
+ else {
+ wcsncpy_s(dev.name, product_str_buf, HID_STR_MAX_LEN);
+ }
+ }
+ else {
+ dev.name[0] = L'\0';
+ }
+
+ CloseHandle(hid_dev_object);
+ }
+ else {
+ dev.name[0] = L'\0';
+ }
+
+ // get device instance id
ULONG id_size = 0;
- cm_res = CM_Get_Device_Interface_PropertyW(&name[0], &DEVPKEY_Device_InstanceId,
+ cm_res = CM_Get_Device_Interface_PropertyW(&interface_name[0], &DEVPKEY_Device_InstanceId,
&prop_type, NULL, &id_size, 0);
if (cm_res != CR_BUFFER_SMALL && cm_res != CR_SUCCESS) continue;
- dev.id.resize((id_size + 1) / 2);
-
- cm_res = CM_Get_Device_Interface_PropertyW(&name[0], &DEVPKEY_Device_InstanceId,
+ cm_res = CM_Get_Device_Interface_PropertyW(&interface_name[0], &DEVPKEY_Device_InstanceId,
&prop_type, reinterpret_cast<PBYTE>(&dev.id[0]), &id_size, 0);
if (cm_res != CR_SUCCESS) continue;
// pop instance id
- auto instance_delim_pos = dev.id.find_last_of('\\');
- if (instance_delim_pos != std::string::npos) dev.id.resize(instance_delim_pos);
-
- dev.handle = handle;
+ auto instance_delim_pos = std::wstring_view(dev.id).find_last_of(L'\\');
+ if (instance_delim_pos != std::string::npos) {
+ dev.id[instance_delim_pos] = L'\0';
+ }
fn(dev);
}
diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp
index 4e6c4f1..a248010 100644
--- a/wrapper/wrapper.cpp
+++ b/wrapper/wrapper.cpp
@@ -15,38 +15,36 @@ using namespace Newtonsoft::Json::Linq;
namespace ra = rawaccel;
-ra::settings default_settings;
+ra::modifier_settings default_modifier_settings;
+ra::device_settings default_device_settings;
-[JsonConverter(Converters::StringEnumConverter::typeid)]
-public enum class AccelMode
+public ref struct VersionHelper
{
- classic, jump, natural, motivity, power, lut, noaccel
+ literal String^ VersionString = RA_VER_STRING;
+
+ static Version^ ValidOrThrow()
+ {
+ try {
+ ra::version_t v = ra::valid_version_or_throw();
+ return gcnew Version(v.major, v.minor, v.patch, 0);
+ }
+ catch (const ra::error& e) {
+ throw gcnew InteropException(e);
+ }
+ }
};
[JsonConverter(Converters::StringEnumConverter::typeid)]
-public enum class SpacedTableMode
+public enum class AccelMode
{
- off, binlog, linear
+ classic, jump, natural, motivity, power, lut, noaccel
};
-[StructLayout(LayoutKind::Sequential)]
-public value struct SpacedTableArgs
-{
- [JsonIgnore]
- SpacedTableMode mode;
-
- [MarshalAs(UnmanagedType::U1)]
- bool transfer;
-
- [MarshalAs(UnmanagedType::U1)]
- unsigned char partitions;
-
- short num;
- double start;
- double stop;
+[JsonConverter(Converters::StringEnumConverter::typeid)]
+public enum class CapMode {
+ in_out, input, output
};
-
generic <typename T>
[StructLayout(LayoutKind::Sequential)]
public value struct Vec2
@@ -56,90 +54,81 @@ public value struct Vec2
};
[StructLayout(LayoutKind::Sequential)]
-public value struct TableArgs
-{
- [JsonProperty("Whether points affect velocity (true) or sensitivity (false)")]
- [MarshalAs(UnmanagedType::U1)]
- bool velocity;
-
- [JsonIgnore]
- int length;
-
- [MarshalAs(UnmanagedType::ByValArray, SizeConst = ra::ARB_LUT_CAPACITY)]
- array<Vec2<float>>^ points;
-
- virtual bool Equals(Object^ ob) override {
- if (ob->GetType() == this->GetType()) {
- TableArgs^ other = (TableArgs^)ob;
-
- if (this->length != other->length) return false;
- if (this->points == other->points) return true;
-
- if (unsigned(length) >= ra::ARB_LUT_CAPACITY ||
- points == nullptr ||
- other->points == nullptr) {
- throw gcnew InteropException("invalid table args");
- }
-
- for (int i = 0; i < length; i++) {
- if (points[i].x != other->points[i].x ||
- points[i].y != other->points[i].y)
- return false;
- }
-
- return true;
- }
- else {
- return false;
- }
- }
-
- virtual int GetHashCode() override {
- return points->GetHashCode() ^ length.GetHashCode();
- }
-};
-
-[StructLayout(LayoutKind::Sequential)]
public value struct AccelArgs
{
+ literal int MaxLutPoints = ra::LUT_POINTS_CAPACITY;
+
AccelMode mode;
+ [JsonProperty("Gain / Velocity")]
[MarshalAs(UnmanagedType::U1)]
- bool legacy;
+ bool gain;
- double offset;
- double cap;
- double accelClassic;
+ double inputOffset;
+ double outputOffset;
+ double acceleration;
double decayRate;
double growthRate;
double motivity;
- double power;
+ double exponentClassic;
double scale;
- double weight;
- double exponent;
+ double exponentPower;
double limit;
double midpoint;
double smooth;
- [JsonProperty(Required = Required::Default)]
- SpacedTableArgs spacedTableArgs;
+ [JsonProperty("Cap / Jump")]
+ Vec2<double> cap;
- TableArgs tableData;
-};
+ [JsonProperty("Cap mode")]
+ CapMode capMode;
-[StructLayout(LayoutKind::Sequential)]
-public value struct DomainArgs
-{
- Vec2<double> domainXY;
- double lpNorm;
+ [JsonIgnore]
+ int length;
+
+ [MarshalAs(UnmanagedType::ByValArray, SizeConst = ra::LUT_RAW_DATA_CAPACITY)]
+ array<float>^ data;
+
+ [OnDeserialized]
+ void OnDeserializedMethod(StreamingContext context)
+ {
+ // data->Length must match SizeConst when marshalling
+ length = data->Length;
+ array<float>::Resize(data, ra::LUT_RAW_DATA_CAPACITY);
+ }
};
[JsonObject(ItemRequired = Required::Always)]
[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
-public ref struct DriverSettings
+public ref struct Profile
{
- literal double WriteDelayMs = ra::WRITE_DELAY;
- literal String^ Key = "Driver settings";
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_NAME_LEN)]
+ System::String^ name;
+
+ [JsonProperty("Whole/combined accel (set false for 'by component' mode)")]
+ [MarshalAs(UnmanagedType::U1)]
+ bool combineMagnitudes;
+
+ double lpNorm;
+
+ [JsonProperty("Stretches domain for horizontal vs vertical inputs")]
+ Vec2<double> domainXY;
+ [JsonProperty("Stretches accel range for horizontal vs vertical inputs")]
+ Vec2<double> rangeXY;
+
+ [JsonProperty("Whole or horizontal accel parameters")]
+ AccelArgs argsX;
+ [JsonProperty("Vertical accel parameters")]
+ AccelArgs argsY;
+
+ [JsonProperty("Sensitivity multiplier")]
+ double sensitivity;
+ [JsonProperty("Y/X sensitivity ratio (vertical sens multiplier)")]
+ double yxSensRatio;
+ [JsonProperty("L/R sensitivity ratio (left sens multiplier)")]
+ double lrSensRatio;
+ [JsonProperty("U/D sensitivity ratio (up sens multiplier)")]
+ double udSensRatio;
[JsonProperty("Degrees of rotation")]
double rotation;
@@ -147,351 +136,235 @@ public ref struct DriverSettings
[JsonProperty("Degrees of angle snapping")]
double snap;
- [JsonProperty("Use x as whole/combined accel")]
- [MarshalAs(UnmanagedType::U1)]
- bool combineMagnitudes;
-
- double dpi;
-
[JsonIgnore]
double minimumSpeed;
[JsonProperty("Input Speed Cap")]
double maximumSpeed;
- [JsonProperty("Accel parameters")]
- Vec2<AccelArgs> args;
+ Profile(ra::profile& args)
+ {
+ Marshal::PtrToStructure(IntPtr(&args), this);
+ }
- [JsonProperty("Sensitivity multipliers")]
- Vec2<double> sensitivity;
+ Profile() :
+ Profile(default_modifier_settings.prof) {}
+};
- [JsonProperty("Negative directional multipliers")]
- Vec2<double> directionalMultipliers;
+[JsonObject(ItemRequired = Required::Always)]
+[StructLayout(LayoutKind::Sequential)]
+public value struct DeviceConfig {
+ [MarshalAs(UnmanagedType::U1)]
+ bool disable;
- [JsonProperty("Stretches domain for horizontal vs vertical inputs")]
- DomainArgs domainArgs;
+ [MarshalAs(UnmanagedType::U1)]
+ [JsonProperty(Required = Required::Default)]
+ bool setExtraInfo;
- [JsonProperty("Stretches accel range for horizontal vs vertical inputs")]
- Vec2<double> rangeXY;
+ [JsonProperty("DPI (normalizes sens to 1000dpi and converts input speed unit: counts/ms -> in/s)")]
+ int dpi;
+ [JsonProperty("Polling rate Hz (keep at 0 for automatic adjustment)")]
+ int pollingRate;
+
+ [ComponentModel::DefaultValue(ra::DEFAULT_TIME_MIN)]
[JsonProperty(Required = Required::Default)]
double minimumTime;
+ [ComponentModel::DefaultValue(ra::DEFAULT_TIME_MAX)]
[JsonProperty(Required = Required::Default)]
double maximumTime;
- [JsonProperty("Ignore devices with matching ID")]
- [MarshalAs(UnmanagedType::U1)]
- bool ignore;
-
- [JsonProperty("Device ID")]
- [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)]
- String^ deviceID = "";
-
- bool ShouldSerializeminimumTime()
- {
- return minimumTime != ra::DEFAULT_TIME_MIN;
- }
-
- bool ShouldSerializemaximumTime()
- {
- return maximumTime != ra::DEFAULT_TIME_MAX;
- }
-
- DriverSettings()
+ bool ShouldSerializesetExtraInfo()
{
- Marshal::PtrToStructure(IntPtr(&default_settings), this);
+ return setExtraInfo == true;
}
-private:
- [OnDeserialized]
- void OnDeserializedMethod(StreamingContext context)
+ bool ShouldSerializeminimumTime()
{
- args.x.tableData.length = args.x.tableData.points->Length;
- args.y.tableData.length = args.y.tableData.points->Length;
-
- array<Vec2<float>>::Resize(args.x.tableData.points, ra::ARB_LUT_CAPACITY);
- array<Vec2<float>>::Resize(args.y.tableData.points, ra::ARB_LUT_CAPACITY);
+ return minimumTime != ra::DEFAULT_TIME_MIN;
}
- [OnSerializing]
- void OnSerializingMethod(StreamingContext context)
+ bool ShouldSerializemaximumTime()
{
- array<Vec2<float>>::Resize(args.x.tableData.points, args.x.tableData.length);
- array<Vec2<float>>::Resize(args.y.tableData.points, args.y.tableData.length);
+ return maximumTime != ra::DEFAULT_TIME_MAX;
}
- [OnSerialized]
- void OnSerializedMethod(StreamingContext context)
+ void Init(const ra::device_config& cfg)
{
- array<Vec2<float>>::Resize(args.x.tableData.points, ra::ARB_LUT_CAPACITY);
- array<Vec2<float>>::Resize(args.y.tableData.points, ra::ARB_LUT_CAPACITY);
+ disable = cfg.disable;
+ setExtraInfo = cfg.set_extra_info;
+ dpi = cfg.dpi;
+ pollingRate = cfg.polling_rate;
+ minimumTime = cfg.clamp.min;
+ maximumTime = cfg.clamp.max;
}
-
};
[JsonObject(ItemRequired = Required::Always)]
-public ref struct LutBase
+[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
+public ref struct DeviceSettings
{
- [JsonConverter(Converters::StringEnumConverter::typeid)]
- enum class Mode
- {
- logarithmic, linear
- } mode;
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_NAME_LEN)]
+ String^ name;
- virtual void SetArgs(AccelArgs%) {}
- virtual void SetData(ra::accel_union&) {}
-};
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_NAME_LEN)]
+ String^ profile;
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)]
+ String^ id;
-[JsonObject(ItemRequired = Required::Always)]
-public ref struct SpacedLut abstract : public LutBase
-{
- [JsonProperty("Whether points affect velocity (true) or sensitivity (false)")]
- bool transfer;
-
- double start;
- double stop;
- array<float>^ data;
+ DeviceConfig config;
- void SetArgsBase(AccelArgs% args)
+ DeviceSettings(ra::device_settings& args)
{
- args.spacedTableArgs.transfer = transfer;
- args.spacedTableArgs.start = start;
- args.spacedTableArgs.stop = stop;
+ Marshal::PtrToStructure(IntPtr(&args), this);
}
- void SetDataBase(ra::accel_union& accel)
- {
- if (size_t(data->LongLength) > ra::SPACED_LUT_CAPACITY) {
- throw gcnew InteropException("data is too large");
- }
- }
+ DeviceSettings() :
+ DeviceSettings(default_device_settings) {}
};
-[JsonObject(ItemRequired = Required::Always)]
-public ref struct LinearLut sealed : public SpacedLut
-{
- LinearLut()
- {
- }
-
- LinearLut(const ra::linear_lut& table)
- {
- mode = Mode::linear;
- transfer = table.transfer;
- start = table.range.start;
- stop = table.range.stop;
- data = gcnew array<float>(table.range.num);
-
- pin_ptr<float> pdata = &data[0];
- std::memcpy(pdata, &table.data, sizeof(float) * data->Length);
- }
- virtual void SetArgs(AccelArgs% args) override
- {
- SetArgsBase(args);
- args.spacedTableArgs.num = data->Length;
- args.spacedTableArgs.mode = SpacedTableMode::linear;
- }
-
- virtual void SetData(ra::accel_union& accel) override
- {
- SetDataBase(accel);
- pin_ptr<float> pdata = &data[0];
- std::memcpy(&accel.lin_lut.data, pdata, sizeof(float) * data->Length);
- }
-};
-
-[JsonObject(ItemRequired = Required::Always)]
-public ref struct BinLogLut sealed : public SpacedLut
+public ref class ProfileErrors
{
- short num;
-
- BinLogLut()
- {
- }
-
- BinLogLut(const ra::binlog_lut& table)
- {
- mode = Mode::logarithmic;
- transfer = table.transfer;
- start = table.range.start;
- stop = table.range.stop;
- num = table.range.num;
- data = gcnew array<float>(1 + num * (int(stop) - int(start)));
-
- pin_ptr<float> pdata = &data[0];
- std::memcpy(pdata, &table.data, sizeof(float) * data->Length);
- }
+ List<String^>^ tmp;
+ bool single;
- virtual void SetArgs(AccelArgs% args) override
- {
- SetArgsBase(args);
- args.spacedTableArgs.num = num;
- args.spacedTableArgs.mode = SpacedTableMode::binlog;
- }
+ delegate void MsgHandler(const char*);
- virtual void SetData(ra::accel_union& accel) override
+ void Add(const char* msg)
{
- SetDataBase(accel);
-
- if (data->Length != 1 + num * (int(stop) - int(start))) {
- throw gcnew InteropException("size of data does not match args");
- }
-
- pin_ptr<float> pdata = &data[0];
- std::memcpy(&accel.log_lut.data, pdata, sizeof(float) * data->Length);
+ tmp->Add(gcnew String(msg));
}
-};
-
-public ref struct RaConvert {
- static DriverSettings^ Settings(String^ json)
+public:
+ ref struct SingleProfileErrors
{
- return NonNullable<DriverSettings^>(json);
- }
+ Profile^ prof;
+ array<String^>^ messages;
+ int lastX;
+ int lastY;
+ };
- static String^ Settings(DriverSettings^ settings)
- {
- JObject^ jObject = JObject::FromObject(settings);
- String^ modes = String::Join(" | ", Enum::GetNames(AccelMode::typeid));
- jObject->AddFirst(gcnew JProperty("### Accel Modes ###", modes));
- return jObject->ToString(Formatting::Indented);
- }
+ List<SingleProfileErrors^>^ list;
- static LutBase^ Table(String^ json)
+ ProfileErrors(List<Profile^>^ profiles)
{
- JObject^ jObject = JObject::Parse(json);
-
- if ((Object^)jObject == nullptr) {
- throw gcnew JsonException("bad json");
- }
-
- LutBase^ base = NonNullable<LutBase^>(jObject);
-
- switch (base->mode) {
- case LutBase::Mode::logarithmic:
- return NonNullable<BinLogLut^>(jObject);
- case LutBase::Mode::linear:
- return NonNullable<LinearLut^>(jObject);
- default:
- throw gcnew NotImplementedException();
+ single = profiles->Count == 1;
+ list = gcnew List<SingleProfileErrors^>();
+ tmp = gcnew List<String^>();
+ MsgHandler^ del = gcnew MsgHandler(this, &ProfileErrors::Add);
+ GCHandle gch = GCHandle::Alloc(del);
+ auto fp = static_cast<void (*)(const char*)>(
+ Marshal::GetFunctionPointerForDelegate(del).ToPointer());
+ ra::profile* native_ptr = new ra::profile();
+
+ for each (auto prof in profiles) {
+ Marshal::StructureToPtr(prof, IntPtr(native_ptr), false);
+ auto [last_x, last_y, _] = ra::valid(*native_ptr, fp);
+
+ if (tmp->Count != 0) {
+ auto singleErrors = gcnew SingleProfileErrors();
+ singleErrors->messages = tmp->ToArray();
+ singleErrors->lastX = last_x;
+ singleErrors->lastY = last_y;
+ singleErrors->prof = prof;
+ list->Add(singleErrors);
+ tmp->Clear();
+ }
}
- }
-
- static String^ Table(LutBase^ lut)
- {
- auto serializerSettings = gcnew JsonSerializerSettings();
- return JsonConvert::SerializeObject(
- lut, lut->GetType(), Formatting::Indented, serializerSettings);
- };
- generic <typename T>
- static T NonNullable(String^ json)
- {
- T obj = JsonConvert::DeserializeObject<T>(json);
- if (obj == nullptr) throw gcnew JsonException("invalid JSON");
- return obj;
+ tmp = nullptr;
+ gch.Free();
+ delete native_ptr;
}
- generic <typename T>
- static T NonNullable(JObject^ jObject)
+ bool Empty()
{
- T obj = jObject->ToObject<T>();
- if (obj == nullptr) throw gcnew JsonException("invalid JSON");
- return obj;
+ return list->Count == 0;
}
-};
-public ref struct ExtendedSettings {
- DriverSettings^ baseSettings;
- Vec2<LutBase^> tables;
-
- using JSON = String^;
-
- ExtendedSettings(DriverSettings^ driverSettings) :
- baseSettings(driverSettings) {}
-
- ExtendedSettings() :
- ExtendedSettings(gcnew DriverSettings()) {}
-
- ExtendedSettings(JSON settingsJson) :
- ExtendedSettings(settingsJson, nullptr, nullptr, false) {}
-
- ExtendedSettings(JSON settingsJson, JSON tableJson) :
- ExtendedSettings(settingsJson, tableJson, nullptr, false) {}
-
- ExtendedSettings(JSON settingsJson, JSON xTableJson, JSON yTableJson) :
- ExtendedSettings(settingsJson, xTableJson, yTableJson, true) {}
-
-private:
- ExtendedSettings(JSON settingsJson, JSON xTableJson, JSON yTableJson, bool byComponent)
+ virtual String^ ToString() override
{
- if (settingsJson) {
- baseSettings = RaConvert::Settings(settingsJson);
- }
- else {
- baseSettings = gcnew DriverSettings();
- }
-
- if (xTableJson || yTableJson) {
- baseSettings->combineMagnitudes = !byComponent;
- }
+ Text::StringBuilder^ sb = gcnew Text::StringBuilder();
- if (xTableJson) {
- tables.x = RaConvert::Table(xTableJson);
- tables.x->SetArgs(baseSettings->args.x);
- }
+ for each (auto elem in list) {
+ if (!single) {
+ sb->AppendFormat("profile: {0}\n", elem->prof->name);
+ }
- if (yTableJson) {
- if (Object::ReferenceEquals(yTableJson, xTableJson)) {
- tables.y = tables.x;
+ auto msgs = elem->messages;
+ if (elem->prof->combineMagnitudes) {
+ for (int i = 0; i < elem->lastX; i++) {
+ sb->AppendFormat("\t{0}\n", msgs[i]);
+ }
}
else {
- tables.y = RaConvert::Table(yTableJson);
+ for (int i = 0; i < elem->lastX; i++) {
+ sb->AppendFormat("\tx: {0}\n", msgs[i]);
+ }
+ for (int i = elem->lastX; i < elem->lastY; i++) {
+ sb->AppendFormat("\ty: {0}\n", msgs[i]);
+ }
}
- tables.y->SetArgs(baseSettings->args.y);
+ for (int i = elem->lastY; i < msgs->Length; i++) {
+ sb->AppendFormat("\t{0}\n", msgs[i]);
+ }
}
- }
+ return sb->ToString();
+ }
};
-public ref class SettingsErrors
+public ref class DeviceErrors
{
-public:
-
- List<String^>^ list;
- int lastX;
- int lastY;
+ List<String^>^ tmp;
+ bool single;
delegate void MsgHandler(const char*);
void Add(const char* msg)
{
- list->Add(gcnew String(msg));
+ tmp->Add(gcnew String(msg));
}
- SettingsErrors(ExtendedSettings^ settings) :
- SettingsErrors(settings->baseSettings) {}
+public:
+ ref struct SingleDeviceErrors
+ {
+ DeviceSettings^ settings;
+ array<String^>^ messages;
+ };
- SettingsErrors(DriverSettings^ settings)
+ List<SingleDeviceErrors^>^ list;
+
+ DeviceErrors(List<DeviceSettings^>^ devSettings)
{
- MsgHandler^ del = gcnew MsgHandler(this, &SettingsErrors::Add);
+ single = devSettings->Count == 1;
+ list = gcnew List<SingleDeviceErrors^>();
+ tmp = gcnew List<String^>();
+ MsgHandler^ del = gcnew MsgHandler(this, &DeviceErrors::Add);
GCHandle gch = GCHandle::Alloc(del);
auto fp = static_cast<void (*)(const char*)>(
Marshal::GetFunctionPointerForDelegate(del).ToPointer());
+ ra::device_settings* native_ptr = new ra::device_settings();
+
+ for each (auto dev in devSettings) {
+ Marshal::StructureToPtr(dev, IntPtr(native_ptr), false);
+ ra::valid(*native_ptr, fp);
+
+ if (tmp->Count != 0) {
+ auto singleErrors = gcnew SingleDeviceErrors();
+ singleErrors->messages = tmp->ToArray();
+ singleErrors->settings = dev;
+ list->Add(singleErrors);
+ tmp->Clear();
+ }
+ }
- ra::settings* args_ptr = new ra::settings();
- Marshal::StructureToPtr(settings, (IntPtr)args_ptr, false);
-
- list = gcnew List<String^>();
- auto [last_x, last_y, _] = ra::valid(*args_ptr, fp);
- lastX = last_x;
- lastY = last_y;
-
+ tmp = nullptr;
gch.Free();
- delete args_ptr;
+ delete native_ptr;
}
bool Empty()
@@ -503,36 +376,52 @@ public:
{
Text::StringBuilder^ sb = gcnew Text::StringBuilder();
- for each (auto s in list->GetRange(0, lastX))
- {
- sb->AppendFormat("x: {0}\n", s);
- }
- for each (auto s in list->GetRange(lastX, lastY - lastX))
- {
- sb->AppendFormat("y: {0}\n", s);
- }
- for each (auto s in list->GetRange(lastY, list->Count - lastY))
- {
- sb->AppendLine(s);
+ for each (auto elem in list) {
+ if (!single) {
+ sb->AppendFormat("device: {0}\n", elem->settings->id);
+ if (!String::IsNullOrWhiteSpace(elem->settings->name)) {
+ sb->AppendFormat(" name: {0}\n", elem->settings->name);
+ }
+ }
+
+ for each (auto msg in elem->messages) {
+ sb->AppendFormat("\tx: {0}\n", msg);
+ }
}
return sb->ToString();
}
};
-struct instance_t {
- ra::io_t data;
- vec2<ra::accel_invoker> inv;
+struct accel_instance_t {
+ ra::modifier mod;
+ ra::modifier_settings settings;
+
+ accel_instance_t() = default;
+
+ accel_instance_t(ra::modifier_settings& args) :
+ settings(args),
+ mod(args) {}
+
+ void init(Profile^ args)
+ {
+ Marshal::StructureToPtr(args, IntPtr(&settings.prof), false);
+ ra::init_data(settings);
+ mod = { settings };
+ }
};
public ref class ManagedAccel
{
- instance_t* const instance = new instance_t();
-
+ accel_instance_t* const instance = new accel_instance_t();
public:
+
ManagedAccel() {}
- ManagedAccel(ExtendedSettings^ settings)
+ ManagedAccel(ra::modifier_settings& settings) :
+ instance(new accel_instance_t(settings)) {}
+
+ ManagedAccel(Profile^ settings)
{
Settings = settings;
}
@@ -547,95 +436,300 @@ public:
delete instance;
}
- Tuple<double, double>^ Accelerate(int x, int y, double time)
+ Tuple<double, double>^ Accelerate(int x, int y, double dpi_factor, double time)
{
vec2d in_out_vec = {
(double)x,
(double)y
};
- instance->data.mod.modify(in_out_vec, instance->inv, time);
+ instance->mod.modify(in_out_vec, instance->settings, dpi_factor, time);
return gcnew Tuple<double, double>(in_out_vec.x, in_out_vec.y);
}
+ property Profile^ Settings
+ {
+ Profile^ get()
+ {
+ return gcnew Profile(instance->settings.prof);
+ }
+
+ void set(Profile^ val)
+ {
+ instance->init(val);
+ }
+
+ }
+
+ ra::modifier_settings NativeSettings()
+ {
+ return instance->settings;
+ }
+
+};
+
+
+[JsonObject(ItemRequired = Required::Always)]
+public ref class DriverConfig {
+public:
+ literal double WriteDelayMs = ra::WRITE_DELAY;
+ literal String^ Key = "Driver settings";
+
+ String^ version = RA_VER_STRING;
+
+ DeviceConfig defaultDeviceConfig;
+
+ List<Profile^>^ profiles;
+
+ [NonSerialized]
+ List<ManagedAccel^>^ accels;
+
+ List<DeviceSettings^>^ devices;
+
void Activate()
{
+ if (accels->Count != profiles->Count) {
+ throw gcnew Exception("Profile count does not match ManagedAccel");
+ }
+
+ std::byte* buffer;
+
+ auto modifier_data_bytes = accels->Count * sizeof(ra::modifier_settings);
+ auto device_data_bytes = devices->Count * sizeof(ra::device_settings);
+
try {
- ra::write(instance->data);
+ buffer = new std::byte[sizeof(ra::io_base) + modifier_data_bytes + device_data_bytes];
}
- catch (const ra::error& e) {
+ catch (const std::exception& e) {
throw gcnew InteropException(e);
}
+
+ auto* byte_ptr = buffer;
+
+ auto* base_data = reinterpret_cast<ra::io_base*>(byte_ptr);
+ base_data->default_dev_cfg.disable = defaultDeviceConfig.disable;
+ base_data->default_dev_cfg.set_extra_info = defaultDeviceConfig.setExtraInfo;
+ base_data->default_dev_cfg.dpi = defaultDeviceConfig.dpi;
+ base_data->default_dev_cfg.polling_rate = defaultDeviceConfig.pollingRate;
+ base_data->default_dev_cfg.clamp.min = defaultDeviceConfig.minimumTime;
+ base_data->default_dev_cfg.clamp.max = defaultDeviceConfig.maximumTime;
+ base_data->modifier_data_size = accels->Count;
+ base_data->device_data_size = devices->Count;
+
+ byte_ptr += sizeof(ra::io_base);
+
+ auto* modifier_data = reinterpret_cast<ra::modifier_settings*>(byte_ptr);
+ for (auto i = 0; i < accels->Count; i++) {
+ auto& mod_settings = modifier_data[i];
+ mod_settings = accels[i]->NativeSettings();
+ }
+
+ byte_ptr += modifier_data_bytes;
+
+ auto* device_data = reinterpret_cast<ra::device_settings*>(byte_ptr);
+ for (auto i = 0; i < devices->Count; i++) {
+ auto& dev_settings = device_data[i];
+ Marshal::StructureToPtr(devices[i], IntPtr(&dev_settings), false);
+ }
+
+ try {
+ ra::write(buffer);
+ delete[] buffer;
+ }
+ catch (const std::exception& e) {
+ delete[] buffer;
+ throw gcnew InteropException(e);
+ }
+ }
+
+ void SetProfileAt(int index, Profile^ val)
+ {
+ profiles[index] = val;
+ accels[index]->Settings = val;
}
- property ExtendedSettings^ Settings
+ // returns null or a joined list of error messages
+ String^ Errors()
{
- ExtendedSettings^ get()
- {
- auto settings = gcnew ExtendedSettings();
- Marshal::PtrToStructure(IntPtr(&instance->data.args), settings->baseSettings);
- settings->tables.x = extract(instance->data.args.argsv.x.spaced_args.mode,
- instance->data.mod.accel.x);
- settings->tables.y = extract(instance->data.args.argsv.y.spaced_args.mode,
- instance->data.mod.accel.y);
- return settings;
+ Text::StringBuilder^ sb = gcnew Text::StringBuilder();
+
+ ProfileErrors^ profErrors = gcnew ProfileErrors(profiles);
+ if (!profErrors->Empty()) {
+ sb->Append(profErrors->ToString());
}
- void set(ExtendedSettings^ val)
- {
- Marshal::StructureToPtr(val->baseSettings, IntPtr(&instance->data.args), false);
- instance->data.mod = { instance->data.args };
- instance->inv = ra::invokers(instance->data.args);
+ DeviceSettings^ defaultDev = gcnew DeviceSettings();
+ defaultDev->config = defaultDeviceConfig;
+ defaultDev->id = "Default";
+ devices->Add(defaultDev);
+
+ DeviceErrors^ devErrors = gcnew DeviceErrors(devices);
+ if (!devErrors->Empty()) {
+ sb->Append(profErrors->ToString());
+ }
+
+ devices->RemoveAt(devices->Count - 1);
+
+ if (sb->Length == 0) {
+ return nullptr;
+ }
+ else {
+ return sb->ToString();
+ }
+ }
+
+ JObject^ ToJObject()
+ {
+ auto dataQueue = gcnew Queue<array<float>^>();
+ auto empty = Array::Empty<float>();
+
+ for each (auto prof in profiles) {
+ if (prof->argsX.mode == AccelMode::lut) {
+ // data->Length is fixed for interop,
+ // temporary resize avoids serializing a bunch of zeros
+ Array::Resize(prof->argsX.data, prof->argsX.length);
+ }
+ else {
+ // table data may be used internally in any mode,
+ // so hide it when it's not needed for deserialization
+ dataQueue->Enqueue(prof->argsX.data);
+ prof->argsX.data = empty;
+ }
+
+ if (prof->argsY.mode == AccelMode::lut) {
+ Array::Resize(prof->argsY.data, prof->argsY.length);
+ }
+ else {
+ dataQueue->Enqueue(prof->argsY.data);
+ prof->argsY.data = empty;
+ }
+ }
+
+ JObject^ jObject = JObject::FromObject(this);
+ String^ capModes = String::Join(" | ", Enum::GetNames(CapMode::typeid));
+ String^ accelModes = String::Join(" | ", Enum::GetNames(AccelMode::typeid));
+ jObject->AddFirst(gcnew JProperty("### Cap modes ###", capModes));
+ jObject->AddFirst(gcnew JProperty("### Accel modes ###", accelModes));
- if (val->tables.x) {
- val->tables.x->SetData(instance->data.mod.accel.x);
+ for each (auto prof in profiles) {
+ if (prof->argsX.mode == AccelMode::lut) {
+ Array::Resize(prof->argsX.data, ra::LUT_RAW_DATA_CAPACITY);
+ }
+ else {
+ prof->argsX.data = dataQueue->Dequeue();
}
- if (val->tables.y) {
- val->tables.y->SetData(instance->data.mod.accel.y);
- }
+ if (prof->argsY.mode == AccelMode::lut) {
+ Array::Resize(prof->argsY.data, ra::LUT_RAW_DATA_CAPACITY);
+ }
+ else {
+ prof->argsY.data = dataQueue->Dequeue();
+ }
}
+ return jObject;
}
- static ManagedAccel^ GetActive()
+ String^ ToJSON()
{
+ return ToJObject()->ToString();
+ }
+
+ // returns (config, null) or (null, error message)
+ static Tuple<DriverConfig^, String^>^ Convert(String^ json)
+ {
+ auto jss = gcnew JsonSerializerSettings();
+ jss->DefaultValueHandling = DefaultValueHandling::Populate;
+ auto cfg = JsonConvert::DeserializeObject<DriverConfig^>(json, jss);
+ if (cfg == nullptr) throw gcnew JsonException("invalid JSON");
+
+ auto message = cfg->Errors();
+ if (message != nullptr) {
+ return gcnew Tuple<DriverConfig^, String^>(nullptr, message);
+ }
+ else {
+ cfg->accels = gcnew List<ManagedAccel^>();
+
+ if (cfg->profiles->Count == 0) {
+ cfg->profiles->Add(gcnew Profile());
+ }
+
+ for each (auto prof in cfg->profiles) {
+ cfg->accels->Add(gcnew ManagedAccel(prof));
+ }
+ return gcnew Tuple<DriverConfig^, String^>(cfg, nullptr);
+ }
+ }
+
+ static DriverConfig^ GetActive()
+ {
+ std::unique_ptr<std::byte[]> bytes;
try {
- auto active = gcnew ManagedAccel();
- ra::read(active->instance->data);
- active->instance->inv = ra::invokers(active->instance->data.args);
- return active;
+ bytes = ra::read();
}
- catch (const ra::error& e) {
+ catch (const std::exception& e) {
throw gcnew InteropException(e);
+ }
+
+ auto cfg = gcnew DriverConfig();
+ cfg->profiles = gcnew List<Profile^>();
+ cfg->accels = gcnew List<ManagedAccel^>();
+ cfg->devices = gcnew List<DeviceSettings^>();
+
+ auto* byte_ptr = bytes.get();
+ ra::io_base* base_data = reinterpret_cast<ra::io_base*>(byte_ptr);
+ cfg->defaultDeviceConfig.Init(base_data->default_dev_cfg);
+
+ byte_ptr += sizeof(ra::io_base);
+
+ ra::modifier_settings* modifier_data = reinterpret_cast<ra::modifier_settings*>(byte_ptr);
+ for (auto i = 0u; i < base_data->modifier_data_size; i++) {
+ auto& mod_settings = modifier_data[i];
+ cfg->profiles->Add(gcnew Profile(mod_settings.prof));
+ cfg->accels->Add(gcnew ManagedAccel(mod_settings));
+ }
+
+ byte_ptr += base_data->modifier_data_size * sizeof(ra::modifier_settings);
+
+ ra::device_settings* device_data = reinterpret_cast<ra::device_settings*>(byte_ptr);
+ for (auto i = 0u; i < base_data->device_data_size; i++) {
+ auto& dev_settings = device_data[i];
+ cfg->devices->Add(gcnew DeviceSettings(dev_settings));
}
+
+ return cfg;
}
-private:
- LutBase^ extract(ra::spaced_lut_mode mode, ra::accel_union& au)
+ static DriverConfig^ FromProfile(Profile^ prof)
{
- switch (mode) {
- case ra::spaced_lut_mode::off: return nullptr;
- case ra::spaced_lut_mode::linear: return gcnew LinearLut(au.lin_lut);
- case ra::spaced_lut_mode::binlog: return gcnew BinLogLut(au.log_lut);
- default: throw gcnew NotImplementedException();
- }
+ auto cfg = gcnew DriverConfig();
+ cfg->profiles = gcnew List<Profile^>();
+ cfg->accels = gcnew List<ManagedAccel^>();
+ cfg->devices = gcnew List<DeviceSettings^>();
+
+ cfg->profiles->Add(prof);
+ cfg->accels->Add(gcnew ManagedAccel(prof));
+ cfg->defaultDeviceConfig.Init(default_device_settings.config);
+ return cfg;
}
-};
-public ref struct VersionHelper
-{
- literal String^ VersionString = RA_VER_STRING;
+ static DriverConfig^ GetDefault()
+ {
+ return FromProfile(gcnew Profile());
+ }
- static Version^ ValidOrThrow()
+ static void Deactivate()
{
try {
- ra::version_t v = ra::valid_version_or_throw();
- return gcnew Version(v.major, v.minor, v.patch, 0);
+ ra::reset();
}
- catch (const ra::error& e) {
+ catch (const std::exception& e) {
throw gcnew InteropException(e);
}
}
+
+private:
+ DriverConfig() {}
};
+
diff --git a/wrapper/wrapper.vcxproj b/wrapper/wrapper.vcxproj
index 5d58614..256b978 100644
--- a/wrapper/wrapper.vcxproj
+++ b/wrapper/wrapper.vcxproj
@@ -60,7 +60,8 @@
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
- <AdditionalDependencies>User32.lib;</AdditionalDependencies>
+ <AdditionalDependencies>
+ </AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(SolutionDir)/common;</AdditionalIncludeDirectories>
@@ -74,7 +75,8 @@
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
- <AdditionalDependencies>User32.lib;</AdditionalDependencies>
+ <AdditionalDependencies>
+ </AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)signed\$(TargetFileName)" &amp;
@@ -98,6 +100,7 @@ copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)signed\Newtonsoft.Json.
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
+ <Reference Include="System" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="wrapper.rc" />
diff --git a/writer/Program.cs b/writer/Program.cs
index 724fa23..83daed1 100644
--- a/writer/Program.cs
+++ b/writer/Program.cs
@@ -11,74 +11,16 @@ namespace writer
class Program
{
+ static readonly string DefaultPath = "settings.json";
+ static readonly string Usage =
+ $"Usage: {AppDomain.CurrentDomain.FriendlyName} <settings file path>\n";
- static void ExitWithMessage(string msg)
+ static void Exit(string msg)
{
MessageBox.Show(msg, "Raw Accel writer");
Environment.Exit(1);
}
- static void ExitWithUsage()
- {
- ExitWithMessage($"Usage: {System.AppDomain.CurrentDomain.FriendlyName} <settings file path>");
- }
-
- delegate string PopOption(params string[] aliases);
-
- static string Read(string path)
- {
- return path == null ? null : File.ReadAllText(path);
- }
-
- static ExtendedSettings Parse(List<string> args)
- {
- PopOption maybePop = aliases =>
- {
- int idx = args.FindIndex(aliases.Contains);
-
- if (idx == -1) return null;
-
- if (idx == args.Count - 1) ExitWithUsage();
-
- string val = args[idx + 1];
- args.RemoveRange(idx, 2);
- return val;
- };
-
- string settingsPath = null;
-
- string tablePath = maybePop("/table", "/t");
-
- if (tablePath != null)
- {
- if (args.Count > 1) ExitWithUsage();
- else if (args.Count == 1) settingsPath = args[0];
-
- return new ExtendedSettings(Read(settingsPath), Read(tablePath));
- }
-
- string xTablePath = maybePop("/xtable", "/xt");
- string yTablePath = maybePop("/ytable", "/yt");
-
- if (args.Count > 1) ExitWithUsage();
- else if (args.Count == 1) settingsPath = args[0];
- else if (xTablePath == null && yTablePath == null) ExitWithUsage();
-
- string xTableJson = Read(xTablePath);
- string yTableJson = null;
-
- if (xTablePath != null && xTablePath.Equals(yTablePath))
- {
- yTableJson = xTableJson;
- }
- else
- {
- yTableJson = Read(yTablePath);
- }
-
- return new ExtendedSettings(Read(settingsPath), xTableJson, yTableJson);
- }
-
static void Main(string[] args)
{
try
@@ -87,34 +29,47 @@ namespace writer
}
catch (InteropException e)
{
- ExitWithMessage(e.Message);
+ Exit(e.Message);
}
try
{
- var settings = Parse(new List<string>(args));
- var errors = new SettingsErrors(settings);
-
- if (errors.Empty())
+ if (args.Length != 1)
{
- new ManagedAccel(settings).Activate();
+ if (File.Exists(DefaultPath))
+ {
+ Exit(Usage);
+ }
+ else
+ {
+ File.WriteAllText(DefaultPath, DriverConfig.GetDefault().ToJSON());
+ Exit($"{Usage}\n(generated default settings file '{DefaultPath}')");
+ }
}
else
{
- ExitWithMessage($"Bad settings:\n\n{errors}");
+ var result = DriverConfig.Convert(File.ReadAllText(args[0]));
+ if (result.Item2 == null)
+ {
+ result.Item1.Activate();
+ }
+ else
+ {
+ Exit($"Bad settings:\n\n{result.Item2}");
+ }
}
}
- catch (System.IO.FileNotFoundException e)
+ catch (FileNotFoundException e)
{
- ExitWithMessage(e.Message);
+ Exit(e.Message);
}
catch (JsonException e)
{
- ExitWithMessage($"Settings invalid:\n\n{e.Message}");
+ Exit($"Settings format invalid:\n\n{e.Message}");
}
catch (Exception e)
{
- ExitWithMessage($"Error:\n\n{e}");
+ Exit($"Error:\n\n{e}");
}
}
}