From 14bde56daf188bfc027dc8ead5b45ec0aa1109d6 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 01:51:31 -0400 Subject: update rest grapher is still broken refactored io / error handling a bit --- wrapper/wrapper.cpp | 463 ++++++++++++++++++++-------------------------------- 1 file changed, 177 insertions(+), 286 deletions(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 71a8cf6..757972b 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -1,17 +1,16 @@ #pragma once +#include +#include +#include + #include #include #include -#include -#include -#include - -#include "wrapper_io.hpp" - using namespace System; using namespace System::Collections::Generic; +using namespace System::IO; using namespace System::Runtime::InteropServices; using namespace System::Reflection; @@ -19,34 +18,39 @@ using namespace Windows::Forms; using namespace Newtonsoft::Json; +namespace ra = rawaccel; + +ra::settings default_settings; + [JsonConverter(Converters::StringEnumConverter::typeid)] public enum class AccelMode { - linear, classic, natural, naturalgain, power, motivity, noaccel + classic, jump, natural, power, motivity, noaccel +}; + +public enum class TableMode +{ + off, binlog, linear }; -[JsonObject(ItemRequired = Required::Always)] [StructLayout(LayoutKind::Sequential)] -public value struct AccelArgs +public value struct TableArgs { - double offset; + [JsonIgnore] + TableMode mode; + [MarshalAs(UnmanagedType::U1)] - bool legacyOffset; - double acceleration; - double scale; - double limit; - double exponent; - double midpoint; - double weight; - [JsonProperty("legacyCap")] - double scaleCap; - double gainCap; - [JsonProperty(Required = Required::Default)] - double speedCap; + bool transfer; + + [MarshalAs(UnmanagedType::U1)] + unsigned char partitions; + + short num; + double start; + double stop; }; generic -[JsonObject(ItemRequired = Required::Always)] [StructLayout(LayoutKind::Sequential)] public value struct Vec2 { @@ -54,7 +58,32 @@ public value struct Vec2 T y; }; -[JsonObject(ItemRequired = Required::Always)] +[StructLayout(LayoutKind::Sequential)] +public value struct AccelArgs +{ + AccelMode mode; + + [MarshalAs(UnmanagedType::U1)] + bool legacy; + + [JsonProperty(Required = Required::Default)] + TableArgs lutArgs; + + double offset; + double cap; + double accelClassic; + double accelNatural; + double accelMotivity; + double motivity; + double power; + double scale; + double weight; + double exponent; + double limit; + double midpoint; + double smooth; +}; + [StructLayout(LayoutKind::Sequential)] public value struct DomainArgs { @@ -66,20 +95,22 @@ public value struct DomainArgs [StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)] public ref struct DriverSettings { + literal double WriteDelayMs = ra::WRITE_DELAY; literal String^ Key = "Driver settings"; [JsonProperty("Degrees of rotation")] double rotation; - [JsonProperty("Degrees of angle snapping", Required = Required::Default)] + [JsonProperty("Degrees of angle snapping")] double snap; [JsonProperty("Use x as whole/combined accel")] [MarshalAs(UnmanagedType::U1)] bool combineMagnitudes; - [JsonProperty("Accel modes")] - Vec2 modes; + double dpi; + + double speedCap; [JsonProperty("Accel parameters")] Vec2 args; @@ -87,192 +118,125 @@ public ref struct DriverSettings [JsonProperty("Sensitivity multipliers")] Vec2 sensitivity; - [JsonProperty("Negative directional multipliers", Required = Required::Default)] + [JsonProperty("Negative directional multipliers")] Vec2 directionalMultipliers; - [JsonProperty("Stretches domain for horizontal vs vertical inputs", Required = Required::Default)] + [JsonProperty("Stretches domain for horizontal vs vertical inputs")] DomainArgs domainArgs; - [JsonProperty("Stretches accel range for horizontal vs vertical inputs", Required = Required::Default)] + [JsonProperty("Stretches accel range for horizontal vs vertical inputs")] Vec2 rangeXY; [JsonProperty(Required = Required::Default)] double minimumTime; - [JsonProperty("Device ID", Required = Required::Default)] - [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)] + [JsonProperty("Device ID")] + [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)] String^ deviceID = ""; bool ShouldSerializeminimumTime() { - return minimumTime > 0 && minimumTime != DEFAULT_TIME_MIN; + return minimumTime != ra::DEFAULT_TIME_MIN; } DriverSettings() { - domainArgs = { { 1, 1 }, 2 }; - rangeXY = { 1, 1 }; + Marshal::PtrToStructure(IntPtr(&default_settings), this); } -}; - - -template -void as_native(DriverSettings^ managed_args, NativeSettingsFunc fn) -{ -#ifndef NDEBUG - if (Marshal::SizeOf(managed_args) != sizeof(settings)) - throw gcnew InvalidOperationException("setting sizes differ"); -#endif - settings args; - Marshal::StructureToPtr(managed_args, (IntPtr)&args, false); - fn(args); - if constexpr (!std::is_invocable_v) { - Marshal::PtrToStructure((IntPtr)&args, managed_args); - } -} - -DriverSettings^ get_default() -{ - DriverSettings^ managed = gcnew DriverSettings(); - as_native(managed, [](settings& args) { - args = {}; - }); - return managed; -} - -void set_active(DriverSettings^ managed) -{ - as_native(managed, [](const settings& args) { - wrapper_io::writeToDriver(args); - }); -} - -DriverSettings^ get_active() -{ - DriverSettings^ managed = gcnew DriverSettings(); - as_native(managed, [](settings& args) { - wrapper_io::readFromDriver(args); - }); - return managed; -} - -void update_modifier(mouse_modifier& mod, DriverSettings^ managed, vec2 luts = {}) -{ - as_native(managed, [&](const settings& args) { - mod = { args, luts }; - }); -} - -using error_list_t = Collections::Generic::List; - -error_list_t^ get_accel_errors(AccelMode mode, AccelArgs^ args) -{ - accel_mode mode_native = (accel_mode)mode; - - auto is_mode = [mode_native](auto... modes) { - return ((mode_native == modes) || ...); - }; - using am = accel_mode; + void ToFile(String^ path) + { + using namespace Newtonsoft::Json::Linq; - auto error_list = gcnew error_list_t(); - - if (args->acceleration > 10 && is_mode(am::natural, am::naturalgain)) - error_list->Add("acceleration can not be greater than 10"); - else if (args->acceleration == 0 && is_mode(am::naturalgain)) - error_list->Add("acceleration must be positive"); - else if (args->acceleration < 0) { - bool additive = mode_native < am::power; - if (additive) error_list->Add("acceleration can not be negative, use a negative weight to compensate"); - else error_list->Add("acceleration can not be negative"); + JObject^ thisJO = JObject::FromObject(this); + String^ modes = String::Join(" | ", Enum::GetNames(AccelMode::typeid)); + thisJO->AddFirst(gcnew JProperty("### Accel Modes ###", modes)); + File::WriteAllText(path, thisJO->ToString(Formatting::Indented)); } - - if (args->scale <= 0) - error_list->Add("scale must be positive"); - if (args->exponent <= 1 && is_mode(am::classic)) - error_list->Add("exponent must be greater than 1"); - else if (args->exponent <= 0) - error_list->Add("exponent must be positive"); + static DriverSettings^ FromFile(String^ path) + { + if (!File::Exists(path)) + { + throw gcnew FileNotFoundException( + String::Format("Settings file not found at {0}", path)); + } - if (args->limit <= 1) - error_list->Add("limit must be greater than 1"); + auto settings = JsonConvert::DeserializeObject( + File::ReadAllText(path)); - if (args->midpoint <= 0) - error_list->Add("midpoint must be positive"); + if (settings == nullptr) { + throw gcnew JsonException(String::Format("{0} contains invalid JSON", path)); + } - if (args->offset < 0) - error_list->Add("offset can not be negative"); + return settings; + } +}; - return error_list; -} +public ref struct InteropException : public Exception { +public: + InteropException(String^ what) : + Exception(what) {} + InteropException(const char* what) : + Exception(gcnew String(what)) {} + InteropException(const std::exception& e) : + InteropException(e.what()) {} +}; -error_list_t^ get_other_errors(DriverSettings^ settings) +public ref class SettingsErrors { - auto error_list = gcnew error_list_t(); +public: + List^ list; + int countX; + int countY; - if (settings->rangeXY.x <= 0 || settings->rangeXY.y <= 0) - { - error_list->Add("range values must be positive"); - } + delegate void MsgHandler(const char*); - if (settings->domainArgs.domainXY.x <= 0 || settings->domainArgs.domainXY.y <= 0) + void Add(const char* msg) { - error_list->Add("domain values must be positive"); + list->Add(msclr::interop::marshal_as(msg)); } - if (settings->domainArgs.lpNorm <= 0) + SettingsErrors(DriverSettings^ settings) { - error_list->Add("lp norm must be positive"); - } - - return error_list; -} + MsgHandler^ del = gcnew MsgHandler(this, &SettingsErrors::Add); + GCHandle gch = GCHandle::Alloc(del); + auto fp = static_cast( + Marshal::GetFunctionPointerForDelegate(del).ToPointer()); -public ref class SettingsErrors -{ -public: - error_list_t^ x; - error_list_t^ y; - error_list_t^ other; + ra::settings args; + Marshal::StructureToPtr(settings, (IntPtr)&args, false); + + list = gcnew List(); + auto [cx, cy, _] = ra::valid(args, fp); + countX = cx; + countY = cy; + + gch.Free(); + } bool Empty() { - return (x == nullptr || x->Count == 0) && - (y == nullptr || y->Count == 0) && - (other == nullptr || other->Count == 0); + return list->Count == 0; } - virtual String^ ToString() override + virtual String^ ToString() override { - if (x == nullptr) throw; - Text::StringBuilder^ sb = gcnew Text::StringBuilder(); - if (y == nullptr) // assume combineMagnitudes + for each (auto s in list->GetRange(0, countX)) { - for each (String^ str in x) - { - sb->AppendLine(str); - } + sb->AppendFormat("x: {0}\n", s); } - else + for each (auto s in list->GetRange(countX, countY)) { - for each (String^ str in x) - { - sb->AppendFormat("x: {0}\n", str); - } - for each (String^ str in y) - { - sb->AppendFormat("y: {0}\n", str); - } + sb->AppendFormat("y: {0}\n", s); } - - for each (String ^ str in other) + for each (auto s in list->GetRange(countY, list->Count)) { - sb->AppendLine(str); + sb->AppendLine(s); } - + return sb->ToString(); } }; @@ -314,7 +278,7 @@ public ref struct RawInputInterop } catch (const std::exception& e) { - throw gcnew System::Exception(gcnew String(e.what())); + throw gcnew InteropException(e); } } @@ -336,80 +300,32 @@ public ref struct RawInputInterop } catch (const std::exception& e) { - throw gcnew System::Exception(gcnew String(e.what())); + throw gcnew InteropException(e); } } }; -public ref struct DriverInterop +public ref class ManagedAccel { - literal double WriteDelayMs = WRITE_DELAY; - static initonly DriverSettings^ DefaultSettings = get_default(); - - static DriverSettings^ GetActiveSettings() - { - return get_active(); - } - - static void Write(DriverSettings^ args) - { - set_active(args); - } + ra::io_t* const instance = new ra::io_t(); - static DriverSettings^ GetDefaultSettings() - { - return get_default(); - } +public: + ManagedAccel() {}; - static SettingsErrors^ GetSettingsErrors(DriverSettings^ args) + ManagedAccel(DriverSettings^ settings) { - auto errors = gcnew SettingsErrors(); - - errors->x = get_accel_errors(args->modes.x, args->args.x); - - if (!args->combineMagnitudes) { - errors->y = get_accel_errors(args->modes.y, args->args.y); - } - - errors->other = get_other_errors(args); - - return errors; + Settings = settings; } - - - static error_list_t^ GetAccelErrors(AccelMode mode, AccelArgs^ args) - { - return get_accel_errors(mode, args); - } -}; - -public ref class ManagedAccel -{ - mouse_modifier* const modifier_instance = new mouse_modifier(); -#ifdef RA_LOOKUP - si_pair* const lut_x = new si_pair[LUT_SIZE]; - si_pair* const lut_y = new si_pair[LUT_SIZE]; -#else - si_pair* lut_x = nullptr; - si_pair* lut_y = nullptr; -#endif - -public: - virtual ~ManagedAccel() { - delete modifier_instance; - delete[] lut_x; - delete[] lut_y; + delete instance; } !ManagedAccel() { - delete modifier_instance; - delete[] lut_x; - delete[] lut_y; + delete instance; } Tuple^ Accelerate(int x, int y, double time) @@ -418,89 +334,64 @@ public: (double)x, (double)y }; - modifier_instance->modify(in_out_vec, time); + + instance->mod.modify(in_out_vec, time); return gcnew Tuple(in_out_vec.x, in_out_vec.y); } - void UpdateFromSettings(DriverSettings^ args) + void Activate() { - update_modifier( - *modifier_instance, - args, - vec2{ lut_x, lut_y } - ); + try { + ra::write(*instance); + } + catch (const ra::error& e) { + throw gcnew InteropException(e); + } } - static ManagedAccel^ GetActiveAccel() + property DriverSettings^ Settings { - settings args; - wrapper_io::readFromDriver(args); + DriverSettings^ get() + { + DriverSettings^ settings = gcnew DriverSettings(); + Marshal::PtrToStructure(IntPtr(&instance->args), settings); + return settings; + } - auto active = gcnew ManagedAccel(); - *active->modifier_instance = { - args - , vec2 { active->lut_x, active->lut_y } - }; - return active; - } -}; + void set(DriverSettings^ val) + { + Marshal::StructureToPtr(val, IntPtr(&instance->args), false); + instance->mod = { instance->args }; + } -public ref struct RawAccelVersion -{ - literal String^ value = RA_VER_STRING; -}; + } -public ref struct VersionException : public Exception -{ -public: - VersionException() {} - VersionException(String^ what) : Exception(what) {} + static ManagedAccel^ GetActive() + { + try { + auto active = gcnew ManagedAccel(); + ra::read(*active->instance); + return active; + } + catch (const ra::error& e) { + throw gcnew InteropException(e); + } + } }; -Version^ convert(rawaccel::version_t v) -{ - return gcnew Version(v.major, v.minor, v.patch, 0); -} - public ref struct VersionHelper { + literal String^ VersionString = RA_VER_STRING; - static Version^ ValidateAndGetDriverVersion(Version^ wrapperTarget) + static Version^ ValidOrThrow() { - Version^ wrapperActual = VersionHelper::typeid->Assembly->GetName()->Version; - - if (wrapperTarget != wrapperActual) { - throw gcnew VersionException("version mismatch, expected wrapper.dll v" + wrapperActual); - } - - version_t drv_ver; - try { - wrapper_io::getDriverVersion(drv_ver); - } - catch (DriverNotInstalledException^ ex) { - throw gcnew VersionException(ex->Message); - } - catch (DriverIOException^) { - // Assume version ioctl is unimplemented (driver version < v1.3.0) - throw gcnew VersionException("driver version is out of date\n\nrun installer.exe to reinstall"); - } - - Version^ drv_ver_managed = convert(drv_ver); - - if (drv_ver_managed < convert(min_driver_version)) { - throw gcnew VersionException( - String::Format("driver version is out of date (v{0})\n\nrun installer.exe to reinstall", - drv_ver_managed)); - } - else if (drv_ver_managed > wrapperActual) { - throw gcnew VersionException( - String::Format("newer driver version is installed (v{0})", - drv_ver_managed)); + ra::version_t v = ra::valid_version_or_throw(); + return gcnew Version(v.major, v.minor, v.patch, 0); } - else { - return drv_ver_managed; + catch (const ra::error& e) { + throw gcnew InteropException(e); } } -- cgit v1.2.3 From 98de0eaac2f6d780da8ff4ad9533dad10be40204 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 18:15:50 -0400 Subject: add flag to negate device match --- wrapper/wrapper.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 757972b..873b156 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -130,6 +130,10 @@ public ref struct DriverSettings [JsonProperty(Required = Required::Default)] double minimumTime; + [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 = ""; -- cgit v1.2.3 From e9866f27d78d9909fd4639cbd14a54b8ad5c2ec1 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 18:33:00 -0400 Subject: driver - apply accel disregarding num packets add setting for max time threshold --- wrapper/wrapper.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 873b156..ab129a8 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -130,6 +130,9 @@ public ref struct DriverSettings [JsonProperty(Required = Required::Default)] double minimumTime; + [JsonProperty(Required = Required::Default)] + double maximumTime; + [JsonProperty("Ignore devices with matching ID")] [MarshalAs(UnmanagedType::U1)] bool ignore; @@ -143,6 +146,11 @@ public ref struct DriverSettings return minimumTime != ra::DEFAULT_TIME_MIN; } + bool ShouldSerializemaximumTime() + { + return maximumTime != ra::DEFAULT_TIME_MAX; + } + DriverSettings() { Marshal::PtrToStructure(IntPtr(&default_settings), this); -- cgit v1.2.3 From 3751ac95831412dbdf9de9744c0ef59c34033d3d Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 20:56:29 -0400 Subject: add minimum to complement speed cap important feature fixes some validation checks --- wrapper/wrapper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index ab129a8..0af7c28 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -110,7 +110,10 @@ public ref struct DriverSettings double dpi; - double speedCap; + [JsonIgnore] + double minimumSpeed; + [JsonProperty("Input Speed Cap")] + double maximumSpeed; [JsonProperty("Accel parameters")] Vec2 args; -- cgit v1.2.3 From d8140fb31ba622f48756986d4d66db6b6ab8b511 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 1 Apr 2021 23:28:41 -0400 Subject: use callbacks for applying accel --- wrapper/wrapper.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 0af7c28..84756af 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -321,9 +321,14 @@ public ref struct RawInputInterop }; +struct instance_t { + ra::io_t data; + vec2 inv; +}; + public ref class ManagedAccel { - ra::io_t* const instance = new ra::io_t(); + instance_t* const instance = new instance_t(); public: ManagedAccel() {}; @@ -350,7 +355,7 @@ public: (double)y }; - instance->mod.modify(in_out_vec, time); + instance->data.mod.modify(in_out_vec, instance->inv, time); return gcnew Tuple(in_out_vec.x, in_out_vec.y); } @@ -358,7 +363,7 @@ public: void Activate() { try { - ra::write(*instance); + ra::write(instance->data); } catch (const ra::error& e) { throw gcnew InteropException(e); @@ -370,14 +375,15 @@ public: DriverSettings^ get() { DriverSettings^ settings = gcnew DriverSettings(); - Marshal::PtrToStructure(IntPtr(&instance->args), settings); + Marshal::PtrToStructure(IntPtr(&instance->data.args), settings); return settings; } void set(DriverSettings^ val) { - Marshal::StructureToPtr(val, IntPtr(&instance->args), false); - instance->mod = { instance->args }; + Marshal::StructureToPtr(val, IntPtr(&instance->data.args), false); + instance->data.mod = { instance->data.args }; + instance->inv = ra::invokers(instance->data.args); } } @@ -386,7 +392,8 @@ public: { try { auto active = gcnew ManagedAccel(); - ra::read(*active->instance); + ra::read(active->instance->data); + active->instance->inv = ra::invokers(active->instance->data.args); return active; } catch (const ra::error& e) { -- cgit v1.2.3 From ebfd5a8af07bc5fdf5b463714d8030e49eac53ba Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Thu, 1 Apr 2021 22:08:01 -0700 Subject: Add differing table types --- wrapper/wrapper.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 84756af..7583312 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -25,7 +25,7 @@ ra::settings default_settings; [JsonConverter(Converters::StringEnumConverter::typeid)] public enum class AccelMode { - classic, jump, natural, power, motivity, noaccel + classic, jump, natural, power, motivity, lut, noaccel }; public enum class TableMode @@ -33,12 +33,20 @@ public enum class TableMode off, binlog, linear }; +public enum class TableType +{ + spaced, arbitrary +}; + [StructLayout(LayoutKind::Sequential)] public value struct TableArgs { [JsonIgnore] TableMode mode; + [JsonIgnore] + TableType type; + [MarshalAs(UnmanagedType::U1)] bool transfer; @@ -50,6 +58,7 @@ public value struct TableArgs double stop; }; + generic [StructLayout(LayoutKind::Sequential)] public value struct Vec2 @@ -58,6 +67,24 @@ public value struct Vec2 T y; }; +public ref struct SpacedTable +{ + [JsonProperty("Arguments for spacing in table")] + TableArgs args; + + [JsonProperty("Series of points for use in curve")] + List^ points; +}; + +public ref struct ArbitraryTable +{ + [JsonProperty("Whether points affect velocity (true) or sensitivity (false)")] + bool transfer; + + [JsonProperty("Series of points for use in curve")] + List>^ points; +}; + [StructLayout(LayoutKind::Sequential)] public value struct AccelArgs { @@ -144,6 +171,12 @@ public ref struct DriverSettings [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)] String^ deviceID = ""; + [JsonIgnore] + SpacedTable^ SpacedTable; + + [JsonIgnore] + ArbitraryTable^ ArbitraryTable; + bool ShouldSerializeminimumTime() { return minimumTime != ra::DEFAULT_TIME_MIN; -- cgit v1.2.3 From 7c1f14845bc948e9ea25908e96099203d9433a69 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 6 Apr 2021 01:21:42 -0400 Subject: update wrapper + writer to handle lut grapher is building but applying options still broken for the most part --- wrapper/wrapper.cpp | 414 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 272 insertions(+), 142 deletions(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 7583312..eb7d4d0 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -1,22 +1,17 @@ #pragma once +#include "interop-exception.h" + #include #include -#include - -#include -#include -#include using namespace System; using namespace System::Collections::Generic; -using namespace System::IO; using namespace System::Runtime::InteropServices; using namespace System::Reflection; -using namespace Windows::Forms; - using namespace Newtonsoft::Json; +using namespace Newtonsoft::Json::Linq; namespace ra = rawaccel; @@ -25,17 +20,13 @@ ra::settings default_settings; [JsonConverter(Converters::StringEnumConverter::typeid)] public enum class AccelMode { - classic, jump, natural, power, motivity, lut, noaccel + classic, jump, natural, power, motivity, noaccel }; +[JsonConverter(Converters::StringEnumConverter::typeid)] public enum class TableMode { - off, binlog, linear -}; - -public enum class TableType -{ - spaced, arbitrary + off, binlog, linear, arbitrary }; [StructLayout(LayoutKind::Sequential)] @@ -44,9 +35,6 @@ public value struct TableArgs [JsonIgnore] TableMode mode; - [JsonIgnore] - TableType type; - [MarshalAs(UnmanagedType::U1)] bool transfer; @@ -67,24 +55,6 @@ public value struct Vec2 T y; }; -public ref struct SpacedTable -{ - [JsonProperty("Arguments for spacing in table")] - TableArgs args; - - [JsonProperty("Series of points for use in curve")] - List^ points; -}; - -public ref struct ArbitraryTable -{ - [JsonProperty("Whether points affect velocity (true) or sensitivity (false)")] - bool transfer; - - [JsonProperty("Series of points for use in curve")] - List>^ points; -}; - [StructLayout(LayoutKind::Sequential)] public value struct AccelArgs { @@ -171,12 +141,6 @@ public ref struct DriverSettings [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)] String^ deviceID = ""; - [JsonIgnore] - SpacedTable^ SpacedTable; - - [JsonIgnore] - ArbitraryTable^ ArbitraryTable; - bool ShouldSerializeminimumTime() { return minimumTime != ra::DEFAULT_TIME_MIN; @@ -191,49 +155,254 @@ public ref struct DriverSettings { Marshal::PtrToStructure(IntPtr(&default_settings), this); } - - void ToFile(String^ path) +}; + +[JsonObject(ItemRequired = Required::Always)] +public ref struct LutBase abstract +{ + [JsonConverter(Converters::StringEnumConverter::typeid)] + enum class Mode { - using namespace Newtonsoft::Json::Linq; + logarithmic, linear, arbitrary + } mode; - JObject^ thisJO = JObject::FromObject(this); - String^ modes = String::Join(" | ", Enum::GetNames(AccelMode::typeid)); - thisJO->AddFirst(gcnew JProperty("### Accel Modes ###", modes)); - File::WriteAllText(path, thisJO->ToString(Formatting::Indented)); + virtual void SetArgs(TableArgs%) abstract; + virtual void SetData(ra::accel_union&) abstract; +}; + +[JsonObject(ItemRequired = Required::Always)] +public ref struct ArbitraryLut sealed : public LutBase +{ + [JsonProperty("Whether points affect velocity (true) or sensitivity (false)")] + bool transfer; + + array^ data; + + virtual void SetArgs(TableArgs% args) override + { + args.mode = TableMode::arbitrary; + args.transfer = transfer; } - static DriverSettings^ FromFile(String^ path) + virtual void SetData(ra::accel_union& accel) override { - if (!File::Exists(path)) - { - throw gcnew FileNotFoundException( - String::Format("Settings file not found at {0}", path)); + throw gcnew NotImplementedException(); + } + +}; + +[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^ data; + + void SetArgsBase(TableArgs% args) + { + args.transfer = transfer; + args.start = start; + args.stop = stop; + } + + void SetDataBase(ra::accel_union& accel) + { + if (size_t(data->LongLength) > ra::LUT_CAPACITY) { + throw gcnew InteropException("data is too large"); } + } +}; - auto settings = JsonConvert::DeserializeObject( - File::ReadAllText(path)); +[JsonObject(ItemRequired = Required::Always)] +public ref struct LinearLut sealed : public SpacedLut +{ + LinearLut(const ra::linear_lut& table) + { + mode = Mode::linear; + transfer = table.transfer; + start = table.range.start; + stop = table.range.stop; + data = gcnew array(table.range.num); + + pin_ptr pdata = &data[0]; + std::memcpy(pdata, &table.data, sizeof(float) * data->Length); + } - if (settings == nullptr) { - throw gcnew JsonException(String::Format("{0} contains invalid JSON", path)); + virtual void SetArgs(TableArgs% args) override + { + SetArgsBase(args); + args.num = data->Length; + args.mode = TableMode::linear; + } + + virtual void SetData(ra::accel_union& accel) override + { + SetDataBase(accel); + pin_ptr 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 +{ + short num; + + 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(1 + num * (int(stop) - int(start))); + + pin_ptr pdata = &data[0]; + std::memcpy(pdata, &table.data, sizeof(float) * data->Length); + } + + virtual void SetArgs(TableArgs% args) override + { + SetArgsBase(args); + args.num = num; + args.mode = TableMode::binlog; + } + + virtual void SetData(ra::accel_union& accel) override + { + SetDataBase(accel); + + if (data->Length != 1 + num * (int(stop) - int(start))) { + throw gcnew InteropException("size of data does not match args"); } - return settings; + pin_ptr pdata = &data[0]; + std::memcpy(&accel.log_lut.data, pdata, sizeof(float) * data->Length); } }; -public ref struct InteropException : public Exception { -public: - InteropException(String^ what) : - Exception(what) {} - InteropException(const char* what) : - Exception(gcnew String(what)) {} - InteropException(const std::exception& e) : - InteropException(e.what()) {} +public ref struct RaConvert { + + static DriverSettings^ Settings(String^ json) + { + return NonNullable(json); + } + + 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); + } + + static LutBase^ Table(String^ json) + { + JObject^ jObject = JObject::Parse(json); + + if ((Object^)jObject == nullptr) { + throw gcnew JsonException("bad json"); + } + + LutBase^ base = NonNullable(jObject); + + switch (base->mode) { + case LutBase::Mode::logarithmic: + return NonNullable(jObject); + case LutBase::Mode::linear: + return NonNullable(jObject); + case LutBase::Mode::arbitrary: + return NonNullable(jObject); + default: + throw gcnew NotImplementedException(); + } + } + + static String^ Table(LutBase^ lut) + { + auto serializerSettings = gcnew JsonSerializerSettings(); + return JsonConvert::SerializeObject( + lut, lut->GetType(), Formatting::Indented, serializerSettings); + }; + + generic + static T NonNullable(String^ json) + { + T obj = JsonConvert::DeserializeObject(json); + if (obj == nullptr) throw gcnew JsonException("invalid JSON"); + return obj; + } + + generic + static T NonNullable(JObject^ jObject) + { + T obj = jObject->ToObject(); + if (obj == nullptr) throw gcnew JsonException("invalid JSON"); + return obj; + } +}; + +public ref struct ExtendedSettings { + DriverSettings^ baseSettings; + Vec2 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) + { + if (settingsJson) { + baseSettings = RaConvert::Settings(settingsJson); + } + else { + baseSettings = gcnew DriverSettings(); + } + + if (xTableJson || yTableJson) { + baseSettings->combineMagnitudes = !byComponent; + } + + if (xTableJson) { + tables.x = RaConvert::Table(xTableJson); + tables.x->SetArgs(baseSettings->args.x.lutArgs); + } + + if (yTableJson) { + if (Object::ReferenceEquals(yTableJson, xTableJson)) { + tables.y = tables.x; + } + else { + tables.y = RaConvert::Table(yTableJson); + } + + tables.y->SetArgs(baseSettings->args.y.lutArgs); + } + } + }; public ref class SettingsErrors { public: + List^ list; int countX; int countY; @@ -242,9 +411,12 @@ public: void Add(const char* msg) { - list->Add(msclr::interop::marshal_as(msg)); + list->Add(gcnew String(msg)); } + SettingsErrors(ExtendedSettings^ settings) : + SettingsErrors(settings->baseSettings) {} + SettingsErrors(DriverSettings^ settings) { MsgHandler^ del = gcnew MsgHandler(this, &SettingsErrors::Add); @@ -289,71 +461,6 @@ public: } }; -struct device_info { - std::wstring name; - std::wstring id; -}; - -std::vector get_unique_device_info() { - std::vector info; - - rawinput_foreach_with_interface([&](const auto& dev, const WCHAR* name) { - info.push_back({ - L"", // get_property_wstr(name, &DEVPKEY_Device_FriendlyName), /* doesn't work */ - dev_id_from_interface(name) - }); - }); - - std::sort(info.begin(), info.end(), - [](auto&& l, auto&& r) { return l.id < r.id; }); - auto last = std::unique(info.begin(), info.end(), - [](auto&& l, auto&& r) { return l.id == r.id; }); - info.erase(last, info.end()); - - return info; -} - -public ref struct RawInputInterop -{ - static void AddHandlesFromID(String^ deviceID, List^ rawInputHandles) - { - try - { - std::vector nativeHandles = rawinput_handles_from_dev_id( - msclr::interop::marshal_as(deviceID)); - - for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh)); - } - catch (const std::exception& e) - { - throw gcnew InteropException(e); - } - } - - static List>^ GetDeviceIDs() - { - try - { - auto managed = gcnew List>(); - - for (auto&& [name, id] : get_unique_device_info()) - { - managed->Add( - ValueTuple( - msclr::interop::marshal_as(name), - msclr::interop::marshal_as(id))); - } - - return managed; - } - catch (const std::exception& e) - { - throw gcnew InteropException(e); - } - } - -}; - struct instance_t { ra::io_t data; vec2 inv; @@ -364,9 +471,9 @@ public ref class ManagedAccel instance_t* const instance = new instance_t(); public: - ManagedAccel() {}; + ManagedAccel() {} - ManagedAccel(DriverSettings^ settings) + ManagedAccel(ExtendedSettings^ settings) { Settings = settings; } @@ -403,20 +510,32 @@ public: } } - property DriverSettings^ Settings + property ExtendedSettings^ Settings { - DriverSettings^ get() + ExtendedSettings^ get() { - DriverSettings^ settings = gcnew DriverSettings(); - Marshal::PtrToStructure(IntPtr(&instance->data.args), settings); + auto settings = gcnew ExtendedSettings(); + Marshal::PtrToStructure(IntPtr(&instance->data.args), settings->baseSettings); + settings->tables.x = extract(instance->data.args.argsv.x.lut_args.mode, + instance->data.mod.accels.x); + settings->tables.y = extract(instance->data.args.argsv.y.lut_args.mode, + instance->data.mod.accels.y); return settings; } - void set(DriverSettings^ val) + void set(ExtendedSettings^ val) { - Marshal::StructureToPtr(val, IntPtr(&instance->data.args), false); + Marshal::StructureToPtr(val->baseSettings, IntPtr(&instance->data.args), false); instance->data.mod = { instance->data.args }; instance->inv = ra::invokers(instance->data.args); + + if (val->tables.x) { + val->tables.x->SetData(instance->data.mod.accels.x); + } + + if (val->tables.y) { + val->tables.y->SetData(instance->data.mod.accels.y); + } } } @@ -433,6 +552,18 @@ public: throw gcnew InteropException(e); } } + +private: + LutBase^ extract(ra::table_mode mode, ra::accel_union& au) + { + switch (mode) { + case ra::table_mode::off: return nullptr; + case ra::table_mode::linear: return gcnew LinearLut(au.lin_lut); + case ra::table_mode::binlog: return gcnew BinLogLut(au.log_lut); + case ra::table_mode::arbitrary: + default: throw gcnew NotImplementedException(); + } + } }; public ref struct VersionHelper @@ -449,5 +580,4 @@ public ref struct VersionHelper throw gcnew InteropException(e); } } - }; -- cgit v1.2.3 From 758de1d236f591de1d8b2fba4c58bfd8d5bbd26e Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 6 Apr 2021 18:04:28 -0700 Subject: Rename accelMotivity to growthRate --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index eb7d4d0..7136fc9 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -70,7 +70,7 @@ public value struct AccelArgs double cap; double accelClassic; double accelNatural; - double accelMotivity; + double growthRate; double motivity; double power; double scale; -- cgit v1.2.3 From 258fcd3bd236a787f07d7dac2049be524d86cb75 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Tue, 6 Apr 2021 23:11:20 -0700 Subject: Fix natural legacy algorithm, rename accelNatural to decayRate --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 7136fc9..a28e199 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -69,7 +69,7 @@ public value struct AccelArgs double offset; double cap; double accelClassic; - double accelNatural; + double decayRate; double growthRate; double motivity; double power; -- cgit v1.2.3 From 5e858b059436375ed1c17f7dc1b3e47a7e8e1d5d Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Wed, 7 Apr 2021 01:05:59 -0700 Subject: Add active value labels for gain switch --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index a28e199..7992de6 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -20,7 +20,7 @@ ra::settings default_settings; [JsonConverter(Converters::StringEnumConverter::typeid)] public enum class AccelMode { - classic, jump, natural, power, motivity, noaccel + classic, jump, natural, power, motivity, lut, noaccel }; [JsonConverter(Converters::StringEnumConverter::typeid)] -- cgit v1.2.3 From e3fe51dde5afed99a393e3b1b1f611fde011d9f3 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 8 Apr 2021 12:38:08 -0400 Subject: fix some things --- wrapper/wrapper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 7992de6..6376100 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -517,9 +517,9 @@ public: auto settings = gcnew ExtendedSettings(); Marshal::PtrToStructure(IntPtr(&instance->data.args), settings->baseSettings); settings->tables.x = extract(instance->data.args.argsv.x.lut_args.mode, - instance->data.mod.accels.x); + instance->data.mod.accel.x); settings->tables.y = extract(instance->data.args.argsv.y.lut_args.mode, - instance->data.mod.accels.y); + instance->data.mod.accel.y); return settings; } @@ -530,11 +530,11 @@ public: instance->inv = ra::invokers(instance->data.args); if (val->tables.x) { - val->tables.x->SetData(instance->data.mod.accels.x); + val->tables.x->SetData(instance->data.mod.accel.x); } if (val->tables.y) { - val->tables.y->SetData(instance->data.mod.accels.y); + val->tables.y->SetData(instance->data.mod.accel.y); } } -- cgit v1.2.3 From 74ffcb8553795f4b50e544a1b2a0e53aec32a860 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Thu, 8 Apr 2021 21:48:17 -0400 Subject: make sizeof arbitrary close to others refactor constructor/fix conversions --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 6376100..f7da5d4 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -210,7 +210,7 @@ public ref struct SpacedLut abstract : public LutBase void SetDataBase(ra::accel_union& accel) { - if (size_t(data->LongLength) > ra::LUT_CAPACITY) { + if (size_t(data->LongLength) > ra::SPACED_LUT_CAPACITY) { throw gcnew InteropException("data is too large"); } } -- cgit v1.2.3 From aad1822effaa16c29dba316601923f31d66ce063 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Thu, 8 Apr 2021 21:49:25 -0700 Subject: Progress in arbitrary --- wrapper/wrapper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 7992de6..263f019 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -186,7 +186,8 @@ public ref struct ArbitraryLut sealed : public LutBase virtual void SetData(ra::accel_union& accel) override { - throw gcnew NotImplementedException(); + pin_ptr pdata = &data[0,0]; + std::memcpy(&accel.arb_lut.raw_data_in, pdata, sizeof(float) * data->Length * 2); } }; -- cgit v1.2.3 From 98afb6f2b04f4f93bd9e82b9882fb4a369b155d3 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Thu, 8 Apr 2021 22:40:40 -0700 Subject: Try reinterpret cast --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index f901ce1..b840cea 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -188,7 +188,7 @@ public ref struct ArbitraryLut sealed : public LutBase { pin_ptr pdata = &data[0,0]; - accel.arb_lut.fill(pdata, data->Length); + accel.arb_lut.fill(reinterpret_cast*>(pdata), data->Length); } }; -- cgit v1.2.3 From f0d4915a01de47d47a26398462f5ed325b317077 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Thu, 8 Apr 2021 23:32:03 -0700 Subject: Something works and that's pretty cool --- wrapper/wrapper.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index b840cea..3ff9129 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -158,7 +158,7 @@ public ref struct DriverSettings }; [JsonObject(ItemRequired = Required::Always)] -public ref struct LutBase abstract +public ref struct LutBase { [JsonConverter(Converters::StringEnumConverter::typeid)] enum class Mode @@ -166,8 +166,8 @@ public ref struct LutBase abstract logarithmic, linear, arbitrary } mode; - virtual void SetArgs(TableArgs%) abstract; - virtual void SetData(ra::accel_union&) abstract; + virtual void SetArgs(TableArgs%) {} + virtual void SetData(ra::accel_union&) {} }; [JsonObject(ItemRequired = Required::Always)] @@ -220,6 +220,10 @@ public ref struct SpacedLut abstract : public LutBase [JsonObject(ItemRequired = Required::Always)] public ref struct LinearLut sealed : public SpacedLut { + LinearLut() + { + } + LinearLut(const ra::linear_lut& table) { mode = Mode::linear; -- cgit v1.2.3 From e5e7896d0df3f73bf153a83dd5022ccf6365f8ee Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Fri, 9 Apr 2021 00:42:55 -0700 Subject: Fixed some bugs --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 3ff9129..74e8683 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -188,7 +188,7 @@ public ref struct ArbitraryLut sealed : public LutBase { pin_ptr pdata = &data[0,0]; - accel.arb_lut.fill(reinterpret_cast*>(pdata), data->Length); + accel.arb_lut.fill(reinterpret_cast*>(pdata), data->Length/2); } }; -- cgit v1.2.3 From 060b79bda0b656bd9aec253389706681a565443e Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Fri, 9 Apr 2021 16:27:32 -0700 Subject: Some more small additions and fixes --- wrapper/wrapper.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 74e8683..1f27415 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -178,6 +178,20 @@ public ref struct ArbitraryLut sealed : public LutBase array^ data; + ArbitraryLut() + { + } + + ArbitraryLut(const ra::arbitrary_lut& table) + { + mode = Mode::arbitrary; + transfer = true; + data = gcnew array(table.last_arbitrary_index + 1, 2); + + pin_ptr pdata = &data[0,0]; + std::memcpy(pdata, &table.raw_data_in, sizeof(float) * 2 * (table.last_arbitrary_index + 1)); + } + virtual void SetArgs(TableArgs% args) override { args.mode = TableMode::arbitrary; @@ -565,7 +579,7 @@ private: case ra::table_mode::off: return nullptr; case ra::table_mode::linear: return gcnew LinearLut(au.lin_lut); case ra::table_mode::binlog: return gcnew BinLogLut(au.log_lut); - case ra::table_mode::arbitrary: + case ra::table_mode::arbitrary: return gcnew ArbitraryLut(au.arb_lut); default: throw gcnew NotImplementedException(); } } -- cgit v1.2.3 From a6926be0e911b7b7637861866f41c3bca31a87a3 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 13 Apr 2021 23:59:21 -0400 Subject: move arbitrary input into settings separate arbitrary mode from spaced modes, arbitrary now deserializes from default settings file --- wrapper/wrapper.cpp | 177 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 69 deletions(-) (limited to 'wrapper/wrapper.cpp') diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 1f27415..6344b77 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -9,7 +9,7 @@ using namespace System; using namespace System::Collections::Generic; using namespace System::Runtime::InteropServices; using namespace System::Reflection; - +using namespace System::Runtime::Serialization; using namespace Newtonsoft::Json; using namespace Newtonsoft::Json::Linq; @@ -20,20 +20,20 @@ ra::settings default_settings; [JsonConverter(Converters::StringEnumConverter::typeid)] public enum class AccelMode { - classic, jump, natural, power, motivity, lut, noaccel + classic, jump, natural, motivity, power, lut, noaccel }; [JsonConverter(Converters::StringEnumConverter::typeid)] -public enum class TableMode +public enum class SpacedTableMode { - off, binlog, linear, arbitrary + off, binlog, linear }; [StructLayout(LayoutKind::Sequential)] -public value struct TableArgs +public value struct SpacedTableArgs { [JsonIgnore] - TableMode mode; + SpacedTableMode mode; [MarshalAs(UnmanagedType::U1)] bool transfer; @@ -55,6 +55,50 @@ public value struct Vec2 T y; }; +[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>^ 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 { @@ -63,9 +107,6 @@ public value struct AccelArgs [MarshalAs(UnmanagedType::U1)] bool legacy; - [JsonProperty(Required = Required::Default)] - TableArgs lutArgs; - double offset; double cap; double accelClassic; @@ -79,6 +120,11 @@ public value struct AccelArgs double limit; double midpoint; double smooth; + + [JsonProperty(Required = Required::Default)] + SpacedTableArgs spacedTableArgs; + + TableArgs tableData; }; [StructLayout(LayoutKind::Sequential)] @@ -155,57 +201,48 @@ public ref struct DriverSettings { Marshal::PtrToStructure(IntPtr(&default_settings), this); } -}; -[JsonObject(ItemRequired = Required::Always)] -public ref struct LutBase -{ - [JsonConverter(Converters::StringEnumConverter::typeid)] - enum class Mode +private: + [OnDeserialized] + void OnDeserializedMethod(StreamingContext context) { - logarithmic, linear, arbitrary - } mode; + args.x.tableData.length = args.x.tableData.points->Length; + args.y.tableData.length = args.y.tableData.points->Length; - virtual void SetArgs(TableArgs%) {} - virtual void SetData(ra::accel_union&) {} -}; - -[JsonObject(ItemRequired = Required::Always)] -public ref struct ArbitraryLut sealed : public LutBase -{ - [JsonProperty("Whether points affect velocity (true) or sensitivity (false)")] - bool transfer; - - array^ data; - - ArbitraryLut() - { + array>::Resize(args.x.tableData.points, ra::ARB_LUT_CAPACITY); + array>::Resize(args.y.tableData.points, ra::ARB_LUT_CAPACITY); } - ArbitraryLut(const ra::arbitrary_lut& table) + [OnSerializing] + void OnSerializingMethod(StreamingContext context) { - mode = Mode::arbitrary; - transfer = true; - data = gcnew array(table.last_arbitrary_index + 1, 2); - - pin_ptr pdata = &data[0,0]; - std::memcpy(pdata, &table.raw_data_in, sizeof(float) * 2 * (table.last_arbitrary_index + 1)); + array>::Resize(args.x.tableData.points, args.x.tableData.length); + array>::Resize(args.y.tableData.points, args.y.tableData.length); } - virtual void SetArgs(TableArgs% args) override + [OnSerialized] + void OnSerializedMethod(StreamingContext context) { - args.mode = TableMode::arbitrary; - args.transfer = transfer; + array>::Resize(args.x.tableData.points, ra::ARB_LUT_CAPACITY); + array>::Resize(args.y.tableData.points, ra::ARB_LUT_CAPACITY); } - virtual void SetData(ra::accel_union& accel) override +}; + +[JsonObject(ItemRequired = Required::Always)] +public ref struct LutBase +{ + [JsonConverter(Converters::StringEnumConverter::typeid)] + enum class Mode { - pin_ptr pdata = &data[0,0]; + logarithmic, linear + } mode; - accel.arb_lut.fill(reinterpret_cast*>(pdata), data->Length/2); - } + virtual void SetArgs(AccelArgs%) {} + virtual void SetData(ra::accel_union&) {} }; + [JsonObject(ItemRequired = Required::Always)] public ref struct SpacedLut abstract : public LutBase { @@ -216,11 +253,11 @@ public ref struct SpacedLut abstract : public LutBase double stop; array^ data; - void SetArgsBase(TableArgs% args) + void SetArgsBase(AccelArgs% args) { - args.transfer = transfer; - args.start = start; - args.stop = stop; + args.spacedTableArgs.transfer = transfer; + args.spacedTableArgs.start = start; + args.spacedTableArgs.stop = stop; } void SetDataBase(ra::accel_union& accel) @@ -250,11 +287,11 @@ public ref struct LinearLut sealed : public SpacedLut std::memcpy(pdata, &table.data, sizeof(float) * data->Length); } - virtual void SetArgs(TableArgs% args) override + virtual void SetArgs(AccelArgs% args) override { SetArgsBase(args); - args.num = data->Length; - args.mode = TableMode::linear; + args.spacedTableArgs.num = data->Length; + args.spacedTableArgs.mode = SpacedTableMode::linear; } virtual void SetData(ra::accel_union& accel) override @@ -270,6 +307,10 @@ public ref struct BinLogLut sealed : public SpacedLut { short num; + BinLogLut() + { + } + BinLogLut(const ra::binlog_lut& table) { mode = Mode::logarithmic; @@ -283,11 +324,11 @@ public ref struct BinLogLut sealed : public SpacedLut std::memcpy(pdata, &table.data, sizeof(float) * data->Length); } - virtual void SetArgs(TableArgs% args) override + virtual void SetArgs(AccelArgs% args) override { SetArgsBase(args); - args.num = num; - args.mode = TableMode::binlog; + args.spacedTableArgs.num = num; + args.spacedTableArgs.mode = SpacedTableMode::binlog; } virtual void SetData(ra::accel_union& accel) override @@ -333,8 +374,6 @@ public ref struct RaConvert { return NonNullable(jObject); case LutBase::Mode::linear: return NonNullable(jObject); - case LutBase::Mode::arbitrary: - return NonNullable(jObject); default: throw gcnew NotImplementedException(); } @@ -401,7 +440,7 @@ private: if (xTableJson) { tables.x = RaConvert::Table(xTableJson); - tables.x->SetArgs(baseSettings->args.x.lutArgs); + tables.x->SetArgs(baseSettings->args.x); } if (yTableJson) { @@ -412,7 +451,7 @@ private: tables.y = RaConvert::Table(yTableJson); } - tables.y->SetArgs(baseSettings->args.y.lutArgs); + tables.y->SetArgs(baseSettings->args.y); } } @@ -443,15 +482,16 @@ public: auto fp = static_cast( Marshal::GetFunctionPointerForDelegate(del).ToPointer()); - ra::settings args; - Marshal::StructureToPtr(settings, (IntPtr)&args, false); + ra::settings* args_ptr = new ra::settings(); + Marshal::StructureToPtr(settings, (IntPtr)args_ptr, false); list = gcnew List(); - auto [cx, cy, _] = ra::valid(args, fp); + auto [cx, cy, _] = ra::valid(*args_ptr, fp); countX = cx; countY = cy; gch.Free(); + delete args_ptr; } bool Empty() @@ -535,9 +575,9 @@ public: { auto settings = gcnew ExtendedSettings(); Marshal::PtrToStructure(IntPtr(&instance->data.args), settings->baseSettings); - settings->tables.x = extract(instance->data.args.argsv.x.lut_args.mode, + 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.lut_args.mode, + settings->tables.y = extract(instance->data.args.argsv.y.spaced_args.mode, instance->data.mod.accel.y); return settings; } @@ -573,13 +613,12 @@ public: } private: - LutBase^ extract(ra::table_mode mode, ra::accel_union& au) + LutBase^ extract(ra::spaced_lut_mode mode, ra::accel_union& au) { switch (mode) { - case ra::table_mode::off: return nullptr; - case ra::table_mode::linear: return gcnew LinearLut(au.lin_lut); - case ra::table_mode::binlog: return gcnew BinLogLut(au.log_lut); - case ra::table_mode::arbitrary: return gcnew ArbitraryLut(au.arb_lut); + 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(); } } -- cgit v1.2.3