summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/accel-union.hpp3
-rw-r--r--common/rawaccel-base.hpp3
-rw-r--r--common/rawaccel-validate.hpp3
-rw-r--r--converter/converter.cpp10
-rw-r--r--grapher/Constants/Constants.cs2
-rw-r--r--grapher/Form1.cs1
-rw-r--r--grapher/Layouts/JumpLayout.cs24
-rw-r--r--grapher/Layouts/LUTLayout.cs2
-rw-r--r--grapher/Layouts/LinearLayout.cs2
-rw-r--r--grapher/Models/AccelGUI.cs124
-rw-r--r--grapher/Models/Mouse/MouseWatcher.cs4
-rw-r--r--grapher/Models/Options/AccelTypeOptions.cs23
-rw-r--r--grapher/Models/Serialized/GUISettings.cs27
-rw-r--r--grapher/Models/Serialized/LookupTable.cs50
-rw-r--r--grapher/Models/Serialized/RawAccelSettings.cs141
-rw-r--r--grapher/Models/Serialized/SettingsManager.cs138
-rw-r--r--grapher/grapher.csproj3
-rw-r--r--wrapper/input.cpp74
-rw-r--r--wrapper/interop-exception.h21
-rw-r--r--wrapper/wrapper.cpp414
-rw-r--r--wrapper/wrapper.vcxproj3
-rw-r--r--wrapper/wrapper.vcxproj.filters6
-rw-r--r--writer/Program.cs88
23 files changed, 665 insertions, 501 deletions
diff --git a/common/accel-union.hpp b/common/accel-union.hpp
index 3d41a18..7f3d5d5 100644
--- a/common/accel-union.hpp
+++ b/common/accel-union.hpp
@@ -22,6 +22,7 @@ namespace rawaccel {
motivity_gain,
lut_log,
lut_lin,
+ lut_arb,
noaccel
};
@@ -31,6 +32,7 @@ namespace rawaccel {
switch (lut_mode) {
case table_mode::binlog: return internal_mode::lut_log;
case table_mode::linear: return internal_mode::lut_lin;
+ case table_mode::arbitrary: return internal_mode::lut_arb;
default: return internal_mode::noaccel;
}
}
@@ -64,6 +66,7 @@ namespace rawaccel {
case internal_mode::motivity_gain: return vis(u.motivity_g);
case internal_mode::lut_log: return vis(u.log_lut);
case internal_mode::lut_lin: return vis(u.lin_lut);
+ case internal_mode::lut_arb:
default: return vis(u.noaccel);
}
}
diff --git a/common/rawaccel-base.hpp b/common/rawaccel-base.hpp
index 9900aab..d318db5 100644
--- a/common/rawaccel-base.hpp
+++ b/common/rawaccel-base.hpp
@@ -29,7 +29,8 @@ namespace rawaccel {
enum class table_mode {
off,
binlog,
- linear
+ linear,
+ arbitrary
};
struct table_args {
diff --git a/common/rawaccel-validate.hpp b/common/rawaccel-validate.hpp
index bccb21c..d625d20 100644
--- a/common/rawaccel-validate.hpp
+++ b/common/rawaccel-validate.hpp
@@ -44,7 +44,7 @@ namespace rawaccel {
error("stop must be greater than start");
}
- if (lut_args.num_elements < 2 ||
+ if (lut_args.num_elements < 2 ||
lut_args.num_elements > 1025) {
error("num must be between 2 and 1025");
}
@@ -73,6 +73,7 @@ namespace rawaccel {
}
}
+
if (args.offset < 0) {
error("offset can not be negative");
}
diff --git a/converter/converter.cpp b/converter/converter.cpp
index 7b71af3..b1761b0 100644
--- a/converter/converter.cpp
+++ b/converter/converter.cpp
@@ -10,6 +10,7 @@
#include <string>
using namespace System;
+using namespace System::IO;
using namespace System::Runtime::InteropServices;
using namespace Newtonsoft::Json;
@@ -181,9 +182,9 @@ bool try_convert(const ia_settings_t& ia_settings) {
}
default: return false;
}
-
+
DriverSettings^ new_settings = Marshal::PtrToStructure<DriverSettings^>((IntPtr)&ra_settings);
- auto errors = gcnew SettingsErrors(new_settings);
+ SettingsErrors^ errors = gcnew SettingsErrors(new_settings);
if (!errors->Empty()) {
Console::WriteLine("Bad settings: {0}", errors);
@@ -191,12 +192,11 @@ bool try_convert(const ia_settings_t& ia_settings) {
}
Console::Write("Sending to driver... ");
- (gcnew ManagedAccel(new_settings))->Activate();
+ (gcnew ManagedAccel(gcnew ExtendedSettings(new_settings)))->Activate();
Console::WriteLine("done");
Console::Write("Generating settings.json... ");
- auto json = JsonConvert::SerializeObject(new_settings, Formatting::Indented);
- System::IO::File::WriteAllText("settings.json", json);
+ File::WriteAllText("settings.json", RaConvert::Settings(new_settings));
Console::WriteLine("done");
return true;
diff --git a/grapher/Constants/Constants.cs b/grapher/Constants/Constants.cs
index 446f5fa..d2e747c 100644
--- a/grapher/Constants/Constants.cs
+++ b/grapher/Constants/Constants.cs
@@ -120,6 +120,8 @@ namespace grapher
/// <summary> Default name of settings file. </summary>
public const string DefaultSettingsFileName = @"settings.json";
+ public const string GuiConfigFileName = ".config";
+
/// <summary> Text to direcitonality panel title when panel is closed. </summary>
public const string DirectionalityTitleClosed = "Anisotropy \u25BC";
diff --git a/grapher/Form1.cs b/grapher/Form1.cs
index 5b13c8f..a4ece9e 100644
--- a/grapher/Form1.cs
+++ b/grapher/Form1.cs
@@ -28,7 +28,6 @@ namespace grapher
{
InitializeComponent();
- Version assemVersion = typeof(RawAcceleration).Assembly.GetName().Version;
Version driverVersion = null;
try
diff --git a/grapher/Layouts/JumpLayout.cs b/grapher/Layouts/JumpLayout.cs
new file mode 100644
index 0000000..cb77963
--- /dev/null
+++ b/grapher/Layouts/JumpLayout.cs
@@ -0,0 +1,24 @@
+using grapher.Models.Serialized;
+
+namespace grapher.Layouts
+{
+ public class JumpLayout : LayoutBase
+ {
+ public JumpLayout()
+ : base()
+ {
+ Name = "Jump";
+ Index = (int)AccelMode.jump;
+ LogarithmicCharts = false;
+
+ AccelLayout = new OptionLayout(false, Acceleration);
+ ScaleLayout = new OptionLayout(false, string.Empty);
+ CapLayout = new OptionLayout(true, string.Empty);
+ WeightLayout = new OptionLayout(false, Weight);
+ OffsetLayout = new OptionLayout(true, Offset);
+ LimitLayout = new OptionLayout(false, Limit);
+ ExponentLayout = new OptionLayout(false, string.Empty);
+ MidpointLayout = new OptionLayout(false, string.Empty);
+ }
+ }
+}
diff --git a/grapher/Layouts/LUTLayout.cs b/grapher/Layouts/LUTLayout.cs
index 7449168..4b4b687 100644
--- a/grapher/Layouts/LUTLayout.cs
+++ b/grapher/Layouts/LUTLayout.cs
@@ -14,7 +14,7 @@ namespace grapher.Layouts
: base()
{
Name = "LookUpTable";
- Index = (int)AccelMode.lut;
+ Index = (int)AccelMode.noaccel + 1;
AccelLayout = new OptionLayout(false, Acceleration);
ScaleLayout = new OptionLayout(false, string.Empty);
diff --git a/grapher/Layouts/LinearLayout.cs b/grapher/Layouts/LinearLayout.cs
index 4681ca9..d98baa5 100644
--- a/grapher/Layouts/LinearLayout.cs
+++ b/grapher/Layouts/LinearLayout.cs
@@ -16,7 +16,7 @@ namespace grapher.Layouts
AccelLayout = new OptionLayout(true, Acceleration);
ScaleLayout = new OptionLayout(false, string.Empty);
CapLayout = new OptionLayout(true, Cap);
- WeightLayout = new OptionLayout(true, Weight);
+ WeightLayout = new OptionLayout(false, Weight);
OffsetLayout = new OptionLayout(true, Offset);
LimitLayout = new OptionLayout(false, string.Empty);
ExponentLayout = new OptionLayout(false, string.Empty);
diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs
index 5a04030..9ed2cb9 100644
--- a/grapher/Models/AccelGUI.cs
+++ b/grapher/Models/AccelGUI.cs
@@ -32,7 +32,7 @@ namespace grapher
AccelCharts = accelCharts;
ApplyOptions = applyOptions;
WriteButton = writeButton;
- ToggleButton = (CheckBox)toggleButton;
+ DisableButton = (CheckBox)toggleButton;
ScaleMenuItem = scaleMenuItem;
Settings = settings;
DefaultButtonFont = WriteButton.Font;
@@ -42,7 +42,7 @@ namespace grapher
ScaleMenuItem.Click += new System.EventHandler(OnScaleMenuItemClick);
WriteButton.Click += new System.EventHandler(OnWriteButtonClick);
- ToggleButton.Click += new System.EventHandler(OnToggleButtonClick);
+ DisableButton.Click += new System.EventHandler(DisableDriverEventHandler);
AccelForm.FormClosing += new FormClosingEventHandler(SaveGUISettingsOnClose);
ButtonTimerInterval = Convert.ToInt32(DriverSettings.WriteDelayMs);
@@ -51,25 +51,8 @@ namespace grapher
ChartRefresh = SetupChartTimer();
- bool settingsActive = Settings.Startup();
- SettingsNotDefault = !Settings.RawAccelSettings.IsDefaultEquivalent();
-
- if (settingsActive)
- {
- LastToggleChecked = SettingsNotDefault;
- ToggleButton.Enabled = LastToggleChecked;
- RefreshOnRead(Settings.RawAccelSettings.AccelerationSettings);
- }
- else
- {
- DriverSettings active = ManagedAccel.GetActive().Settings;
- bool activeNotDefault = !RawAccelSettings.IsDefaultEquivalent(active);
-
- LastToggleChecked = activeNotDefault;
- ToggleButton.Enabled = SettingsNotDefault || activeNotDefault;
- RefreshOnRead(active);
- }
-
+ RefreshUser();
+ RefreshActive();
SetupButtons();
// TODO: The below removes an overlapping form from the anisotropy panel.
@@ -94,7 +77,7 @@ namespace grapher
public Button WriteButton { get; }
- public CheckBox ToggleButton { get; }
+ public CheckBox DisableButton { get; }
public Timer ButtonTimer { get; }
@@ -104,8 +87,6 @@ namespace grapher
public DeviceIDManager DeviceIDManager { get; }
- public Action UpdateInputManagers { get; private set; }
-
private Timer ChartRefresh { get; }
private Font SmallButtonFont { get; }
@@ -125,46 +106,37 @@ namespace grapher
private void SaveGUISettingsOnClose(Object sender, FormClosingEventArgs e)
{
var guiSettings = Settings.MakeGUISettingsFromFields();
- if (!Settings.RawAccelSettings.GUISettings.Equals(guiSettings))
+ if (!Settings.GuiSettings.Equals(guiSettings))
{
- Settings.RawAccelSettings.GUISettings = guiSettings;
- Settings.RawAccelSettings.Save();
+ guiSettings.Save();
}
}
public void UpdateActiveSettingsFromFields()
{
- var driverSettings = Settings.RawAccelSettings.AccelerationSettings;
-
- var newArgs = ApplyOptions.GetArgs();
-
var settings = new DriverSettings
{
rotation = ApplyOptions.Rotation.Field.Data,
- snap = driverSettings.snap,
sensitivity = new Vec2<double>
{
x = ApplyOptions.Sensitivity.Fields.X,
y = ApplyOptions.Sensitivity.Fields.Y
},
combineMagnitudes = ApplyOptions.IsWhole,
- args = newArgs,
- minimumTime = driverSettings.minimumTime,
- directionalMultipliers = driverSettings.directionalMultipliers,
+ args = ApplyOptions.GetArgs(),
domainArgs = ApplyOptions.Directionality.GetDomainArgs(),
rangeXY = ApplyOptions.Directionality.GetRangeXY(),
deviceID = DeviceIDManager.ID,
- maximumSpeed = driverSettings.maximumSpeed,
- minimumSpeed = driverSettings.minimumSpeed
};
+ Settings.SetHiddenOptions(settings);
+
ButtonDelay(WriteButton);
- SettingsErrors errors = Settings.TryUpdateActiveSettings(settings);
+
+ SettingsErrors errors = Settings.TryActivate(settings);
if (errors.Empty())
{
- SettingsNotDefault = !Settings.RawAccelSettings.IsDefaultEquivalent();
- LastToggleChecked = SettingsNotDefault;
- RefreshOnRead(Settings.RawAccelSettings.AccelerationSettings);
+ RefreshActive();
}
else
{
@@ -172,25 +144,28 @@ namespace grapher
}
}
- public void RefreshOnRead(DriverSettings args)
+ public void UpdateInputManagers()
{
- UpdateShownActiveValues(args);
- UpdateGraph(args);
-
- UpdateInputManagers = () =>
- {
- MouseWatcher.UpdateHandles(args.deviceID);
- DeviceIDManager.Update(args.deviceID);
- };
+ MouseWatcher.UpdateHandles(Settings.ActiveSettings.baseSettings.deviceID);
+ DeviceIDManager.Update(Settings.ActiveSettings.baseSettings.deviceID);
+ }
+ public void RefreshActive()
+ {
+ UpdateGraph();
UpdateInputManagers();
}
- public void UpdateGraph(DriverSettings args)
+ public void RefreshUser()
+ {
+ UpdateShownActiveValues(Settings.UserSettings);
+ }
+
+ public void UpdateGraph()
{
AccelCharts.Calculate(
Settings.ActiveAccel,
- args);
+ Settings.ActiveSettings.baseSettings);
AccelCharts.Bind();
}
@@ -214,32 +189,31 @@ namespace grapher
{
WriteButton.Top = Constants.SensitivityChartAloneHeight - Constants.ButtonVerticalOffset;
- ToggleButton.Appearance = Appearance.Button;
- ToggleButton.FlatStyle = FlatStyle.System;
- ToggleButton.TextAlign = ContentAlignment.MiddleCenter;
- ToggleButton.Size = WriteButton.Size;
- ToggleButton.Top = WriteButton.Top;
+ DisableButton.Appearance = Appearance.Button;
+ DisableButton.FlatStyle = FlatStyle.System;
+ DisableButton.TextAlign = ContentAlignment.MiddleCenter;
+ DisableButton.Size = WriteButton.Size;
+ DisableButton.Top = WriteButton.Top;
SetButtonDefaults();
}
private void SetButtonDefaults()
{
- ToggleButton.Checked = LastToggleChecked;
-
- ToggleButton.Font = DefaultButtonFont;
- ToggleButton.Text = ToggleButton.Checked ? "Disable" : "Enable";
- ToggleButton.Update();
+ DisableButton.Font = DefaultButtonFont;
+ DisableButton.Text = "Disable";
+ DisableButton.Enabled = true;
+ DisableButton.Update();
WriteButton.Font = DefaultButtonFont;
WriteButton.Text = Constants.WriteButtonDefaultText;
- WriteButton.Enabled = ToggleButton.Checked || !ToggleButton.Enabled;
+ WriteButton.Enabled = true;
WriteButton.Update();
}
private void OnScaleMenuItemClick(object sender, EventArgs e)
{
- UpdateGraph(Settings.RawAccelSettings.AccelerationSettings);
+ UpdateGraph();
}
private void OnWriteButtonClick(object sender, EventArgs e)
@@ -247,24 +221,16 @@ namespace grapher
UpdateActiveSettingsFromFields();
}
- private void OnToggleButtonClick(object sender, EventArgs e)
+ private void DisableDriverEventHandler(object sender, EventArgs e)
{
- var accel = ToggleButton.Checked ?
- new ManagedAccel(Settings.RawAccelSettings.AccelerationSettings) :
- AccelTypeOptions.DefaultSettings;
-
- LastToggleChecked = ToggleButton.Checked;
- ButtonDelay(ToggleButton);
-
- SettingsManager.SendToDriver(accel);
- Settings.ActiveAccel = accel;
- RefreshOnRead(accel.Settings);
+ ButtonDelay(DisableButton);
+ Settings.DisableDriver();
+ RefreshActive();
}
private void OnButtonTimerTick(object sender, EventArgs e)
{
ButtonTimer.Stop();
- ToggleButton.Enabled = SettingsNotDefault;
SetButtonDefaults();
}
@@ -276,15 +242,13 @@ namespace grapher
private void ButtonDelay(ButtonBase btn)
{
- ToggleButton.Checked = false;
-
- ToggleButton.Enabled = false;
+ DisableButton.Enabled = false;
WriteButton.Enabled = false;
btn.Font = SmallButtonFont;
btn.Text = $"{Constants.ButtonDelayText} : {ButtonTimerInterval} ms";
- ToggleButton.Update();
+ DisableButton.Update();
WriteButton.Update();
StartButtonTimer();
diff --git a/grapher/Models/Mouse/MouseWatcher.cs b/grapher/Models/Mouse/MouseWatcher.cs
index 163829f..c5c2ae5 100644
--- a/grapher/Models/Mouse/MouseWatcher.cs
+++ b/grapher/Models/Mouse/MouseWatcher.cs
@@ -772,8 +772,8 @@ namespace grapher.Models.Mouse
// strip negative directional multipliers, charts calculated from positive input
- Vec2<double> dirMults = SettingsManager.RawAccelSettings
- .AccelerationSettings.directionalMultipliers;
+ Vec2<double> dirMults = SettingsManager.ActiveSettings.baseSettings
+ .directionalMultipliers;
if (dirMults.x > 0 && x < 0)
{
diff --git a/grapher/Models/Options/AccelTypeOptions.cs b/grapher/Models/Options/AccelTypeOptions.cs
index 7e2e3d7..556f969 100644
--- a/grapher/Models/Options/AccelTypeOptions.cs
+++ b/grapher/Models/Options/AccelTypeOptions.cs
@@ -17,13 +17,14 @@ namespace grapher
new LinearLayout(),
new ClassicLayout(),
new NaturalLayout(),
+ new JumpLayout(),
new PowerLayout(),
new MotivityLayout(),
new OffLayout(),
new LUTLayout(),
}.ToDictionary(k => k.Name);
- public static readonly ManagedAccel DefaultSettings = new ManagedAccel();
+ public static readonly AccelArgs DefaultArgs = new DriverSettings().args.x;
#endregion Fields
@@ -233,22 +234,18 @@ namespace grapher
public void SetArgs(ref AccelArgs args)
{
- AccelArgs defaults = DefaultSettings.Settings.args.x;
- args.accelClassic = defaults.accelClassic;
- args.accelMotivity = defaults.accelMotivity;
- args.accelNatural = defaults.accelClassic;
- args.scale = Scale.Visible ? Scale.Field.Data : defaults.scale;
- args.cap = Cap.Visible ? Cap.SensitivityCap : defaults.cap;
- args.limit = Limit.Visible ? Limit.Field.Data : defaults.limit;
- args.exponent = Exponent.Visible ? Exponent.Field.Data : defaults.exponent;
- args.offset = Offset.Visible ? Offset.Offset : defaults.offset;
- args.midpoint = Midpoint.Visible ? Midpoint.Field.Data : defaults.midpoint;
- args.weight = Weight.Visible ? Weight.Field.Data : defaults.weight;
+ if (Scale.Visible) args.scale = Scale.Field.Data;
+ if (Cap.Visible) args.cap = Cap.SensitivityCap;
+ if (Limit.Visible) args.limit = Limit.Field.Data;
+ if (Exponent.Visible) args.exponent = Exponent.Field.Data;
+ if (Offset.Visible) args.offset = Offset.Offset;
+ if (Midpoint.Visible) args.midpoint = Midpoint.Field.Data;
+ if (Weight.Visible) args.weight = Weight.Field.Data;
}
public AccelArgs GenerateArgs()
{
- AccelArgs args = new AccelArgs();
+ AccelArgs args = new DriverSettings().args.x;
SetArgs(ref args);
return args;
}
diff --git a/grapher/Models/Serialized/GUISettings.cs b/grapher/Models/Serialized/GUISettings.cs
index bb35055..93d56de 100644
--- a/grapher/Models/Serialized/GUISettings.cs
+++ b/grapher/Models/Serialized/GUISettings.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using System;
+using System.IO;
namespace grapher.Models.Serialized
{
@@ -65,6 +66,32 @@ namespace grapher.Models.Serialized
AutoWriteToDriverOnStartup.GetHashCode();
}
+ public void Save()
+ {
+ File.WriteAllText(Constants.GuiConfigFileName, JsonConvert.SerializeObject(this));
+ }
+
+ public static GUISettings MaybeLoad()
+ {
+ GUISettings settings = null;
+
+ try
+ {
+ settings = JsonConvert.DeserializeObject<GUISettings>(
+ File.ReadAllText(Constants.GuiConfigFileName));
+ }
+ catch (Exception ex)
+ {
+ if (!(ex is JsonException || ex is FileNotFoundException))
+ {
+ throw;
+ }
+ }
+
+ return settings;
+ }
+
#endregion Methods
+
}
}
diff --git a/grapher/Models/Serialized/LookupTable.cs b/grapher/Models/Serialized/LookupTable.cs
deleted file mode 100644
index d373461..0000000
--- a/grapher/Models/Serialized/LookupTable.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace grapher.Models.Serialized
-{
- [Serializable]
- public static class LookupTable
- {
- public static void Deserialize(string lutFile, ref DriverSettings settings)
- {
- if (!File.Exists(lutFile))
- {
- throw new Exception($"LUT file does not exist at {lutFile}.");
- }
-
- JObject lutJObject = JObject.Parse(File.ReadAllText(lutFile));
-
- var spacedLut = lutJObject.ToObject<SpacedTable>(JsonSerializer.Create(RawAccelSettings.SerializerSettings));
-
- if (spacedLut is null)
- {
- var arbitraryLut = lutJObject.ToObject<ArbitraryTable>(JsonSerializer.Create(RawAccelSettings.SerializerSettings));
-
- if (arbitraryLut is null || arbitraryLut.points is null)
- {
- throw new Exception($"{lutFile} does not contain valid lookuptable json.");
- }
-
- settings.ArbitraryTable = arbitraryLut;
- settings.args.x.lutArgs.type = TableType.arbitrary;
- }
- else
- {
- if (spacedLut.points is null)
- {
- throw new Exception($"{lutFile} does not contain valid lookuptable json.");
- }
-
- settings.SpacedTable = spacedLut;
- settings.args.x.lutArgs = spacedLut.args;
- }
- }
- }
-}
diff --git a/grapher/Models/Serialized/RawAccelSettings.cs b/grapher/Models/Serialized/RawAccelSettings.cs
deleted file mode 100644
index dc4eb0a..0000000
--- a/grapher/Models/Serialized/RawAccelSettings.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.IO;
-using System.Linq;
-
-namespace grapher.Models.Serialized
-{
- [Serializable]
- public class RawAccelSettings
- {
- #region Fields
-
- public static readonly string ExecutingDirectory = AppDomain.CurrentDomain.BaseDirectory;
- public static readonly string DefaultSettingsFile = Path.Combine(ExecutingDirectory, Constants.DefaultSettingsFileName);
- public static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
- {
- MissingMemberHandling = MissingMemberHandling.Ignore,
- };
- #endregion Fields
-
- #region Constructors
-
- public RawAccelSettings() { }
-
- public RawAccelSettings(
- DriverSettings accelSettings,
- GUISettings guiSettings)
- {
- AccelerationSettings = accelSettings;
- GUISettings = guiSettings;
- }
-
- #endregion Constructors
-
- #region Properties
- [JsonProperty(Required = Required.Always)]
- public GUISettings GUISettings { get; set; }
-
- [JsonProperty(DriverSettings.Key, Required = Required.Always)]
- public DriverSettings AccelerationSettings { get; set; }
-
- #endregion Properties
-
- #region Methods
-
- public static RawAccelSettings Load(Func<GUISettings> DefaultGUISettingsSupplier)
- {
- return Load(DefaultSettingsFile, DefaultGUISettingsSupplier);
- }
-
- public static RawAccelSettings Load(string file, Func<GUISettings> DefaultGUISettingsSupplier)
- {
- try
- {
- RawAccelSettings settings = null;
-
- JObject settingsJObject = JObject.Parse(File.ReadAllText(file));
- if (settingsJObject.ContainsKey(DriverSettings.Key))
- {
- settings = settingsJObject.ToObject<RawAccelSettings>(JsonSerializer.Create(SerializerSettings));
- }
- else
- {
- settings = new RawAccelSettings
- {
- AccelerationSettings = settingsJObject.ToObject<DriverSettings>(),
- GUISettings = DefaultGUISettingsSupplier()
- };
- }
-
- if (settings is null || settings.AccelerationSettings is null)
- {
- throw new JsonException($"{file} contains invalid JSON");
- }
-
- return settings;
- }
- catch (FileNotFoundException e)
- {
- throw new FileNotFoundException($"Settings file does not exist at {file}", e);
- }
- catch (JsonException e)
- {
- throw new JsonException($"Settings file at {file} does not contain valid Raw Accel Settings.", e);
- }
- }
-
- public static bool Exists()
- {
- return Exists(DefaultSettingsFile);
- }
-
- public static bool Exists(string file)
- {
- return File.Exists(file);
- }
-
- public void Save()
- {
- Save(DefaultSettingsFile);
- }
-
- public void Save(string file)
- {
- JObject thisJO = JObject.FromObject(this);
- AddComments(thisJO);
- File.WriteAllText(file, thisJO.ToString(Formatting.Indented));
- }
-
- private void AddComments(JObject thisJO)
- {
- string modes = string.Join(" | ", Enum.GetNames(typeof(AccelMode)));
- ((JObject)thisJO[DriverSettings.Key])
- .AddFirst(new JProperty("### Mode Types ###", modes));
- }
-
- public bool IsDefaultEquivalent()
- {
- return IsDefaultEquivalent(AccelerationSettings);
- }
-
- public static bool IsDefaultEquivalent(DriverSettings accelSettings)
- {
- bool wholeOrNoY = accelSettings.combineMagnitudes ||
- accelSettings.args.y.mode == AccelMode.noaccel;
-
- return string.IsNullOrEmpty(accelSettings.deviceID) &&
- accelSettings.sensitivity.x == 1 &&
- accelSettings.sensitivity.y == 1 &&
- accelSettings.directionalMultipliers.x <= 0 &&
- accelSettings.directionalMultipliers.y <= 0 &&
- accelSettings.rotation == 0 &&
- accelSettings.snap == 0 &&
- accelSettings.args.x.mode == AccelMode.noaccel &&
- wholeOrNoY;
- }
-
- #endregion Methods
- }
-}
diff --git a/grapher/Models/Serialized/SettingsManager.cs b/grapher/Models/Serialized/SettingsManager.cs
index 25aa534..c0cc413 100644
--- a/grapher/Models/Serialized/SettingsManager.cs
+++ b/grapher/Models/Serialized/SettingsManager.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using System;
+using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Text;
@@ -21,22 +22,41 @@ namespace grapher.Models.Serialized
ToolStripMenuItem showVelocityAndGain,
DeviceIDManager deviceIDManager)
{
- ActiveAccel = activeAccel;
DpiField = dpiField;
PollRateField = pollRateField;
AutoWriteMenuItem = autoWrite;
ShowLastMouseMoveMenuItem = showLastMouseMove;
ShowVelocityAndGainMoveMenuItem = showVelocityAndGain;
DeviceIDManager = deviceIDManager;
+
+ SetActiveFields(activeAccel);
+
+ GuiSettings = GUISettings.MaybeLoad();
+
+ if (GuiSettings is null)
+ {
+ GuiSettings = MakeGUISettingsFromFields();
+ GuiSettings.Save();
+ }
+ else
+ {
+ UpdateFieldsFromGUISettings();
+ }
+
+ UserSettings = InitUserSettings();
}
#endregion Constructors
#region Properties
- public ManagedAccel ActiveAccel { get; set; }
+ public GUISettings GuiSettings { get; private set; }
+
+ public ManagedAccel ActiveAccel { get; private set; }
+
+ public ExtendedSettings ActiveSettings { get; private set; }
- public RawAccelSettings RawAccelSettings { get; private set; }
+ public DriverSettings UserSettings { get; private set; }
public Field DpiField { get; private set; }
@@ -53,47 +73,54 @@ namespace grapher.Models.Serialized
#endregion Properties
#region Methods
- public SettingsErrors TryUpdateActiveSettings(DriverSettings settings)
- {
- var errors = TryUpdateAccel(settings);
-
- if (errors.Empty())
- {
- RawAccelSettings.AccelerationSettings = settings;
- RawAccelSettings.GUISettings = MakeGUISettingsFromFields();
- RawAccelSettings.Save();
- }
- return errors;
+ public void DisableDriver()
+ {
+ var defaultSettings = new ExtendedSettings();
+ ActiveSettings = defaultSettings;
+ ActiveAccel.Settings = defaultSettings;
+ new Thread(() => ActiveAccel.Activate()).Start();
}
public void UpdateFieldsFromGUISettings()
{
- DpiField.SetToEntered(RawAccelSettings.GUISettings.DPI);
- PollRateField.SetToEntered(RawAccelSettings.GUISettings.PollRate);
- ShowLastMouseMoveMenuItem.Checked = RawAccelSettings.GUISettings.ShowLastMouseMove;
- ShowVelocityAndGainMoveMenuItem.Checked = RawAccelSettings.GUISettings.ShowVelocityAndGain;
- AutoWriteMenuItem.Checked = RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup;
+ DpiField.SetToEntered(GuiSettings.DPI);
+ PollRateField.SetToEntered(GuiSettings.PollRate);
+ ShowLastMouseMoveMenuItem.Checked = GuiSettings.ShowLastMouseMove;
+ ShowVelocityAndGainMoveMenuItem.Checked = GuiSettings.ShowVelocityAndGain;
+ AutoWriteMenuItem.Checked = GuiSettings.AutoWriteToDriverOnStartup;
}
- public SettingsErrors TryUpdateAccel(DriverSettings settings)
+ public SettingsErrors TryActivate(DriverSettings settings)
{
- var accel = new ManagedAccel(settings);
- var errors = SendToDriverSafe(accel);
- if (errors.Empty()) ActiveAccel= accel;
- return errors;
- }
+ var errors = new SettingsErrors(settings);
- public static void SendToDriver(ManagedAccel accel)
- {
- new Thread(() => accel.Activate()).Start();
+ if (errors.Empty())
+ {
+ GuiSettings = MakeGUISettingsFromFields();
+ GuiSettings.Save();
+
+ UserSettings = settings;
+ File.WriteAllText(Constants.DefaultSettingsFileName, RaConvert.Settings(settings));
+
+ ActiveSettings = new ExtendedSettings(settings);
+ ActiveAccel.Settings = ActiveSettings;
+
+ new Thread(() => ActiveAccel.Activate()).Start();
+ }
+
+ return errors;
}
- public static SettingsErrors SendToDriverSafe(ManagedAccel accel)
+ public void SetHiddenOptions(DriverSettings settings)
{
- var errors = new SettingsErrors(accel.Settings);
- if (errors.Empty()) SendToDriver(accel);
- return errors;
+ 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;
}
public GUISettings MakeGUISettingsFromFields()
@@ -108,32 +135,51 @@ namespace grapher.Models.Serialized
};
}
- // Returns true when file settings are active
- public bool Startup()
+ public bool TableActive()
+ {
+ return ActiveSettings.tables.x != null || ActiveSettings.tables.y != null;
+ }
+
+ public void SetActiveFields(ManagedAccel activeAccel)
{
- if (RawAccelSettings.Exists())
+ ActiveAccel = activeAccel;
+ ActiveSettings = activeAccel.Settings;
+ }
+
+ private DriverSettings InitUserSettings()
+ {
+ var path = Constants.DefaultSettingsFileName;
+ if (File.Exists(path))
{
try
{
- RawAccelSettings = RawAccelSettings.Load(() => MakeGUISettingsFromFields());
- UpdateFieldsFromGUISettings();
- if (RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup)
+ DriverSettings settings = RaConvert.Settings(File.ReadAllText(path));
+
+ if (!GuiSettings.AutoWriteToDriverOnStartup ||
+ TableActive() ||
+ TryActivate(settings).Empty())
{
- TryUpdateAccel(RawAccelSettings.AccelerationSettings);
+ return settings;
}
- return RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup;
+
}
catch (JsonException e)
{
- Console.WriteLine($"bad settings: {e}");
+ System.Diagnostics.Debug.WriteLine($"bad settings: {e}");
}
}
- RawAccelSettings = new RawAccelSettings(
- ManagedAccel.GetActive().Settings,
- MakeGUISettingsFromFields());
- RawAccelSettings.Save();
- return true;
+ 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;
+ }
}
#endregion Methods
diff --git a/grapher/grapher.csproj b/grapher/grapher.csproj
index e884c0d..c896510 100644
--- a/grapher/grapher.csproj
+++ b/grapher/grapher.csproj
@@ -80,6 +80,7 @@
<Compile Include="Constants\Constants.cs" />
<Compile Include="Layouts\LUTLayout.cs" />
<Compile Include="Layouts\MotivityLayout.cs" />
+ <Compile Include="Layouts\JumpLayout.cs" />
<Compile Include="MessageDialog.cs">
<SubType>Form</SubType>
</Compile>
@@ -137,8 +138,6 @@
<Compile Include="Models\Options\OptionXY.cs" />
<Compile Include="Models\Options\TextOption.cs" />
<Compile Include="Models\Serialized\GUISettings.cs" />
- <Compile Include="Models\Serialized\LookupTable.cs" />
- <Compile Include="Models\Serialized\RawAccelSettings.cs" />
<Compile Include="Models\Serialized\SettingsManager.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/wrapper/input.cpp b/wrapper/input.cpp
new file mode 100644
index 0000000..d50f774
--- /dev/null
+++ b/wrapper/input.cpp
@@ -0,0 +1,74 @@
+#include "interop-exception.h"
+
+#include <utility-rawinput.hpp>
+#include <algorithm>
+#include <msclr\marshal_cppstd.h>
+
+using namespace System;
+using namespace System::Collections::Generic;
+
+struct device_info {
+ std::wstring name;
+ std::wstring id;
+};
+
+std::vector<device_info> get_unique_device_info() {
+ std::vector<device_info> 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<IntPtr>^ rawInputHandles)
+ {
+ try
+ {
+ std::vector<HANDLE> nativeHandles = rawinput_handles_from_dev_id(
+ msclr::interop::marshal_as<std::wstring>(deviceID));
+
+ for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh));
+ }
+ catch (const std::exception& e)
+ {
+ throw gcnew RawInputInteropException(e);
+ }
+ }
+
+ static List<ValueTuple<String^, String^>>^ GetDeviceIDs()
+ {
+ try
+ {
+ auto managed = gcnew List<ValueTuple<String^, String^>>();
+
+ for (auto&& [name, id] : get_unique_device_info())
+ {
+ managed->Add(
+ ValueTuple<String^, String^>(
+ msclr::interop::marshal_as<String^>(name),
+ msclr::interop::marshal_as<String^>(id)));
+ }
+
+ return managed;
+ }
+ catch (const std::exception& e)
+ {
+ throw gcnew RawInputInteropException(e);
+ }
+ }
+
+};
+
diff --git a/wrapper/interop-exception.h b/wrapper/interop-exception.h
new file mode 100644
index 0000000..8ebae5c
--- /dev/null
+++ b/wrapper/interop-exception.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <exception>
+
+public ref struct InteropException : System::Exception {
+ InteropException(System::String^ what) :
+ Exception(what) {}
+ InteropException(const char* what) :
+ Exception(gcnew System::String(what)) {}
+ InteropException(const std::exception& e) :
+ InteropException(e.what()) {}
+};
+
+public ref struct RawInputInteropException : InteropException {
+ RawInputInteropException(System::String^ what) :
+ InteropException(what) {}
+ RawInputInteropException(const char* what) :
+ InteropException(what) {}
+ RawInputInteropException(const std::exception& e) :
+ InteropException(e) {}
+};
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 <rawaccel-io.hpp>
#include <rawaccel-validate.hpp>
-#include <utility-rawinput.hpp>
-
-#include <algorithm>
-#include <type_traits>
-#include <msclr\marshal_cppstd.h>
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<double>^ 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<Vec2<double>>^ 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<float, 2>^ 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<float>^ 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<DriverSettings^>(
- 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<float>(table.range.num);
+
+ pin_ptr<float> 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<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
+{
+ 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<float>(1 + num * (int(stop) - int(start)));
+
+ pin_ptr<float> 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<float> 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<DriverSettings^>(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<LutBase^>(jObject);
+
+ switch (base->mode) {
+ case LutBase::Mode::logarithmic:
+ return NonNullable<BinLogLut^>(jObject);
+ case LutBase::Mode::linear:
+ return NonNullable<LinearLut^>(jObject);
+ case LutBase::Mode::arbitrary:
+ return NonNullable<ArbitraryLut^>(jObject);
+ default:
+ throw gcnew NotImplementedException();
+ }
+ }
+
+ 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;
+ }
+
+ generic <typename T>
+ static T NonNullable(JObject^ jObject)
+ {
+ T obj = jObject->ToObject<T>();
+ if (obj == nullptr) throw gcnew JsonException("invalid JSON");
+ return obj;
+ }
+};
+
+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)
+ {
+ 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<String^>^ list;
int countX;
int countY;
@@ -242,9 +411,12 @@ public:
void Add(const char* msg)
{
- list->Add(msclr::interop::marshal_as<String^>(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<device_info> get_unique_device_info() {
- std::vector<device_info> 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<IntPtr>^ rawInputHandles)
- {
- try
- {
- std::vector<HANDLE> nativeHandles = rawinput_handles_from_dev_id(
- msclr::interop::marshal_as<std::wstring>(deviceID));
-
- for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh));
- }
- catch (const std::exception& e)
- {
- throw gcnew InteropException(e);
- }
- }
-
- static List<ValueTuple<String^, String^>>^ GetDeviceIDs()
- {
- try
- {
- auto managed = gcnew List<ValueTuple<String^, String^>>();
-
- for (auto&& [name, id] : get_unique_device_info())
- {
- managed->Add(
- ValueTuple<String^, String^>(
- msclr::interop::marshal_as<String^>(name),
- msclr::interop::marshal_as<String^>(id)));
- }
-
- return managed;
- }
- catch (const std::exception& e)
- {
- throw gcnew InteropException(e);
- }
- }
-
-};
-
struct instance_t {
ra::io_t data;
vec2<ra::accel_invoker> 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);
}
}
-
};
diff --git a/wrapper/wrapper.vcxproj b/wrapper/wrapper.vcxproj
index fba03a7..8de0cfb 100644
--- a/wrapper/wrapper.vcxproj
+++ b/wrapper/wrapper.vcxproj
@@ -83,17 +83,18 @@ copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)signed\Newtonsoft.Json.
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="interop-exception.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
+ <ClCompile Include="input.cpp" />
<ClCompile Include="wrapper.cpp" />
</ItemGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="wrapper.rc" />
diff --git a/wrapper/wrapper.vcxproj.filters b/wrapper/wrapper.vcxproj.filters
index 96b8e1a..9caeae1 100644
--- a/wrapper/wrapper.vcxproj.filters
+++ b/wrapper/wrapper.vcxproj.filters
@@ -18,6 +18,9 @@
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="interop-exception.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="wrapper.cpp">
@@ -26,6 +29,9 @@
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="input.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="wrapper.rc">
diff --git a/writer/Program.cs b/writer/Program.cs
index d381c16..6cbcf8e 100644
--- a/writer/Program.cs
+++ b/writer/Program.cs
@@ -1,8 +1,9 @@
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Windows.Forms;
namespace writer
@@ -11,9 +12,71 @@ namespace writer
class Program
{
- static void Show(string msg)
+ static void ExitWithMessage(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)
@@ -24,19 +87,12 @@ namespace writer
}
catch (InteropException e)
{
- Show(e.Message);
- return;
- }
-
- if (args.Length != 1)
- {
- Show($"Usage: {System.AppDomain.CurrentDomain.FriendlyName} <settings file path>");
- return;
+ ExitWithMessage(e.Message);
}
try
{
- var settings = DriverSettings.FromFile(args[0]);
+ var settings = Parse(new List<string>(args));
var errors = new SettingsErrors(settings);
if (errors.Empty())
@@ -45,16 +101,20 @@ namespace writer
}
else
{
- Show($"Bad settings:\n\n{errors}");
+ ExitWithMessage($"Bad settings:\n\n{errors}");
}
}
+ catch (System.IO.FileNotFoundException e)
+ {
+ ExitWithMessage(e.Message);
+ }
catch (JsonException e)
{
- Show($"Settings invalid:\n\n{e.Message}");
+ ExitWithMessage($"Settings invalid:\n\n{e.Message}");
}
catch (Exception e)
{
- Show($"Error:\n\n{e}");
+ ExitWithMessage($"Error:\n\n{e}");
}
}
}