diff --git a/src/BizHawk.Client.Common/Controller.cs b/src/BizHawk.Client.Common/Controller.cs index a28bf42734..3a31f3af9e 100644 --- a/src/BizHawk.Client.Common/Controller.cs +++ b/src/BizHawk.Client.Common/Controller.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -23,21 +24,29 @@ namespace BizHawk.Client.Common public ControllerDefinition Definition { get; } - public bool IsPressed(string button) => _buttons[button]; + public bool IsPressed(string button) + => _buttons.GetValueOrDefault(button); - public int AxisValue(string name) => _axes[name]; + public int AxisValue(string name) + => _axes.GetValueOrDefault(name); public IReadOnlyCollection<(string Name, int Strength)> GetHapticsSnapshot() => _haptics.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); public void SetHapticChannelStrength(string name, int strength) => _haptics[name] = strength; - private readonly WorkingDictionary> _bindings = new WorkingDictionary>(); - private readonly WorkingDictionary _buttons = new WorkingDictionary(); - private readonly WorkingDictionary _axes = new WorkingDictionary(); - private readonly Dictionary _axisRanges = new WorkingDictionary(); + private readonly Dictionary> _bindings = new(); + + private readonly Dictionary _buttons = new(); + + private readonly Dictionary _axes = new(); + + private readonly Dictionary _axisRanges = new(); + private readonly Dictionary _axisBindings = new Dictionary(); - private readonly Dictionary _haptics = new WorkingDictionary(); + + private readonly Dictionary _haptics = new(); + private readonly Dictionary _feedbackBindings = new Dictionary(); public bool this[string button] => IsPressed(button); @@ -89,7 +98,7 @@ namespace BizHawk.Client.Common value *= v.Mult; // -1..1 -> -A..A (where A is the larger "side" of the range e.g. a range of 0..50, neutral=10 would give A=40, and thus a value in -40..40) - var range = _axisRanges[k]; + var range = _axisRanges[k]; // this was `GetValueOrPutNew`, but I really hope it was always found, since `new AxisSpec()` isn't valid --yoshi value *= Math.Max(range.Neutral - range.Min, range.Max - range.Neutral); // shift the midpoint, so a value of 0 becomes range.Neutral (and, assuming >=1x multiplier, all values in range are reachable) @@ -148,7 +157,7 @@ namespace BizHawk.Client.Common _axes[button] = controller.AxisValue(button); } - foreach (var button in controller.InversedButtons) _buttons[button] = !_buttons[button]; + foreach (var button in controller.InversedButtons) _buttons[button] = !_buttons.GetValueOrDefault(button); } public void BindMulti(string button, string controlString) @@ -161,7 +170,7 @@ namespace BizHawk.Client.Common var controlBindings = controlString.Split(','); foreach (var control in controlBindings) { - _bindings[button].Add(control.Trim()); + _bindings.GetValueOrPutNew(button).Add(control.Trim()); } } diff --git a/src/BizHawk.Client.Common/controllers/AutofireController.cs b/src/BizHawk.Client.Common/controllers/AutofireController.cs index 934271127b..42f3ac8482 100644 --- a/src/BizHawk.Client.Common/controllers/AutofireController.cs +++ b/src/BizHawk.Client.Common/controllers/AutofireController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -20,11 +21,11 @@ namespace BizHawk.Client.Common private readonly IEmulator _emulator; - private readonly WorkingDictionary> _bindings = new WorkingDictionary>(); + private readonly Dictionary> _bindings = new(); - private WorkingDictionary _buttons = new(); + private Dictionary _buttons = new(); - private readonly WorkingDictionary _buttonStarts = new WorkingDictionary(); + private readonly Dictionary _buttonStarts = new(); public int On { get; set; } public int Off { get; set; } @@ -34,8 +35,8 @@ namespace BizHawk.Client.Common public ControllerDefinition Definition => _emulator.ControllerDefinition; public bool IsPressed(string button) - => _buttons[button] - && ((internal_frame - _buttonStarts[button]) % (On + Off)) < On; + => _buttons.GetValueOrDefault(button) + && ((internal_frame - _buttonStarts.GetValueOrDefault(button)) % (On + Off)) < On; public void ClearStarts() { @@ -69,7 +70,7 @@ namespace BizHawk.Client.Common if (controller.IsPressed(boundBtn)) { isPressed = true; - if (!buttonStatesPrev[k]) _buttonStarts[k] = internal_frame; + if (!buttonStatesPrev.GetValueOrDefault(k)) _buttonStarts[k] = internal_frame; } } _buttons[k] = isPressed; @@ -83,7 +84,7 @@ namespace BizHawk.Client.Common var controlBindings = controlString.Split(','); foreach (var control in controlBindings) { - _bindings[button].Add(control.Trim()); + _bindings.GetValueOrPutNew(button).Add(control.Trim()); } } } diff --git a/src/BizHawk.Client.Common/controllers/SimpleController.cs b/src/BizHawk.Client.Common/controllers/SimpleController.cs index 5954279425..509e19d0e1 100644 --- a/src/BizHawk.Client.Common/controllers/SimpleController.cs +++ b/src/BizHawk.Client.Common/controllers/SimpleController.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -15,29 +15,33 @@ namespace BizHawk.Client.Common public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null; - protected WorkingDictionary Buttons { get; private set; } = new WorkingDictionary(); - protected WorkingDictionary Axes { get; private set; } = new WorkingDictionary(); - protected WorkingDictionary HapticFeedback { get; private set; } = new WorkingDictionary(); + protected Dictionary Axes { get; private set; } = new(); + + protected Dictionary Buttons { get; private set; } = new(); + + protected Dictionary HapticFeedback { get; private set; } = new(); public SimpleController(ControllerDefinition definition) => Definition = definition; public void Clear() { - Buttons = new WorkingDictionary(); - Axes = new WorkingDictionary(); - HapticFeedback = new WorkingDictionary(); + Buttons = new(); + Axes = new(); + HapticFeedback = new(); } public bool this[string button] { - get => Buttons[button]; + get => Buttons.GetValueOrDefault(button); set => Buttons[button] = value; } - public virtual bool IsPressed(string button) => this[button]; + public virtual bool IsPressed(string button) + => Buttons.GetValueOrDefault(button); - public int AxisValue(string name) => Axes[name]; + public int AxisValue(string name) + => Axes.GetValueOrDefault(name); public IReadOnlyCollection<(string Name, int Strength)> GetHapticsSnapshot() => HapticFeedback.Select(kvp => (kvp.Key, kvp.Value)).ToArray(); diff --git a/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs b/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs index 3466729bf7..84459076e0 100644 --- a/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs +++ b/src/BizHawk.Client.Common/inputAdapters/StickyAdapters.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; -using BizHawk.Common; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -26,13 +25,7 @@ namespace BizHawk.Client.Common public int AxisValue(string name) { - var val = _axisSet[name]; - - if (val.HasValue) - { - return val.Value; - } - + if (_axisSet.TryGetValue(name, out var i)) return i; if (Source == null) { return 0; @@ -51,13 +44,13 @@ namespace BizHawk.Client.Common // if SetAxis() is called (typically virtual pads), then that axis will entirely override the Source input // otherwise, the source is passed thru. - private readonly WorkingDictionary _axisSet = new WorkingDictionary(); + private readonly Dictionary _axisSet = new(); public void SetAxis(string name, int? value) { - if (value.HasValue) + if (value is int i) { - _axisSet[name] = value; + _axisSet[name] = i; } else { @@ -154,8 +147,9 @@ namespace BizHawk.Client.Common _off = off < 0 ? 0 : off; } - private readonly WorkingDictionary _boolPatterns = new WorkingDictionary(); - private readonly WorkingDictionary _axisPatterns = new WorkingDictionary(); + private readonly Dictionary _axisPatterns = new(); + + private readonly Dictionary _boolPatterns = new(); public AutoFireStickyXorAdapter() { diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs index 122fdc75ce..5bb34b6cfe 100755 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs @@ -3,14 +3,16 @@ using System.Diagnostics; using System.Linq; using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common { internal class Bk2Controller : IMovieController { - private readonly WorkingDictionary _myBoolButtons = new(); - private readonly WorkingDictionary _myAxisControls = new(); + private readonly Dictionary _myAxisControls = new(); + + private readonly Dictionary _myBoolButtons = new(); private readonly Bk2ControllerDefinition _type; @@ -45,8 +47,11 @@ namespace BizHawk.Client.Common public ControllerDefinition Definition => _type; - public bool IsPressed(string button) => _myBoolButtons[button]; - public int AxisValue(string name) => _myAxisControls[name]; + public int AxisValue(string name) + => _myAxisControls.GetValueOrDefault(name); + + public bool IsPressed(string button) + => _myBoolButtons.GetValueOrDefault(button); public IReadOnlyCollection<(string Name, int Strength)> GetHapticsSnapshot() => Array.Empty<(string, int)>(); diff --git a/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs b/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs index d20c8259dc..240cee3f24 100644 --- a/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs +++ b/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -39,14 +39,10 @@ namespace BizHawk.Client.Common public ControllerDefinition Definition { get; set; } public bool IsPressed(string button) - { - return _myBoolButtons[button]; - } + => _myBoolButtons.GetValueOrDefault(button); public int AxisValue(string name) - { - return _myAxisControls[name]; - } + => _myAxisControls.GetValueOrDefault(name); public IReadOnlyCollection<(string Name, int Strength)> GetHapticsSnapshot() => throw new NotImplementedException(); // no idea --yoshi @@ -212,8 +208,9 @@ namespace BizHawk.Client.Common } } - private readonly WorkingDictionary _myBoolButtons = new WorkingDictionary(); - private readonly WorkingDictionary _myAxisControls = new WorkingDictionary(); + private readonly Dictionary _myAxisControls = new(); + + private readonly Dictionary _myBoolButtons = new(); private bool IsGenesis6Button() => Definition.BoolButtons.Contains("P1 X"); diff --git a/src/BizHawk.Client.EmuHawk/Input/Input.cs b/src/BizHawk.Client.EmuHawk/Input/Input.cs index 06f45a1972..0becc9f7a0 100644 --- a/src/BizHawk.Client.EmuHawk/Input/Input.cs +++ b/src/BizHawk.Client.EmuHawk/Input/Input.cs @@ -58,9 +58,12 @@ namespace BizHawk.Client.EmuHawk _updateThread.Start(); } - private readonly WorkingDictionary _lastState = new WorkingDictionary(); - private readonly WorkingDictionary _axisValues = new WorkingDictionary(); - private readonly WorkingDictionary _axisDeltas = new WorkingDictionary(); + private readonly Dictionary _axisDeltas = new(); + + private readonly Dictionary _axisValues = new(); + + private readonly Dictionary _lastState = new(); + private bool _trackDeltas; private bool _ignoreEventsNextPoll; @@ -99,7 +102,7 @@ namespace BizHawk.Client.EmuHawk var modIndex = _currentConfig.ModifierKeysEffective.IndexOf(button1); var currentModifier = modIndex is -1 ? 0U : 1U << modIndex; if (EnableIgnoreModifiers && currentModifier is not 0U) return; - if (newState == _lastState[button1]) return; + if (newState == _lastState.GetValueOrDefault(button1)) return; if (currentModifier is not 0U) { @@ -135,7 +138,11 @@ namespace BizHawk.Client.EmuHawk if (ShouldSwallow(MainFormInputAllowedCallback(false), ClientInputFocus.Pad)) return; - if (_trackDeltas) _axisDeltas[axis] += Math.Abs(newValue - _axisValues[axis]); + if (_trackDeltas) + { + _axisDeltas[axis] = _axisDeltas.GetValueOrDefault(axis) + + Math.Abs(newValue - _axisValues.GetValueOrDefault(axis)); + } _axisValues[axis] = newValue; } @@ -217,8 +224,11 @@ namespace BizHawk.Client.EmuHawk if (_trackDeltas) { // these are relative to screen coordinates, but that's not terribly important - _axisDeltas["WMouse X"] += Math.Abs(mousePos.X - _axisValues["WMouse X"]) * 50; - _axisDeltas["WMouse Y"] += Math.Abs(mousePos.Y - _axisValues["WMouse Y"]) * 50; + const float MOUSE_DELTA_SCALE = 50.0f; + _axisDeltas["WMouse X"] = _axisDeltas.GetValueOrDefault("WMouse X") + + MOUSE_DELTA_SCALE * Math.Abs(mousePos.X - _axisValues.GetValueOrDefault("WMouse X")); + _axisDeltas["WMouse Y"] = _axisDeltas.GetValueOrDefault("WMouse Y") + + MOUSE_DELTA_SCALE * Math.Abs(mousePos.Y - _axisValues.GetValueOrDefault("WMouse Y")); } // coordinate translation happens later _axisValues["WMouse X"] = mousePos.X; diff --git a/src/BizHawk.Common/CustomCollections.cs b/src/BizHawk.Common/CustomCollections.cs index 98b55aa91f..eb2738c1a0 100644 --- a/src/BizHawk.Common/CustomCollections.cs +++ b/src/BizHawk.Common/CustomCollections.cs @@ -1,9 +1,5 @@ using System.Collections; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; - -using BizHawk.Common.CollectionExtensions; namespace BizHawk.Common { @@ -103,22 +99,4 @@ namespace BizHawk.Common IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } - - /// A dictionary whose index getter creates an entry if the requested key isn't part of the collection, making it always safe to use the returned value. The new entry's value will be the result of the default constructor of . - [Serializable] - public class WorkingDictionary : Dictionary - where TKey : notnull - where TValue : new() - { - public WorkingDictionary() {} - - protected WorkingDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {} - - [property: MaybeNull] - public new TValue this[TKey key] - { - get => this.GetValueOrPutNew(key); - set => base[key] = value; - } - } } diff --git a/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs b/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs index 302d21eefa..2264981622 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs @@ -91,7 +91,9 @@ namespace BizHawk.Emulation.Common case CircularAxisConstraint circular: var xAxis = k; var yAxis = circular.PairedAxis; - (axes[xAxis], axes[yAxis]) = circular.ApplyTo(axes[xAxis], axes[yAxis]); + (axes[xAxis], axes[yAxis]) = circular.ApplyTo( + CollectionExtensions.GetValueOrDefault(axes, xAxis), + CollectionExtensions.GetValueOrDefault(axes, yAxis)); break; } } diff --git a/src/BizHawk.Emulation.Common/SaveController.cs b/src/BizHawk.Emulation.Common/SaveController.cs index e8f7d65b0b..63e8284ce0 100644 --- a/src/BizHawk.Emulation.Common/SaveController.cs +++ b/src/BizHawk.Emulation.Common/SaveController.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; namespace BizHawk.Emulation.Common { @@ -12,7 +13,7 @@ namespace BizHawk.Emulation.Common /// public class SaveController : IController { - private readonly WorkingDictionary _buttons = new WorkingDictionary(); + private readonly Dictionary _buttons = new(); public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null; @@ -35,10 +36,10 @@ namespace BizHawk.Emulation.Common public void Serialize(BinaryWriter b) { b.Write(_buttons.Keys.Count); - foreach (var k in _buttons.Keys) + foreach (var (k, v) in _buttons) { b.Write(k); - b.Write(_buttons[k]); + b.Write(v); } } @@ -90,14 +91,10 @@ namespace BizHawk.Emulation.Common } public bool IsPressed(string button) - { - return _buttons[button] != 0; - } + => _buttons.GetValueOrDefault(button) is not 0; public int AxisValue(string name) - { - return _buttons[name]; - } + => _buttons.GetValueOrDefault(name); public IReadOnlyCollection<(string Name, int Strength)> GetHapticsSnapshot() => Array.Empty<(string, int)>();