From 57be3fadb777f185454361270c1a8076417ed6a5 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 20 Oct 2020 00:40:22 -0400 Subject: [PATCH 1/6] add speed cap --- common/rawaccel-settings.h | 1 + common/rawaccel.hpp | 28 ++++++++++++++++++++++------ grapher/Models/AccelGUI.cs | 3 ++- wrapper/wrapper.cpp | 3 +++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/common/rawaccel-settings.h b/common/rawaccel-settings.h index aeb89e89..02f0a8a2 100644 --- a/common/rawaccel-settings.h +++ b/common/rawaccel-settings.h @@ -18,6 +18,7 @@ namespace rawaccel { bool combine_mags = true; vec2 modes = { accel_mode::noaccel, accel_mode::noaccel }; vec2 argsv; + double speed_cap = 0; vec2d sens = { 1, 1 }; milliseconds time_min = DEFAULT_TIME_MIN; }; diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index ecd38501..3a49aa67 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -200,11 +200,25 @@ namespace rawaccel { accel(args, mode, lut), gain_cap(args.gain_cap, accel), clamp(args.scale_cap) {} - inline double apply(double speed) const { + inline double apply(double speed, double output_speed_cap) const { + double scale; + if (gain_cap.should_apply(speed)) { - return clamp(gain_cap.apply(speed)); + scale = gain_cap.apply(speed); + } + else { + scale = accel.apply(speed); + } + + scale = clamp(scale); + + double output_speed = scale * speed; + + if (output_speed_cap > 0 && output_speed > output_speed_cap) { + scale = output_speed_cap / speed; } - else return clamp(accel.apply(speed)); + + return scale; } accelerator() = default; @@ -216,6 +230,7 @@ namespace rawaccel { bool apply_accel = false; bool combine_magnitudes = true; rotator rotate; + double output_speed_cap = 0; vec2 accels; vec2d sensitivity = { 1, 1 }; @@ -236,6 +251,7 @@ namespace rawaccel { return; } + output_speed_cap = maxsd(args.speed_cap, 0); accels.x = accelerator(args.argsv.x, args.modes.x, luts.x); accels.y = accelerator(args.argsv.y, args.modes.y, luts.y); apply_accel = true; @@ -259,13 +275,13 @@ namespace rawaccel { if (combine_magnitudes) { double mag = sqrtsd(movement.x * movement.x + movement.y * movement.y); double speed = mag / time; - double scale = accels.x.apply(speed); + double scale = accels.x.apply(speed, output_speed_cap); movement.x *= scale; movement.y *= scale; } else { - movement.x *= accels.x.apply(fabs(movement.x) / time); - movement.y *= accels.y.apply(fabs(movement.y) / time); + movement.x *= accels.x.apply(fabs(movement.x) / time, output_speed_cap); + movement.y *= accels.y.apply(fabs(movement.y) / time, output_speed_cap); } } } diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs index dd1e37de..902b135f 100644 --- a/grapher/Models/AccelGUI.cs +++ b/grapher/Models/AccelGUI.cs @@ -120,7 +120,8 @@ public void UpdateActiveSettingsFromFields() combineMagnitudes = ApplyOptions.IsWhole, modes = ApplyOptions.GetModes(), args = ApplyOptions.GetArgs(), - minimumTime = driverSettings.minimumTime + minimumTime = driverSettings.minimumTime, + speedCap = driverSettings.speedCap }; WriteButtonDelay(); diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index a921801f..1bfb251b 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -63,6 +63,9 @@ public ref struct DriverSettings [JsonProperty("Accel parameters")] Vec2 args; + [JsonProperty("Output Speed Cap", Required = Required::Default)] + double speedCap; + [JsonProperty("Sensitivity multipliers")] Vec2 sensitivity; From c7ba6fb1d992a0efbcb581dfeaa65b0f5f59cdb7 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 20 Oct 2020 19:05:35 -0400 Subject: [PATCH 2/6] update min time threshold for 8khz --- common/rawaccel-settings.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/rawaccel-settings.h b/common/rawaccel-settings.h index 02f0a8a2..fe171818 100644 --- a/common/rawaccel-settings.h +++ b/common/rawaccel-settings.h @@ -4,10 +4,12 @@ #include "accel-base.hpp" namespace rawaccel { + using milliseconds = double; + inline constexpr int MAX_POLL_RATE_KHZ = 8; + inline constexpr milliseconds DEFAULT_TIME_MIN = 1.0 / MAX_POLL_RATE_KHZ * 0.8; inline constexpr milliseconds WRITE_DELAY = 1000; - inline constexpr milliseconds DEFAULT_TIME_MIN = 0.4; enum class accel_mode { linear, classic, natural, naturalgain, power, motivity, noaccel From 91803c92a0ad16168126cf7d80de12d14855440d Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Wed, 21 Oct 2020 18:54:44 -0400 Subject: [PATCH 3/6] fix sens label visibility when separated --- grapher/Models/Options/ActiveValueLabelXY.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grapher/Models/Options/ActiveValueLabelXY.cs b/grapher/Models/Options/ActiveValueLabelXY.cs index 1367a6ab..381779c5 100644 --- a/grapher/Models/Options/ActiveValueLabelXY.cs +++ b/grapher/Models/Options/ActiveValueLabelXY.cs @@ -143,7 +143,8 @@ public void AlignActiveValues() private void Align (int width) { FullWidth = width; - ShortenedWidth = FullWidth / 2; + // ShortenedWidth = FullWidth / 2; + ShortenedWidth = FullWidth; SetYLeft(); Y.Width = ShortenedWidth; From 737461c030322ca9120aca7f61cb664fb484265a Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Wed, 21 Oct 2020 19:23:42 -0400 Subject: [PATCH 4/6] put autowrite option back in menu --- grapher/Form1.Designer.cs | 20 +++- grapher/Form1.cs | 1 + grapher/Models/AccelGUI.cs | 93 +++++++++---------- grapher/Models/AccelGUIFactory.cs | 2 + grapher/Models/Serialized/GUISettings.cs | 10 +- grapher/Models/Serialized/RawAccelSettings.cs | 17 ++-- grapher/Models/Serialized/SettingsManager.cs | 25 +++-- 7 files changed, 95 insertions(+), 73 deletions(-) diff --git a/grapher/Form1.Designer.cs b/grapher/Form1.Designer.cs index a6ae7543..6fd9478b 100644 --- a/grapher/Form1.Designer.cs +++ b/grapher/Form1.Designer.cs @@ -168,6 +168,7 @@ private void InitializeComponent() this.GainChart = new System.Windows.Forms.DataVisualization.Charting.Chart(); this.VelocityChart = new System.Windows.Forms.DataVisualization.Charting.Chart(); this.AccelerationChart = new System.Windows.Forms.DataVisualization.Charting.Chart(); + this.AutoWriteMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.optionsPanel.SuspendLayout(); this.menuStrip1.SuspendLayout(); this.chartsPanel.SuspendLayout(); @@ -954,7 +955,8 @@ private void InitializeComponent() this.advancedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.capStyleToolStripMenuItem, this.offsetStyleToolStripMenuItem, - this.toolStripMenuItem1}); + this.toolStripMenuItem1, + this.AutoWriteMenuItem}); this.advancedToolStripMenuItem.Name = "advancedToolStripMenuItem"; this.advancedToolStripMenuItem.Size = new System.Drawing.Size(72, 20); this.advancedToolStripMenuItem.Text = "Advanced"; @@ -965,7 +967,7 @@ private void InitializeComponent() this.gainCapToolStripMenuItem, this.legacyCapToolStripMenuItem}); this.capStyleToolStripMenuItem.Name = "capStyleToolStripMenuItem"; - this.capStyleToolStripMenuItem.Size = new System.Drawing.Size(163, 22); + this.capStyleToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.capStyleToolStripMenuItem.Text = "Cap Style"; // // gainCapToolStripMenuItem @@ -988,7 +990,7 @@ private void InitializeComponent() this.gainOffsetToolStripMenuItem, this.legacyOffsetToolStripMenuItem}); this.offsetStyleToolStripMenuItem.Name = "offsetStyleToolStripMenuItem"; - this.offsetStyleToolStripMenuItem.Size = new System.Drawing.Size(163, 22); + this.offsetStyleToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.offsetStyleToolStripMenuItem.Text = "Offset Style"; // // gainOffsetToolStripMenuItem @@ -1009,7 +1011,7 @@ private void InitializeComponent() this.wholeVectorToolStripMenuItem, this.byVectorComponentToolStripMenuItem}); this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(163, 22); + this.toolStripMenuItem1.Size = new System.Drawing.Size(210, 22); this.toolStripMenuItem1.Text = "Application Style"; // // wholeVectorToolStripMenuItem @@ -1279,6 +1281,15 @@ private void InitializeComponent() title6.Text = "Sensitivity"; this.AccelerationChart.Titles.Add(title6); // + // AutoWriteMenuItem + // + this.AutoWriteMenuItem.Checked = true; + this.AutoWriteMenuItem.CheckOnClick = true; + this.AutoWriteMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.AutoWriteMenuItem.Name = "AutoWriteMenuItem"; + this.AutoWriteMenuItem.Size = new System.Drawing.Size(210, 22); + this.AutoWriteMenuItem.Text = "Apply Settings On Startup"; + // // RawAcceleration // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1406,6 +1417,7 @@ private void InitializeComponent() private System.Windows.Forms.DataVisualization.Charting.Chart GainChart; private System.Windows.Forms.DataVisualization.Charting.Chart VelocityChart; private System.Windows.Forms.DataVisualization.Charting.Chart AccelerationChart; + private System.Windows.Forms.ToolStripMenuItem AutoWriteMenuItem; } } diff --git a/grapher/Form1.cs b/grapher/Form1.cs index 446618bf..d62ed6d8 100644 --- a/grapher/Form1.cs +++ b/grapher/Form1.cs @@ -59,6 +59,7 @@ public RawAcceleration() legacyCapToolStripMenuItem, gainOffsetToolStripMenuItem, legacyOffsetToolStripMenuItem, + AutoWriteMenuItem, ScaleMenuItem, DPITextBox, PollRateTextBox, diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs index 902b135f..09b432f7 100644 --- a/grapher/Models/AccelGUI.cs +++ b/grapher/Models/AccelGUI.cs @@ -33,13 +33,8 @@ public AccelGUI( ToggleButton = (CheckBox)toggleButton; ScaleMenuItem = scaleMenuItem; Settings = settings; - Settings.Startup(); - RefreshOnRead(Settings.RawAccelSettings.AccelerationSettings); - AccelForm.DoResize(); - DefaultButtonFont = WriteButton.Font; SmallButtonFont = new Font(WriteButton.Font.Name, WriteButton.Font.Size * Constants.SmallButtonSizeFactor); - MouseWatcher = mouseWatcher; ScaleMenuItem.Click += new System.EventHandler(OnScaleMenuItemClick); @@ -50,9 +45,30 @@ public AccelGUI( ButtonTimerInterval = Convert.ToInt32(DriverInterop.WriteDelayMs); ButtonTimer = new Timer(); ButtonTimer.Tick += new System.EventHandler(OnButtonTimerTick); - SetupButtons(); ChartRefresh = SetupChartTimer(); + + bool settingsActive = Settings.Startup(); + SettingsNotDefault = !Settings.RawAccelSettings.IsDefaultEquivalent(); + + if (settingsActive) + { + LastToggleChecked = SettingsNotDefault; + ToggleButton.Enabled = LastToggleChecked; + RefreshOnRead(Settings.RawAccelSettings.AccelerationSettings); + } + else + { + DriverSettings active = DriverInterop.GetActiveSettings(); + bool activeNotDefault = !RawAccelSettings.IsDefaultEquivalent(active); + + LastToggleChecked = activeNotDefault; + ToggleButton.Enabled = SettingsNotDefault || activeNotDefault; + RefreshOnRead(active); + } + + SetupButtons(); + AccelForm.DoResize(); } #endregion Constructors @@ -124,11 +140,12 @@ public void UpdateActiveSettingsFromFields() speedCap = driverSettings.speedCap }; - WriteButtonDelay(); + ButtonDelay(WriteButton); SettingsErrors errors = Settings.TryUpdateActiveSettings(settings); if (errors.Empty()) { - RefreshToggleStateFromNewSettings(); + SettingsNotDefault = !Settings.RawAccelSettings.IsDefaultEquivalent(); + LastToggleChecked = SettingsNotDefault; RefreshOnRead(Settings.RawAccelSettings.AccelerationSettings); } else @@ -177,34 +194,23 @@ private void SetupButtons() ToggleButton.Size = WriteButton.Size; ToggleButton.Top = WriteButton.Top; - RefreshToggleStateFromNewSettings(); - SetToggleButtonDefault(); - SetWriteButtonDefault(); + SetButtonDefaults(); } - private void RefreshToggleStateFromNewSettings() + private void SetButtonDefaults() { - SettingsNotDefault = !Settings.RawAccelSettings.IsDefaultEquivalent(); - LastToggleChecked = SettingsNotDefault; - } + ToggleButton.Checked = LastToggleChecked; + + ToggleButton.Font = DefaultButtonFont; + ToggleButton.Text = ToggleButton.Checked ? "Enabled" : "Disabled"; + ToggleButton.Update(); - private void SetWriteButtonDefault() - { WriteButton.Font = DefaultButtonFont; WriteButton.Text = Constants.WriteButtonDefaultText; WriteButton.Enabled = ToggleButton.Checked || !ToggleButton.Enabled; WriteButton.Update(); } - private void SetToggleButtonDefault() - { - ToggleButton.Checked = LastToggleChecked; - ToggleButton.Enabled = SettingsNotDefault; - ToggleButton.Font = DefaultButtonFont; - ToggleButton.Text = ToggleButton.Checked ? "Enabled" : "Disabled"; - ToggleButton.Update(); - } - private void OnScaleMenuItemClick(object sender, EventArgs e) { UpdateGraph(Settings.RawAccelSettings.AccelerationSettings); @@ -221,7 +227,8 @@ private void OnToggleButtonClick(object sender, EventArgs e) Settings.RawAccelSettings.AccelerationSettings : DriverInterop.DefaultSettings; - ToggleButtonDelay(); + LastToggleChecked = ToggleButton.Checked; + ButtonDelay(ToggleButton); SettingsManager.SendToDriver(settings); Settings.ActiveAccel.UpdateFromSettings(settings); @@ -231,8 +238,8 @@ private void OnToggleButtonClick(object sender, EventArgs e) private void OnButtonTimerTick(object sender, EventArgs e) { ButtonTimer.Stop(); - SetToggleButtonDefault(); - SetWriteButtonDefault(); + ToggleButton.Enabled = SettingsNotDefault; + SetButtonDefaults(); } private void StartButtonTimer() @@ -241,33 +248,17 @@ private void StartButtonTimer() ButtonTimer.Start(); } - private void WriteButtonDelay() + private void ButtonDelay(ButtonBase btn) { - WriteButton.Font = SmallButtonFont; - WriteButton.Text = $"{Constants.ButtonDelayText} : {ButtonTimerInterval} ms"; + ToggleButton.Checked = false; + + ToggleButton.Enabled = false; WriteButton.Enabled = false; - WriteButton.Update(); - if (ToggleButton.Enabled) - { - LastToggleChecked = ToggleButton.Checked; - ToggleButton.Checked = false; - ToggleButton.Enabled = false; - ToggleButton.Update(); - } - StartButtonTimer(); - } + btn.Font = SmallButtonFont; + btn.Text = $"{Constants.ButtonDelayText} : {ButtonTimerInterval} ms"; - private void ToggleButtonDelay() - { - LastToggleChecked = ToggleButton.Checked; - ToggleButton.Checked = false; - ToggleButton.Enabled = false; - ToggleButton.Font = SmallButtonFont; - ToggleButton.Text = $"{Constants.ButtonDelayText} : {ButtonTimerInterval} ms"; ToggleButton.Update(); - - WriteButton.Enabled = false; WriteButton.Update(); StartButtonTimer(); diff --git a/grapher/Models/AccelGUIFactory.cs b/grapher/Models/AccelGUIFactory.cs index 51bbc2b9..3dc2a742 100644 --- a/grapher/Models/AccelGUIFactory.cs +++ b/grapher/Models/AccelGUIFactory.cs @@ -32,6 +32,7 @@ public static AccelGUI Construct( ToolStripMenuItem legacyCapToolStripMenuItem, ToolStripMenuItem gainOffsetToolStripMenuItem, ToolStripMenuItem legacyOffsetToolStripMenuItem, + ToolStripMenuItem autoWriteMenuItem, ToolStripMenuItem scaleMenuItem, ToolStripTextBox dpiTextBox, ToolStripTextBox pollRateTextBox, @@ -326,6 +327,7 @@ public static AccelGUI Construct( activeAccel, accelCalculator.DPI, accelCalculator.PollRate, + autoWriteMenuItem, showLastMouseMoveMenuItem, showVelocityGainToolStripMenuItem); diff --git a/grapher/Models/Serialized/GUISettings.cs b/grapher/Models/Serialized/GUISettings.cs index c8f87aed..bb350552 100644 --- a/grapher/Models/Serialized/GUISettings.cs +++ b/grapher/Models/Serialized/GUISettings.cs @@ -4,6 +4,7 @@ namespace grapher.Models.Serialized { [Serializable] + [JsonObject(ItemRequired = Required.Always)] public class GUISettings { #region Constructors @@ -27,6 +28,9 @@ public GUISettings() {} [JsonProperty(Order = 4)] public bool ShowVelocityAndGain { get; set; } + [JsonProperty(Order = 5)] + public bool AutoWriteToDriverOnStartup { get; set; } + #endregion Properties #region Methods @@ -48,7 +52,8 @@ public bool Equals(GUISettings other) return DPI == other.DPI && PollRate == other.PollRate && ShowLastMouseMove == other.ShowLastMouseMove && - ShowVelocityAndGain == other.ShowVelocityAndGain; + ShowVelocityAndGain == other.ShowVelocityAndGain && + AutoWriteToDriverOnStartup == other.AutoWriteToDriverOnStartup; } public override int GetHashCode() @@ -56,7 +61,8 @@ public override int GetHashCode() return DPI.GetHashCode() ^ PollRate.GetHashCode() ^ ShowLastMouseMove.GetHashCode() ^ - ShowVelocityAndGain.GetHashCode(); + ShowVelocityAndGain.GetHashCode() ^ + AutoWriteToDriverOnStartup.GetHashCode(); } #endregion Methods diff --git a/grapher/Models/Serialized/RawAccelSettings.cs b/grapher/Models/Serialized/RawAccelSettings.cs index 818bfb61..af87a657 100644 --- a/grapher/Models/Serialized/RawAccelSettings.cs +++ b/grapher/Models/Serialized/RawAccelSettings.cs @@ -117,13 +117,18 @@ private void AddComments(JObject thisJO) public bool IsDefaultEquivalent() { - bool wholeOrNoY = AccelerationSettings.combineMagnitudes || - AccelerationSettings.modes.y == AccelMode.noaccel; + return IsDefaultEquivalent(AccelerationSettings); + } + + public static bool IsDefaultEquivalent(DriverSettings accelSettings) + { + bool wholeOrNoY = accelSettings.combineMagnitudes || + accelSettings.modes.y == AccelMode.noaccel; - return AccelerationSettings.sensitivity.x == 1 && - AccelerationSettings.sensitivity.y == 1 && - AccelerationSettings.rotation == 0 && - AccelerationSettings.modes.x == AccelMode.noaccel && + return accelSettings.sensitivity.x == 1 && + accelSettings.sensitivity.y == 1 && + accelSettings.rotation == 0 && + accelSettings.modes.x == AccelMode.noaccel && wholeOrNoY; } diff --git a/grapher/Models/Serialized/SettingsManager.cs b/grapher/Models/Serialized/SettingsManager.cs index 8712c87a..f13ba810 100644 --- a/grapher/Models/Serialized/SettingsManager.cs +++ b/grapher/Models/Serialized/SettingsManager.cs @@ -14,12 +14,14 @@ public SettingsManager( ManagedAccel activeAccel, Field dpiField, Field pollRateField, + ToolStripMenuItem autoWrite, ToolStripMenuItem showLastMouseMove, ToolStripMenuItem showVelocityAndGain) { ActiveAccel = activeAccel; DpiField = dpiField; PollRateField = pollRateField; + AutoWriteMenuItem = autoWrite; ShowLastMouseMoveMenuItem = showLastMouseMove; ShowVelocityAndGainMoveMenuItem = showVelocityAndGain; } @@ -36,6 +38,8 @@ public SettingsManager( private Field PollRateField { get; set; } + private ToolStripMenuItem AutoWriteMenuItem { get; set; } + private ToolStripMenuItem ShowLastMouseMoveMenuItem { get; set; } private ToolStripMenuItem ShowVelocityAndGainMoveMenuItem { get; set; } @@ -92,12 +96,7 @@ public void UpdateFieldsFromGUISettings() PollRateField.SetToEntered(RawAccelSettings.GUISettings.PollRate); ShowLastMouseMoveMenuItem.Checked = RawAccelSettings.GUISettings.ShowLastMouseMove; ShowVelocityAndGainMoveMenuItem.Checked = RawAccelSettings.GUISettings.ShowVelocityAndGain; - } - - public void UpdateActiveAccelFromFileSettings(DriverSettings settings) - { - TryUpdateAccel(settings); - UpdateFieldsFromGUISettings(); + AutoWriteMenuItem.Checked = RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup; } public SettingsErrors TryUpdateAccel(DriverSettings settings) @@ -126,11 +125,13 @@ public GUISettings MakeGUISettingsFromFields() DPI = (int)DpiField.Data, PollRate = (int)PollRateField.Data, ShowLastMouseMove = ShowLastMouseMoveMenuItem.Checked, - ShowVelocityAndGain = ShowVelocityAndGainMoveMenuItem.Checked + ShowVelocityAndGain = ShowVelocityAndGainMoveMenuItem.Checked, + AutoWriteToDriverOnStartup = AutoWriteMenuItem.Checked }; } - public void Startup() + // Returns true when file settings are active + public bool Startup() { if (RawAccelSettings.Exists()) { @@ -138,8 +139,11 @@ public void Startup() { RawAccelSettings = RawAccelSettings.Load(() => MakeGUISettingsFromFields()); UpdateFieldsFromGUISettings(); - UpdateActiveAccelFromFileSettings(RawAccelSettings.AccelerationSettings); - return; + if (RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup) + { + TryUpdateAccel(RawAccelSettings.AccelerationSettings); + } + return RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup; } catch (JsonException e) { @@ -151,6 +155,7 @@ public void Startup() DriverInterop.GetActiveSettings(), MakeGUISettingsFromFields()); RawAccelSettings.Save(); + return true; } #endregion Methods From f0ec7a278892c0dfed7c39e4efebd57d97cdb46c Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Wed, 21 Oct 2020 21:03:19 -0400 Subject: [PATCH 5/6] move speedcap into accelerator --- common/accel-base.hpp | 1 + common/rawaccel-settings.h | 1 - common/rawaccel.hpp | 19 +++++++++---------- grapher/Models/AccelGUI.cs | 9 ++++++--- wrapper/wrapper.cpp | 5 ++--- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/common/accel-base.hpp b/common/accel-base.hpp index ac7ac4d1..b15d6953 100644 --- a/common/accel-base.hpp +++ b/common/accel-base.hpp @@ -14,6 +14,7 @@ namespace rawaccel { double weight = 1; double scale_cap = 0; double gain_cap = 0; + double speed_cap = 0; }; template diff --git a/common/rawaccel-settings.h b/common/rawaccel-settings.h index fe171818..e9e158c6 100644 --- a/common/rawaccel-settings.h +++ b/common/rawaccel-settings.h @@ -20,7 +20,6 @@ namespace rawaccel { bool combine_mags = true; vec2 modes = { accel_mode::noaccel, accel_mode::noaccel }; vec2 argsv; - double speed_cap = 0; vec2d sens = { 1, 1 }; milliseconds time_min = DEFAULT_TIME_MIN; }; diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 3a49aa67..b160a425 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -195,12 +195,15 @@ namespace rawaccel { accel_variant accel; velocity_gain_cap gain_cap; accel_scale_clamp clamp; + double output_speed_cap = 0; accelerator(const accel_args& args, accel_mode mode, si_pair* lut = nullptr) : accel(args, mode, lut), gain_cap(args.gain_cap, accel), clamp(args.scale_cap) - {} + { + output_speed_cap = maxsd(args.speed_cap, 0); + } - inline double apply(double speed, double output_speed_cap) const { + inline double apply(double speed) const { double scale; if (gain_cap.should_apply(speed)) { @@ -212,9 +215,7 @@ namespace rawaccel { scale = clamp(scale); - double output_speed = scale * speed; - - if (output_speed_cap > 0 && output_speed > output_speed_cap) { + if (output_speed_cap > 0 && (scale * speed) > output_speed_cap) { scale = output_speed_cap / speed; } @@ -230,7 +231,6 @@ namespace rawaccel { bool apply_accel = false; bool combine_magnitudes = true; rotator rotate; - double output_speed_cap = 0; vec2 accels; vec2d sensitivity = { 1, 1 }; @@ -251,7 +251,6 @@ namespace rawaccel { return; } - output_speed_cap = maxsd(args.speed_cap, 0); accels.x = accelerator(args.argsv.x, args.modes.x, luts.x); accels.y = accelerator(args.argsv.y, args.modes.y, luts.y); apply_accel = true; @@ -275,13 +274,13 @@ namespace rawaccel { if (combine_magnitudes) { double mag = sqrtsd(movement.x * movement.x + movement.y * movement.y); double speed = mag / time; - double scale = accels.x.apply(speed, output_speed_cap); + double scale = accels.x.apply(speed); movement.x *= scale; movement.y *= scale; } else { - movement.x *= accels.x.apply(fabs(movement.x) / time, output_speed_cap); - movement.y *= accels.y.apply(fabs(movement.y) / time, output_speed_cap); + movement.x *= accels.x.apply(fabs(movement.x) / time); + movement.y *= accels.y.apply(fabs(movement.y) / time); } } } diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs index 09b432f7..c08313bc 100644 --- a/grapher/Models/AccelGUI.cs +++ b/grapher/Models/AccelGUI.cs @@ -125,6 +125,10 @@ public void UpdateActiveSettingsFromFields() { var driverSettings = Settings.RawAccelSettings.AccelerationSettings; + var newArgs = ApplyOptions.GetArgs(); + newArgs.x.speedCap = driverSettings.args.x.speedCap; + newArgs.y.speedCap = driverSettings.args.y.speedCap; + var settings = new DriverSettings { rotation = ApplyOptions.Rotation.Field.Data, @@ -135,9 +139,8 @@ public void UpdateActiveSettingsFromFields() }, combineMagnitudes = ApplyOptions.IsWhole, modes = ApplyOptions.GetModes(), - args = ApplyOptions.GetArgs(), - minimumTime = driverSettings.minimumTime, - speedCap = driverSettings.speedCap + args = newArgs, + minimumTime = driverSettings.minimumTime }; ButtonDelay(WriteButton); diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 1bfb251b..ee88112a 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -33,6 +33,8 @@ public value struct AccelArgs [JsonProperty("legacyCap")] double scaleCap; double gainCap; + [JsonProperty(Required = Required::Default)] + double speedCap; }; generic @@ -63,9 +65,6 @@ public ref struct DriverSettings [JsonProperty("Accel parameters")] Vec2 args; - [JsonProperty("Output Speed Cap", Required = Required::Default)] - double speedCap; - [JsonProperty("Sensitivity multipliers")] Vec2 sensitivity; From fa3a5f448d6d6d66b3de313f674623c583bdf41b Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Wed, 21 Oct 2020 21:03:31 -0400 Subject: [PATCH 6/6] update signed --- signed/driver/rawaccel.sys | Bin 52552 -> 52560 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/signed/driver/rawaccel.sys b/signed/driver/rawaccel.sys index 94872fea0221bfc9687587668d3fd8d97886b9cc..a390fc4f3d27eb48f10a0e62dc7df29ff86b591c 100644 GIT binary patch delta 13035 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 HAAkQ3gpxQj delta 12917 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