refactor IMovieController

This commit is contained in:
adelikat 2020-04-14 19:05:17 -05:00
parent 27605f4828
commit 13e58cbac5
14 changed files with 150 additions and 161 deletions

View File

@ -31,7 +31,7 @@ namespace BizHawk.Client.Common
var lg = Global.MovieSession.MovieControllerInstance();
try
{
lg.SetControllersAsMnemonic(inputLogEntry);
lg.SetFromMnemonic(inputLogEntry);
}
catch (Exception)
{

View File

@ -6,7 +6,12 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
public class StickyXorAdapter : IController
public interface IStickyController : IController
{
bool IsSticky(string button);
}
public class StickyXorAdapter : IStickyController
{
public ControllerDefinition Definition => Source.Definition;
@ -102,7 +107,7 @@ namespace BizHawk.Client.Common
}
}
public class AutoFireStickyXorAdapter : IController
public class AutoFireStickyXorAdapter : IStickyController
{
public ControllerDefinition Definition => Source.Definition;

View File

@ -115,16 +115,16 @@ namespace BizHawk.Client.Common
if (Movie.InputLogLength > Global.Emulator.Frame)
{
var input = Movie.GetInputState(Global.Emulator.Frame);
MovieControllerAdapter.LatchFromSource(input);
MovieControllerAdapter.LatchFrom(input);
}
MovieControllerAdapter.LatchPlayerFromSource(rewiredSource, MultiTrack.CurrentPlayer);
MovieControllerAdapter.LatchPlayerFrom(rewiredSource, MultiTrack.CurrentPlayer);
}
}
public void LatchInputFromPlayer(IController source)
{
MovieControllerAdapter.LatchFromSource(source);
MovieControllerAdapter.LatchFrom(source);
}
/// <summary>
@ -146,7 +146,7 @@ namespace BizHawk.Client.Common
return;
}
MovieControllerAdapter.LatchFromSource(input);
MovieControllerAdapter.LatchFrom(input);
if (MultiTrack.IsActive)
{
Global.InputManager.MultitrackRewiringAdapter.Source = MovieControllerAdapter;
@ -301,7 +301,7 @@ namespace BizHawk.Client.Common
// we don't want TasMovie to latch user input outside its internal recording mode, so limit it to autohold
if (Movie is TasMovie && Movie.IsPlaying())
{
MovieControllerAdapter.LatchSticky();
MovieControllerAdapter.LatchFromSticky(Global.InputManager.AutofireStickyXorAdapter);
}
else
{

View File

@ -7,75 +7,27 @@ using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
public class Bk2ControllerAdapter : IMovieController
public class Bk2Controller : IMovieController
{
private class ControlMap
{
public string Name { get; set; }
public bool IsBool { get; set; }
public bool IsAxis { get; set; }
}
private List<ControlMap> _controlsOrdered = new List<ControlMap>();
private readonly string _logKey = "";
private readonly WorkingDictionary<string, bool> _myBoolButtons = new WorkingDictionary<string, bool>();
private readonly WorkingDictionary<string, float> _myAxisControls = new WorkingDictionary<string, float>();
public Bk2ControllerAdapter()
private Bk2ControllerDefinition _type = new Bk2ControllerDefinition();
private List<ControlMap> _controlsOrdered = new List<ControlMap>();
public Bk2Controller()
{
}
public Bk2ControllerAdapter(string key)
public Bk2Controller(string key)
{
_logKey = key;
SetLogOverride();
}
private void SetLogOverride()
{
if (!string.IsNullOrEmpty(_logKey))
{
var groups = _logKey.Split(new[] { "#" }, StringSplitOptions.RemoveEmptyEntries);
var controls = groups
.Select(group => group.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).ToList())
.ToList();
_type.ControlsFromLog = controls;
}
}
// TODO: get rid of this, add a SetBool() method or something for the set access, replace get with IsPressed
public bool this[string button]
{
get => _myBoolButtons[button];
set
{
if (_myBoolButtons.ContainsKey(button))
{
_myBoolButtons[button] = value;
}
}
}
#region IController Implementation
public bool IsPressed(string button)
{
return _myBoolButtons[button];
}
public float AxisValue(string name)
{
return _myAxisControls[name];
}
#endregion
#region IMovieController Implementation
private Bk2ControllerDefinition _type = new Bk2ControllerDefinition();
public ControllerDefinition Definition
{
get => _type;
@ -97,43 +49,14 @@ namespace BizHawk.Client.Common
}
}
/// <summary>
/// latches one player from the source
/// </summary>
public void LatchPlayerFromSource(IController playerSource, int playerNum)
{
foreach (var button in playerSource.Definition.BoolButtons)
{
var bnp = ButtonNameParser.Parse(button);
public bool IsPressed(string button) => _myBoolButtons[button];
public float AxisValue(string name) => _myAxisControls[name];
if (bnp?.PlayerNum != playerNum)
{
continue;
}
#endregion
var val = playerSource.IsPressed(button);
_myBoolButtons[button] = val;
}
#region IMovieController Implementation
foreach (var button in Definition.AxisControls)
{
var bnp = ButtonNameParser.Parse(button);
if (bnp?.PlayerNum != playerNum)
{
continue;
}
var val = playerSource.AxisValue(button);
_myAxisControls[button] = val;
}
}
/// <summary>
/// latches all buttons from the provided source
/// </summary>
public void LatchFromSource(IController source)
public void LatchFrom(IController source)
{
foreach (var button in Definition.BoolButtons)
{
@ -146,14 +69,41 @@ namespace BizHawk.Client.Common
}
}
/// <summary>
/// latches sticky buttons from <see cref="AutoFireStickyXorAdapter"/>
/// </summary>
public void LatchSticky()
public void LatchPlayerFrom(IController playerSource, int controllerNum)
{
foreach (var button in playerSource.Definition.BoolButtons)
{
var bnp = ButtonNameParser.Parse(button);
if (bnp?.PlayerNum != controllerNum)
{
continue;
}
var val = playerSource.IsPressed(button);
_myBoolButtons[button] = val;
}
foreach (var button in Definition.AxisControls)
{
var bnp = ButtonNameParser.Parse(button);
if (bnp?.PlayerNum != controllerNum)
{
continue;
}
var val = playerSource.AxisValue(button);
_myAxisControls[button] = val;
}
}
public void LatchFromSticky(IStickyController controller)
{
foreach (var button in Definition.BoolButtons)
{
_myBoolButtons[button] = Global.InputManager.AutofireStickyXorAdapter.IsSticky(button);
_myBoolButtons[button] = controller.IsSticky(button);
}
// float controls don't have sticky logic, so latch default value
@ -163,10 +113,7 @@ namespace BizHawk.Client.Common
}
}
/// <summary>
/// latches all buttons from the supplied mnemonic string
/// </summary>
public void SetControllersAsMnemonic(string mnemonic)
public void SetFromMnemonic(string mnemonic)
{
if (!string.IsNullOrWhiteSpace(mnemonic))
{
@ -193,14 +140,39 @@ namespace BizHawk.Client.Common
}
}
#endregion
public void SetBool(string buttonName, bool value)
{
_myBoolButtons[buttonName] = value;
}
public void SetAxis(string buttonName, float value)
{
_myAxisControls[buttonName] = value;
}
public class Bk2ControllerDefinition : ControllerDefinition
#endregion
private void SetLogOverride()
{
if (!string.IsNullOrEmpty(_logKey))
{
var groups = _logKey.Split(new[] { "#" }, StringSplitOptions.RemoveEmptyEntries);
var controls = groups
.Select(group => group.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).ToList())
.ToList();
_type.ControlsFromLog = controls;
}
}
private class ControlMap
{
public string Name { get; set; }
public bool IsBool { get; set; }
public bool IsAxis { get; set; }
}
private class Bk2ControllerDefinition : ControllerDefinition
{
public Bk2ControllerDefinition()
{

View File

@ -16,7 +16,7 @@ namespace BizHawk.Client.Common
_logKey = logKey;
}
public IMovieController MovieControllerAdapter => new Bk2ControllerAdapter(_logKey);
public IMovieController MovieControllerAdapter => new Bk2Controller(_logKey);
public void SetSource(IController source) => _source = source;

View File

@ -6,7 +6,7 @@ namespace BizHawk.Client.Common
{
public partial class Bk2Movie : IMovie
{
private Bk2ControllerAdapter _adapter;
private Bk2Controller _adapter;
public Bk2Movie(string filename = null)
{
@ -121,11 +121,11 @@ namespace BizHawk.Client.Common
}
}
public virtual IController GetInputState(int frame)
public IMovieController GetInputState(int frame)
{
if (frame < FrameCount && frame >= 0)
{
_adapter ??= new Bk2ControllerAdapter
_adapter ??= new Bk2Controller
{
Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
@ -148,7 +148,7 @@ namespace BizHawk.Client.Common
getFrame = frame;
}
_adapter.SetControllersAsMnemonic(Log[getFrame]);
_adapter.SetFromMnemonic(Log[getFrame]);
return _adapter;
}

View File

@ -239,7 +239,7 @@ namespace BizHawk.Client.Common
/// </summary>
/// <param name="frame">The frame of input to be retrieved</param>
/// <returns>A controller state representing the specified frame of input, if frame is out of range, will return null</returns>
IController GetInputState(int frame);
IMovieController GetInputState(int frame);
#endregion
}

View File

@ -6,17 +6,35 @@ namespace BizHawk.Client.Common
{
new ControllerDefinition Definition { get; set; }
void LatchPlayerFromSource(IController playerSource, int playerNum);
void LatchFromSource(IController source);
/// <summary>
/// Latches to the given <see cref="IController" />
/// </summary>
void LatchFrom(IController source);
/// <summary>
/// Used by tastudio when it appends new frames in HandleMovieAfterFrameLoop() and ExtendMovieForEdit().
/// For buttons it latches autohold state, for analogs it latches mid value.
/// All real user input latched by LatchFromPhysical() is ignored.
/// Latches to only the buttons in the given <see cref="IController" /> for the given controller
/// </summary>
void LatchSticky();
void LatchPlayerFrom(IController playerSource, int controllerNum);
void SetControllersAsMnemonic(string mnemonic);
/// <summary>
/// Latches to the given <see cref="IStickyController" />
/// For buttons it latches autohold state, for analogs it latches mid value.
/// </summary>
void LatchFromSticky(IStickyController controller);
/// <summary>
/// Sets the controller to the state represented by the given mnemonic string
/// </summary>
void SetFromMnemonic(string mnemonic);
/// <summary>
/// Sets the given boolean button to the given value
/// </summary>
void SetBool(string buttonName, bool value);
/// <summary>
/// Sets the given axis button to the given value
/// </summary>
void SetAxis(string buttonName, float value);
}
}

View File

@ -393,7 +393,7 @@ namespace BizHawk.Client.Common
int oldLength = InputLogLength;
ChangeLog.AddGeneralUndo(oldLength, oldLength + numFrames - 1);
Global.MovieSession.MovieControllerAdapter.LatchSticky();
Global.MovieSession.MovieControllerAdapter.LatchFromSticky(Global.InputManager.AutofireStickyXorAdapter);
var lg = LogGeneratorInstance();
lg.SetSource(Global.InputManager.MovieOutputHardpoint); // account for autohold. needs autohold pattern to be already recorded in the current frame
@ -419,8 +419,8 @@ namespace BizHawk.Client.Common
ExtendMovieForEdit(frame - Log.Count + 1);
}
var adapter = GetInputState(frame) as Bk2ControllerAdapter;
adapter[buttonName] = !adapter.IsPressed(buttonName);
var adapter = GetInputState(frame);
adapter.SetBool(buttonName, !adapter.IsPressed(buttonName));
var lg = LogGeneratorInstance();
lg.SetSource(adapter);
@ -438,9 +438,9 @@ namespace BizHawk.Client.Common
ExtendMovieForEdit(frame - Log.Count + 1);
}
var adapter = GetInputState(frame) as Bk2ControllerAdapter;
var adapter = GetInputState(frame);
var old = adapter.IsPressed(buttonName);
adapter[buttonName] = val;
adapter.SetBool(buttonName, val);
var lg = LogGeneratorInstance();
lg.SetSource(adapter);
@ -466,9 +466,9 @@ namespace BizHawk.Client.Common
int changed = -1;
for (int i = 0; i < count; i++)
{
var adapter = GetInputState(frame + i) as Bk2ControllerAdapter;
var adapter = GetInputState(frame + i);
bool old = adapter.IsPressed(buttonName);
adapter[buttonName] = val;
adapter.SetBool(buttonName, val);
var lg = LogGeneratorInstance();
lg.SetSource(adapter);
@ -496,7 +496,7 @@ namespace BizHawk.Client.Common
ExtendMovieForEdit(frame - Log.Count + 1);
}
var adapter = GetInputState(frame) as Bk2ControllerAdapter;
var adapter = GetInputState(frame);
var old = adapter.AxisValue(buttonName);
adapter.SetAxis(buttonName, val);
@ -524,7 +524,7 @@ namespace BizHawk.Client.Common
int changed = -1;
for (int i = 0; i < count; i++)
{
var adapter = GetInputState(frame + i) as Bk2ControllerAdapter;
var adapter = GetInputState(frame + i);
float old = adapter.AxisValue(buttonName);
adapter.SetAxis(buttonName, val);

View File

@ -110,16 +110,10 @@ namespace BizHawk.Client.Common
}
public bool BoolIsPressed(int frame, string buttonName)
{
return ((Bk2ControllerAdapter)GetInputState(frame))
.IsPressed(buttonName);
}
=> GetInputState(frame).IsPressed(buttonName);
public float GetFloatState(int frame, string buttonName)
{
return ((Bk2ControllerAdapter)GetInputState(frame))
.AxisValue(buttonName);
}
=> GetInputState(frame).AxisValue(buttonName);
public void ClearGreenzone()
{

View File

@ -780,7 +780,7 @@ namespace BizHawk.Client.EmuHawk
{
var logEntry = _bestBotAttempt.Log[index];
var lg = Global.MovieSession.MovieControllerInstance();
lg.SetControllersAsMnemonic(logEntry);
lg.SetFromMnemonic(logEntry);
foreach (var button in lg.Definition.BoolButtons)
{

View File

@ -375,12 +375,12 @@ namespace BizHawk.Client.EmuHawk
var branch = Tastudio.CurrentTasMovie.Branches.FirstOrDefault(b => b.UniqueIdentifier.ToString() == branchId);
if (branch != null && frame < branch.InputLog.Count)
{
var adapter = new Bk2ControllerAdapter
var adapter = new Bk2Controller
{
Definition = Global.MovieSession.MovieControllerAdapter.Definition
};
adapter.SetControllersAsMnemonic(branch.InputLog[frame]);
adapter.SetFromMnemonic(branch.InputLog[frame]);
foreach (var button in adapter.Definition.BoolButtons)
{

View File

@ -12,9 +12,9 @@ namespace BizHawk.Client.EmuHawk
private readonly IEmulator _emulator;
private readonly ToolManager _tools;
private readonly string[] _log;
private readonly Bk2ControllerAdapter _targetController;
private readonly Bk2Controller _targetController;
private string _inputKey;
private Bk2ControllerAdapter _controller;
private Bk2Controller _controller;
public MovieZone(IMovie movie, IEmulator emulator, ToolManager tools, int start, int length, string key = "")
{
@ -22,8 +22,8 @@ namespace BizHawk.Client.EmuHawk
_tools = tools;
var lg = movie.LogGeneratorInstance();
lg.SetSource(Global.MovieSession.MovieControllerAdapter);
_targetController = new Bk2ControllerAdapter { Definition = _emulator.ControllerDefinition };
_targetController.LatchFromSource(_targetController); // Reference and create all buttons
_targetController = new Bk2Controller { Definition = _emulator.ControllerDefinition };
_targetController.LatchFrom(_targetController); // Reference and create all buttons
if (key == "")
{
@ -54,7 +54,7 @@ namespace BizHawk.Client.EmuHawk
}
}
_controller = new Bk2ControllerAdapter { Definition = d };
_controller = new Bk2Controller { Definition = d };
var logGenerator = new Bk2LogEntryGenerator("");
logGenerator.SetSource(_controller);
logGenerator.GenerateLogEntry(); // Reference and create all buttons.
@ -72,7 +72,7 @@ namespace BizHawk.Client.EmuHawk
{
for (int i = 0; i < length; i++)
{
_controller.LatchFromSource(movie.GetInputState(i + start));
_controller.LatchFrom(movie.GetInputState(i + start));
_log[i] = logGenerator.GenerateLogEntry();
}
}
@ -108,7 +108,7 @@ namespace BizHawk.Client.EmuHawk
}
}
var newController = new Bk2ControllerAdapter { Definition = d };
var newController = new Bk2Controller { Definition = d };
var logGenerator = new Bk2LogEntryGenerator("");
logGenerator.SetSource(newController);
@ -117,12 +117,12 @@ namespace BizHawk.Client.EmuHawk
// Reset all buttons in targetController (it may still have buttons that aren't being set here set true)
var tC = new Bk2LogEntryGenerator("");
tC.SetSource(_targetController);
_targetController.SetControllersAsMnemonic(tC.EmptyEntry);
_targetController.SetFromMnemonic(tC.EmptyEntry);
for (int i = 0; i < Length; i++)
{
_controller.SetControllersAsMnemonic(_log[i]);
_controller.SetFromMnemonic(_log[i]);
LatchFromSourceButtons(_targetController, _controller);
newController.LatchFromSource(_targetController);
newController.LatchFrom(_targetController);
_log[i] = logGenerator.GenerateLogEntry();
}
@ -151,7 +151,7 @@ namespace BizHawk.Client.EmuHawk
{
for (int i = 0; i < Length; i++)
{ // Overlay the frames.
_controller.SetControllersAsMnemonic(_log[i]);
_controller.SetFromMnemonic(_log[i]);
LatchFromSourceButtons(_targetController, _controller);
ORLatchFromSource(_targetController, movie.GetInputState(i + Start));
movie.PokeFrame(i + Start, _targetController);
@ -161,7 +161,7 @@ namespace BizHawk.Client.EmuHawk
{
for (int i = 0; i < Length; i++)
{ // Copy over the frame.
_controller.SetControllersAsMnemonic(_log[i]);
_controller.SetFromMnemonic(_log[i]);
LatchFromSourceButtons(_targetController, _controller);
movie.PokeFrame(i + Start, _targetController);
}
@ -257,8 +257,8 @@ namespace BizHawk.Client.EmuHawk
Name = Path.GetFileNameWithoutExtension(fileName);
// Adapters
_targetController = new Bk2ControllerAdapter { Definition = _emulator.ControllerDefinition };
_targetController.LatchFromSource(_targetController); // Reference and create all buttons
_targetController = new Bk2Controller { Definition = _emulator.ControllerDefinition };
_targetController.LatchFrom(_targetController); // Reference and create all buttons
string[] keys = _inputKey.Split('|');
var d = new ControllerDefinition();
foreach (var k in keys)
@ -273,16 +273,16 @@ namespace BizHawk.Client.EmuHawk
}
}
_controller = new Bk2ControllerAdapter { Definition = d };
_controller = new Bk2Controller { Definition = d };
}
#region Custom Latch
private void LatchFromSourceButtons(Bk2ControllerAdapter latching, IController source)
private void LatchFromSourceButtons(IMovieController latching, IController source)
{
foreach (string button in source.Definition.BoolButtons)
{
latching[button] = source.IsPressed(button);
latching.SetBool(button, source.IsPressed(button));
}
foreach (string name in source.Definition.AxisControls)
@ -291,11 +291,11 @@ namespace BizHawk.Client.EmuHawk
}
}
private void ORLatchFromSource(Bk2ControllerAdapter latching, IController source)
private void ORLatchFromSource(IMovieController latching, IController source)
{
foreach (string button in latching.Definition.BoolButtons)
{
latching[button] |= source.IsPressed(button);
latching.SetBool(button, latching.IsPressed(button) | source.IsPressed(button));
}
foreach (string name in latching.Definition.AxisControls)

View File

@ -28,7 +28,7 @@ namespace BizHawk.Client.EmuHawk
try
{
var lg = Global.MovieSession.MovieControllerInstance();
lg.SetControllersAsMnemonic(inputLogEntry);
lg.SetFromMnemonic(inputLogEntry);
foreach (var button in lg.Definition.BoolButtons)
{