Skip to content

Commit

Permalink
Refactor MnemonicCache
Browse files Browse the repository at this point in the history
+ make Bk2LogEntryGenerator and Bk2InputDisplayGenerator static
This should simplify stuff and make the logic clearer
  • Loading branch information
Morilli committed Sep 28, 2023
1 parent 97690f7 commit 1e4eb7d
Show file tree
Hide file tree
Showing 45 changed files with 298 additions and 410 deletions.
2 changes: 1 addition & 1 deletion src/BizHawk.Client.Common/Api/Classes/JoypadApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public IReadOnlyDictionary<string, object> GetImmediate(int? controller = null)

public void SetFromMnemonicStr(string inputLogEntry)
{
var controller = _movieSession.GenerateMovieController(_inputManager.ActiveController.Definition, null);
var controller = _movieSession.GenerateMovieController(_inputManager.ActiveController.Definition);
try
{
controller.SetFromMnemonic(inputLogEntry);
Expand Down
2 changes: 1 addition & 1 deletion src/BizHawk.Client.Common/Api/Classes/MovieApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public string GetInputAsMnemonic(int frame)
return string.Empty;
}

return _movieSession.Movie.GetInputState(frame).LogEntryGenerator.GenerateLogEntry();
return Bk2LogEntryGenerator.GenerateLogEntry(_movieSession.Movie.GetInputState(frame));
}

public void Save(string filename = null)
Expand Down
4 changes: 2 additions & 2 deletions src/BizHawk.Client.Common/DisplayManager/OSDManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ public string InputStrOrAll()
? MakeStringFor(_inputManager.AutofireStickyXorAdapter.Or(_movieSession.Movie.GetInputState(_emulator.Frame - 1)))
: InputStrImmediate();

private string MakeStringFor(IController controller)
private static string MakeStringFor(IController controller)
{
return _inputManager.InputDisplayGenerator.Generate(controller);
return Bk2InputDisplayGenerator.Generate(controller);
}

public string MakeIntersectImmediatePrevious()
Expand Down
65 changes: 0 additions & 65 deletions src/BizHawk.Client.Common/display/IInputDisplayGenerator.cs

This file was deleted.

47 changes: 47 additions & 0 deletions src/BizHawk.Client.Common/display/InputDisplayGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Linq;
using System.Text;
using BizHawk.Emulation.Common;

namespace BizHawk.Client.Common
{
/// <summary>
/// Generates a display friendly version of the input log entry
/// using .bk2 mnemonics as the basis for display
/// </summary>
public static class Bk2InputDisplayGenerator
{
public static string Generate(IController source)
{
if (source.Definition.MnemonicsCache is null)
throw new InvalidOperationException("Can't generate input display string with empty mnemonics cache");

var sb = new StringBuilder();

foreach ((string buttonName, AxisSpec? axisSpec) in source.Definition.ControlsOrdered.SelectMany(x => x))
{
if (axisSpec.HasValue)
{
int val = source.AxisValue(buttonName);

if (val == axisSpec.Value.Neutral)
{
sb.Append(" ");
}
else
{
sb.Append(val.ToString().PadLeft(5, ' ')).Append(',');
}
}
else
{
sb.Append(source.IsPressed(buttonName)
? source.Definition.MnemonicsCache[buttonName]
: ' ');
}
}

return sb.ToString();
}
}
}
13 changes: 3 additions & 10 deletions src/BizHawk.Client.Common/inputAdapters/InputManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ namespace BizHawk.Client.Common
// (1)->Input Display
public class InputManager
{
public Bk2InputDisplayGenerator InputDisplayGenerator { get; private set; }

// the original source controller, bound to the user, sort of the "input" port for the chain, i think
public Controller ActiveController { get; private set; }

Expand Down Expand Up @@ -53,23 +51,18 @@ public class InputManager

public Func<(Point Pos, long Scroll, bool LMB, bool MMB, bool RMB, bool X1MB, bool X2MB)> GetMainFormMouseInfo { get; set; }

private void SetActiveController(Controller controller, string systemId)
{
ActiveController = controller;
InputDisplayGenerator = new Bk2InputDisplayGenerator(systemId, ActiveController.Definition);
}

public void ResetMainControllers(AutofireController nullAutofireController)
{
SetActiveController(new Controller(NullController.Instance.Definition), VSystemID.Raw.NULL);
ActiveController = new Controller(NullController.Instance.Definition);
AutoFireController = nullAutofireController;
}

public void SyncControls(IEmulator emulator, IMovieSession session, Config config)
{
var def = emulator.ControllerDefinition;
def.BuildMnemonicsCache(Bk2MnemonicLookup.MnemonicFunc(emulator.SystemId));

SetActiveController(BindToDefinition(def, config.AllTrollers, config.AllTrollersAnalog, config.AllTrollersFeedbacks), emulator.SystemId);
ActiveController = BindToDefinition(def, config.AllTrollers, config.AllTrollersAnalog, config.AllTrollersFeedbacks);
AutoFireController = BindToDefinitionAF(emulator, config.AllTrollersAutoFire, config.AutofireOn, config.AutofireOff);

// allow propagating controls that are in the current controller definition but not in the prebaked one
Expand Down
22 changes: 6 additions & 16 deletions src/BizHawk.Client.Common/movie/MovieSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,13 @@ public MovieSession(
public IInputAdapter MovieOut { get; } = new CopyControllerAdapter();
public IStickyAdapter StickySource { get; set; }

public IMovieController MovieController { get; private set; } = new Bk2Controller(NullController.Instance.Definition, VSystemID.Raw.NULL);
public IMovieController MovieController { get; private set; } = new Bk2Controller(NullController.Instance.Definition);

public IMovieController GenerateMovieController()
public IMovieController GenerateMovieController(ControllerDefinition definition = null, string logKey = null)
{
// TODO: expose Movie.LogKey and pass in here
return new Bk2Controller("", MovieController.Definition, Movie.SystemID);
}

public IMovieController GenerateMovieController(ControllerDefinition definition, string systemId)
{
// TODO: expose Movie.LogKey and pass in here
return new Bk2Controller("", definition, systemId);
}

public void SetMovieController(ControllerDefinition definition, string systemId)
{
MovieController = GenerateMovieController(definition, systemId);
// TODO: should this fallback to Movie.LogKey?
// this function is kinda weird
return new Bk2Controller(definition ?? MovieController.Definition, logKey);
}

public void HandleFrameBefore()
Expand Down Expand Up @@ -244,7 +234,7 @@ public void QueueNewMovie(IMovie movie, bool record, string systemId, IDictionar

public void RunQueuedMovie(bool recordMode, IEmulator emulator)
{
MovieController = new Bk2Controller(emulator.ControllerDefinition, emulator.SystemId);
MovieController = new Bk2Controller(emulator.ControllerDefinition);

Movie = _queuedMovie;
Movie.Attach(emulator);
Expand Down
76 changes: 26 additions & 50 deletions src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,22 @@ internal class Bk2Controller : IMovieController
private readonly WorkingDictionary<string, bool> _myBoolButtons = new();
private readonly WorkingDictionary<string, int> _myAxisControls = new();

private readonly Bk2ControllerDefinition _type;
private readonly string _systemId;

private IList<ControlMap> _controlsOrdered;

private IList<ControlMap> ControlsOrdered => _controlsOrdered ??= _type.OrderedControlsFlat
.Select(c => new ControlMap
{
Name = c,
IsBool = _type.BoolButtons.Contains(c),
IsAxis = _type.Axes.ContainsKey(c)
})
.ToArray();

public Bk2Controller(string key, ControllerDefinition definition, string systemId) : this(definition, systemId)
public Bk2Controller(ControllerDefinition definition, string logKey) : this(definition)
{
if (!string.IsNullOrEmpty(key))
{
var groups = key.Split(new[] { "#" }, StringSplitOptions.RemoveEmptyEntries);

_type.ControlsFromLog = groups
.Select(group => group.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries))
.ToArray();
}
if (!string.IsNullOrEmpty(logKey))
Definition = new Bk2ControllerDefinition(definition, logKey);
}

public Bk2Controller(ControllerDefinition definition, string systemId)
public Bk2Controller(ControllerDefinition definition)
{
_type = new Bk2ControllerDefinition(definition);
_systemId = systemId;
Definition = definition;
foreach ((string axisName, AxisSpec range) in definition.Axes)
{
_myAxisControls[axisName] = range.Neutral;
}
}

public ControllerDefinition Definition => _type;
public ControllerDefinition Definition { get; }

public bool IsPressed(string button) => _myBoolButtons[button];
public int AxisValue(string name) => _myAxisControls[name];
Expand All @@ -57,9 +36,6 @@ public Bk2Controller(ControllerDefinition definition, string systemId)

public void SetHapticChannelStrength(string name, int strength) {}

private Bk2LogEntryGenerator _logEntryGenerator;
public Bk2LogEntryGenerator LogEntryGenerator => _logEntryGenerator ??= new Bk2LogEntryGenerator(_systemId, this);

public void SetFrom(IController source)
{
for (int index = 0; index < Definition.BoolButtons.Count; index++)
Expand Down Expand Up @@ -92,22 +68,23 @@ public void SetFromMnemonic(string mnemonic)
var trimmed = mnemonic.Replace("|", "");
var iterator = 0;

foreach (var key in ControlsOrdered)
foreach (var playerControls in Definition.ControlsOrdered)
foreach ((string buttonname, AxisSpec? axisSpec) in playerControls)
{
if (key.IsBool)
{
_myBoolButtons[key.Name] = trimmed[iterator] != '.';
iterator++;
}
else if (key.IsAxis)
if (axisSpec.HasValue)
{
var commaIndex = trimmed.Substring(iterator).IndexOf(',');
var temp = trimmed.Substring(iterator, commaIndex);
var val = int.Parse(temp.Trim());
_myAxisControls[key.Name] = val;
_myAxisControls[buttonname] = val;

iterator += commaIndex + 1;
}
else
{
_myBoolButtons[buttonname] = trimmed[iterator] != '.';
iterator++;
}
}
}
}
Expand All @@ -122,24 +99,23 @@ public void SetAxis(string buttonName, int value)
_myAxisControls[buttonName] = value;
}

private class ControlMap
{
public string Name { get; set; }
public bool IsBool { get; set; }
public bool IsAxis { get; set; }
}

private class Bk2ControllerDefinition : ControllerDefinition
{
public IReadOnlyList<IReadOnlyList<string>> ControlsFromLog = null;
private readonly IReadOnlyList<IReadOnlyList<(string, AxisSpec?)>> _controlsFromLogKey;

public Bk2ControllerDefinition(ControllerDefinition source)
: base(source)
public Bk2ControllerDefinition(ControllerDefinition sourceDefinition, string logKey)
: base(sourceDefinition)
{
var groups = logKey.Split(new[] { "#" }, StringSplitOptions.RemoveEmptyEntries);

_controlsFromLogKey = groups
.Select(group => group.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries)
.Select(buttonname => (buttonname, sourceDefinition.Axes.TryGetValue(buttonname, out var axisSpec) ? axisSpec : (AxisSpec?)null))
.ToArray())
.ToArray();
}

protected override IReadOnlyList<IReadOnlyList<string>> GenOrderedControls()
=> ControlsFromLog is not null && ControlsFromLog.Count is not 0 ? ControlsFromLog : base.GenOrderedControls();
protected override IReadOnlyList<IReadOnlyList<(string Name, AxisSpec? AxisSpec)>> GenOrderedControls() => _controlsFromLogKey;
}
}
}
Loading

0 comments on commit 1e4eb7d

Please sign in to comment.