Cache `Bk2InputDisplayGenerator`s for long-lasting `IController`s

This commit is contained in:
YoshiRulz 2021-12-05 22:25:02 +10:00 committed by James Groom
parent 25ccca8bbb
commit a11d0381b2
19 changed files with 69 additions and 19 deletions

View File

@ -9,6 +9,8 @@ namespace BizHawk.Client.Common
{
public class Controller : IController
{
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public Controller(ControllerDefinition definition)
{
Definition = definition;

View File

@ -182,12 +182,12 @@ namespace BizHawk.Client.Common
public string InputStrMovie()
{
return MakeStringFor(_movieSession.MovieController);
return MakeStringFor(_movieSession.MovieController, cache: true);
}
public string InputStrImmediate()
{
return MakeStringFor(_inputManager.AutofireStickyXorAdapter);
return MakeStringFor(_inputManager.AutofireStickyXorAdapter, cache: true);
}
public string InputPrevious()
@ -205,13 +205,19 @@ namespace BizHawk.Client.Common
}
public string InputStrOrAll()
=> MakeStringFor(_movieSession.Movie.IsPlayingOrRecording() && _emulator.Frame > 0
? _inputManager.AutofireStickyXorAdapter.Or(_movieSession.Movie.GetInputState(_emulator.Frame - 1))
: _inputManager.AutofireStickyXorAdapter);
=> _movieSession.Movie.IsPlayingOrRecording() && _emulator.Frame > 0
? MakeStringFor(_inputManager.AutofireStickyXorAdapter.Or(_movieSession.Movie.GetInputState(_emulator.Frame - 1)))
: InputStrImmediate();
private string MakeStringFor(IController controller)
private string MakeStringFor(IController controller, bool cache = false)
{
return new Bk2InputDisplayGenerator(_emulator.SystemId, controller).Generate();
var idg = controller.InputDisplayGenerator;
if (idg is null)
{
idg = new Bk2InputDisplayGenerator(_emulator.SystemId, controller);
if (cache) controller.InputDisplayGenerator = idg;
}
return idg.Generate();
}
public string MakeIntersectImmediatePrevious()
@ -300,7 +306,8 @@ namespace BizHawk.Client.Common
// basically we're tinting whatever is pressed because it's sticky specially
// in order to achieve this we want to avoid drawing anything pink that isn't actually held down right now
// so we make an AND adapter and combine it using immediate & sticky
var autoString = MakeStringFor(_inputManager.StickyXorAdapter.Source.Xor(_inputManager.AutofireStickyXorAdapter).And(_inputManager.AutofireStickyXorAdapter));
// (adapter creation moved to InputManager)
var autoString = MakeStringFor(_inputManager.WeirdStickyControllerForInputDisplay, cache: true);
g.DrawString(autoString, MessageFont, autoColor, point.X, point.Y);
//recolor everything that's changed from the previous input

View File

@ -9,6 +9,8 @@ namespace BizHawk.Client.Common
{
public class AutofireController : IController
{
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public AutofireController(IEmulator emulator, int on, int off)
{
On = on < 1 ? 0 : on;

View File

@ -15,6 +15,8 @@ namespace BizHawk.Client.Common
public ControllerDefinition Definition { get; set; }
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button) => _pressed.Contains(button);
public int AxisValue(string name) => 0;

View File

@ -13,6 +13,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition { get; }
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
protected WorkingDictionary<string, bool> Buttons { get; private set; } = new WorkingDictionary<string, bool>();
protected WorkingDictionary<string, int> Axes { get; private set; } = new WorkingDictionary<string, int>();
protected WorkingDictionary<string, int> HapticFeedback { get; private set; } = new WorkingDictionary<string, int>();

View File

@ -4,19 +4,11 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
public interface IInputDisplayGenerator
{
/// <summary>
/// Generates a display friendly version of the input log entry
/// </summary>
string Generate();
}
/// <summary>
/// An implementation of <see cref="IInputDisplayGenerator"/> that
/// uses .bk2 mnemonics as the basis for display
/// </summary>
public class Bk2InputDisplayGenerator
public class Bk2InputDisplayGenerator : IInputDisplayGenerator
{
private readonly string _systemId;
private readonly IController _source;

View File

@ -8,6 +8,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition => Source.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button)
{
if (Source != null && SourceAnd != null)
@ -34,6 +36,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition => Source.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button)
{
if (Source != null && SourceXor != null)
@ -60,6 +64,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition => Source.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button)
{
return (Source?.IsPressed(button) ?? false)

View File

@ -11,6 +11,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition => Curr.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button) => Curr.IsPressed(button);
public int AxisValue(string name) => Curr.AxisValue(name);

View File

@ -24,13 +24,15 @@ namespace BizHawk.Client.Common
private UdlrControllerAdapter UdLRControllerAdapter { get; } = new UdlrControllerAdapter();
public AutoFireStickyXorAdapter AutofireStickyXorAdapter { get; } = new AutoFireStickyXorAdapter();
public AutoFireStickyXorAdapter AutofireStickyXorAdapter { get; private set; } = new AutoFireStickyXorAdapter();
/// <summary>
/// provides an opportunity to mutate the player's input in an autohold style
/// </summary>
public StickyXorAdapter StickyXorAdapter { get; } = new StickyXorAdapter();
public IController WeirdStickyControllerForInputDisplay { get; private set; }
/// <summary>
/// Used to AND to another controller, used for <see cref="IJoypadApi.Set(IReadOnlyDictionary{string, bool}, int?)">JoypadApi.Set</see>
/// </summary>
@ -72,8 +74,10 @@ namespace BizHawk.Client.Common
UdLRControllerAdapter.Source = ActiveController.Or(AutoFireController);
UdLRControllerAdapter.AllowUdlr = config.AllowUdlr;
// these are all reference types which don't change so this SHOULD be a no-op, but I'm not brave enough to move it to the ctor --yoshi
StickyXorAdapter.Source = UdLRControllerAdapter;
AutofireStickyXorAdapter.Source = StickyXorAdapter;
AutofireStickyXorAdapter = new() { Source = StickyXorAdapter };
WeirdStickyControllerForInputDisplay = StickyXorAdapter.Source.Xor(AutofireStickyXorAdapter).And(AutofireStickyXorAdapter);
session.MovieIn = AutofireStickyXorAdapter;
session.StickySource = AutofireStickyXorAdapter;

View File

@ -13,6 +13,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition { get; private set; }
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
private readonly Dictionary<string, bool> _overrides = new Dictionary<string, bool>();
private readonly Dictionary<string, int> _axisOverrides = new Dictionary<string, int>();
private readonly List<string> _inverses = new List<string>();

View File

@ -15,6 +15,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition => Source.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button)
{
var source = Source.IsPressed(button);
@ -115,6 +117,8 @@ namespace BizHawk.Client.Common
{
public ControllerDefinition Definition => Source.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button)
{
var source = Source.IsPressed(button);

View File

@ -15,6 +15,8 @@ namespace BizHawk.Client.Common
public ControllerDefinition Definition => Source.Definition;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool AllowUdlr { get; set; }
public bool IsPressed(string button)

View File

@ -25,6 +25,8 @@ namespace BizHawk.Client.Common
})
.ToList();
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public Bk2Controller(string key, ControllerDefinition definition) : this(definition)
{
if (!string.IsNullOrEmpty(key))

View File

@ -8,6 +8,8 @@ namespace BizHawk.Client.Common
{
internal class BkmControllerAdapter : IController
{
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public BkmControllerAdapter(ControllerDefinition definition, string systemId)
{
// We do need to map the definition name to the legacy

View File

@ -14,6 +14,8 @@ namespace BizHawk.Emulation.Common
{
public ControllerDefinition Definition { get; } = new ControllerDefinition("Null Controller").MakeImmutable();
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public bool IsPressed(string button) => false;
public int AxisValue(string name) => 0;

View File

@ -70,6 +70,8 @@ namespace BizHawk.Emulation.Common
private readonly IController _src;
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public DummyController(
IController src,
IReadOnlyDictionary<string, string> buttonAxisRemaps)

View File

@ -11,6 +11,9 @@ namespace BizHawk.Emulation.Common
/// </summary>
ControllerDefinition Definition { get; }
/// <summary>used as cache by frontend; implement as autoprop w/ initial value <see langword="null"/></summary>
IInputDisplayGenerator InputDisplayGenerator { get; set; }
/// <seealso cref="SetHapticChannelStrength"/>
IReadOnlyCollection<(string Name, int Strength)> GetHapticsSnapshot();

View File

@ -0,0 +1,10 @@
namespace BizHawk.Emulation.Common
{
public interface IInputDisplayGenerator
{
/// <summary>
/// Generates a display friendly version of the input log entry
/// </summary>
string Generate();
}
}

View File

@ -16,6 +16,8 @@ namespace BizHawk.Emulation.Common
{
private readonly WorkingDictionary<string, int> _buttons = new WorkingDictionary<string, int>();
public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null;
public SaveController()
{
Definition = null;