diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs index 920a5cecb6..6145e90c5b 100755 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs @@ -122,17 +122,15 @@ namespace BizHawk.Client.Common private class Bk2ControllerDefinition : ControllerDefinition { + public IReadOnlyList> ControlsFromLog = null; + public Bk2ControllerDefinition(ControllerDefinition source) : base(source) { } - public List> ControlsFromLog { private get; set; } = new List>(); - - public override IEnumerable> ControlsOrdered => - ControlsFromLog.Any() - ? ControlsFromLog - : base.ControlsOrdered; + protected override IReadOnlyList> GenOrderedControls() + => ControlsFromLog is not null && ControlsFromLog.Count is not 0 ? ControlsFromLog : base.GenOrderedControls(); } } } diff --git a/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs b/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs index 9c08bcab66..e574999bb4 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs @@ -21,6 +21,20 @@ namespace BizHawk.Emulation.Common private bool _mutable = true; + private IReadOnlyList> _orderedControls = null; + + /// starts with console buttons, then each player's buttons individually + public IReadOnlyList> ControlsOrdered + { + get + { + if (_orderedControls is not null) return _orderedControls; + if (!_mutable) return _orderedControls = GenOrderedControls(); + const string ERR_MSG = "this " + nameof(ControllerDefinition) + " has not yet been built and sealed, so it is not safe to enumerate this while it could still be mutated"; + throw new InvalidOperationException(ERR_MSG); + } + } + public readonly string Name; public ControllerDefinition(string name) @@ -77,39 +91,20 @@ namespace BizHawk.Emulation.Common } } - /// - /// Gets a list of controls put in a logical order such as by controller number, - /// This is a default implementation that should work most of the time - /// - public virtual IEnumerable> ControlsOrdered - { - get - { - var list = new List(Axes.Keys); - list.AddRange(BoolButtons); - - // starts with console buttons, then each player's buttons individually - var ret = new List[PlayerCount + 1]; - for (int i = 0; i < ret.Length; i++) - { - ret[i] = new List(); - } - - foreach (string btn in list) - { - ret[PlayerNumber(btn)].Add(btn); - } - - return ret; - } - } - private void AssertMutable() { const string ERR_MSG = "this " + nameof(ControllerDefinition) + " has been built and sealed, and may not be mutated"; if (!_mutable) throw new InvalidOperationException(ERR_MSG); } + protected virtual IReadOnlyList> GenOrderedControls() + { + var ret = new List[PlayerCount + 1]; + for (var i = 0; i < ret.Length; i++) ret[i] = new(); + foreach (var btn in Axes.Keys.Concat(BoolButtons)) ret[PlayerNumber(btn)].Add(btn); + return ret; + } + /// permanently disables the ability to mutate this instance; returns this reference public ControllerDefinition MakeImmutable() {