TAStudio - better column building and tracking of what has been pressed. Also now allows a variable number of players to be recorded.
This commit is contained in:
parent
0737f884bd
commit
ba2c345608
|
@ -124,7 +124,6 @@
|
|||
<Compile Include="movie\HeaderKeys.cs" />
|
||||
<Compile Include="movie\IMovie.cs" />
|
||||
<Compile Include="movie\IMovieHeader.cs" />
|
||||
<Compile Include="movie\IMovieRecord.cs" />
|
||||
<Compile Include="movie\InputAdapters.cs" />
|
||||
<Compile Include="movie\MnemonicsGenerator.cs" />
|
||||
<Compile Include="movie\Movie.cs" />
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents everything needed for a frame of input
|
||||
/// </summary>
|
||||
public interface IMovieRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the string representation of the controller input as a series of mnemonics
|
||||
/// </summary>
|
||||
string Input { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not this was a lag frame,
|
||||
/// where lag is the act of the core failing to poll for input (input on lag frames have no affect)
|
||||
/// </summary>
|
||||
bool Lagged { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a valude indicating whether or not this record has a captured state
|
||||
/// </summary>
|
||||
bool HasState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Savestate for this frame of input
|
||||
/// </summary>
|
||||
IEnumerable<byte> State { get; }
|
||||
}
|
||||
}
|
|
@ -466,17 +466,130 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public class NewMnemonicsGenerator
|
||||
{
|
||||
public MnemonicLookupTable MnemonicLookup { get; private set; }
|
||||
public IController Source { get; private set; }
|
||||
|
||||
public List<string> ActivePlayers { get; set; }
|
||||
|
||||
public NewMnemonicsGenerator(IController source)
|
||||
{
|
||||
MnemonicLookup = new MnemonicLookupTable();
|
||||
Source = source;
|
||||
ActivePlayers = MnemonicLookup[Global.Emulator.SystemId].Select(x => x.Name).ToList();
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get { return false; } // TODO
|
||||
get
|
||||
{
|
||||
IEnumerable<MnemonicCollection> collections = MnemonicLookup[Global.Emulator.SystemId].Where(x => ActivePlayers.Contains(x.Name));
|
||||
|
||||
foreach (var mc in collections)
|
||||
{
|
||||
foreach (var kvp in mc)
|
||||
{
|
||||
if (Source.IsPressed(kvp.Key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public string EmptyMnemonic
|
||||
{
|
||||
get
|
||||
{
|
||||
return String.Empty; // TODO
|
||||
IEnumerable<MnemonicCollection> collections = MnemonicLookup[Global.Emulator.SystemId].Where(x => ActivePlayers.Contains(x.Name));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append('|');
|
||||
foreach (var mc in collections)
|
||||
{
|
||||
foreach (var kvp in mc)
|
||||
{
|
||||
sb.Append('.');
|
||||
}
|
||||
sb.Append('|');
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public string MnemonicString
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<MnemonicCollection> collections = MnemonicLookup[Global.Emulator.SystemId].Where(x => ActivePlayers.Contains(x.Name));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append('|');
|
||||
foreach (var mc in collections)
|
||||
{
|
||||
foreach(var kvp in mc)
|
||||
{
|
||||
sb.Append(Source.IsPressed(kvp.Key) ? kvp.Value : '.');
|
||||
}
|
||||
sb.Append('|');
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<char> Mnemonics
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<MnemonicCollection> collections = MnemonicLookup[Global.Emulator.SystemId].Where(x => ActivePlayers.Contains(x.Name));
|
||||
|
||||
List<char> mnemonics = new List<char>();
|
||||
foreach (var mc in collections)
|
||||
{
|
||||
mnemonics.AddRange(mc.Select(x => x.Value));
|
||||
}
|
||||
|
||||
return mnemonics;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, char> AvailableMnemonics
|
||||
{
|
||||
get
|
||||
{
|
||||
var buttons = new Dictionary<string, char>();
|
||||
IEnumerable<MnemonicCollection> collections = MnemonicLookup[Global.Emulator.SystemId].Where(x => ActivePlayers.Contains(x.Name));
|
||||
|
||||
foreach (var mc in collections)
|
||||
{
|
||||
foreach (var kvp in mc)
|
||||
{
|
||||
buttons.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, bool> GetBoolButtons()
|
||||
{
|
||||
var buttons = new Dictionary<string, bool>();
|
||||
IEnumerable<MnemonicCollection> collections = MnemonicLookup[Global.Emulator.SystemId].Where(x => ActivePlayers.Contains(x.Name));
|
||||
|
||||
foreach (var mc in collections)
|
||||
{
|
||||
foreach (var kvp in mc)
|
||||
{
|
||||
buttons.Add(kvp.Key, Source.IsPressed(kvp.Key));
|
||||
}
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,25 +7,48 @@ using BizHawk.Emulation.Common;
|
|||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public class MovieRecord : IMovieRecord
|
||||
public class MovieRecord
|
||||
{
|
||||
Dictionary<string, bool> BoolButtons = new Dictionary<string, bool>();
|
||||
// TODO: pass in ActivePlayers
|
||||
// TODO: pass in IController source, probably wasteful though
|
||||
|
||||
private NewMnemonicsGenerator _mg;
|
||||
private Dictionary<string, bool> _boolButtons = new Dictionary<string, bool>();
|
||||
private byte[] _state;
|
||||
|
||||
public MovieRecord()
|
||||
{
|
||||
_mg = new NewMnemonicsGenerator(Global.MovieOutputHardpoint);
|
||||
}
|
||||
|
||||
public MovieRecord(IController source, bool captureState)
|
||||
{
|
||||
_mg = new NewMnemonicsGenerator(source);
|
||||
SetInput();
|
||||
if (captureState)
|
||||
{
|
||||
Lagged = Global.Emulator.IsLagFrame;
|
||||
_state = Global.Emulator.SaveStateBinary();
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> ActivePlayers
|
||||
{
|
||||
get
|
||||
{
|
||||
return _mg.ActivePlayers;
|
||||
}
|
||||
set
|
||||
{
|
||||
_mg.ActivePlayers = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Input
|
||||
{
|
||||
get
|
||||
{
|
||||
SimpleController controller = new SimpleController { Type = new ControllerDefinition() };
|
||||
foreach (var kvp in BoolButtons)
|
||||
{
|
||||
controller["P1 " + kvp.Key] = kvp.Value; // TODO: multi-player, all cores
|
||||
}
|
||||
|
||||
controller.Type.Name = Global.Emulator.ControllerDefinition.Name;
|
||||
MnemonicsGenerator mg = new MnemonicsGenerator();
|
||||
mg.SetSource(controller);
|
||||
return mg.GetControllersAsMnemonic();
|
||||
return _mg.MnemonicString;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,52 +58,31 @@ namespace BizHawk.Client.Common
|
|||
get { return _state; }
|
||||
}
|
||||
|
||||
public bool IsPressed(int player, string mnemonic)
|
||||
public bool IsPressed(string buttonName)
|
||||
{
|
||||
return BoolButtons[mnemonic]; // TODO: player
|
||||
return _boolButtons[buttonName];
|
||||
}
|
||||
|
||||
|
||||
public void SetInput(IController controller)
|
||||
public void SetInput()
|
||||
{
|
||||
var mnemonics = MnemonicConstants.BUTTONS[Global.Emulator.Controller.Type.Name].Select(x => x.Value);
|
||||
foreach (var mnemonic in mnemonics)
|
||||
{
|
||||
BoolButtons[mnemonic] = controller["P1 " + mnemonic]; // TODO: doesn't work on every core, can't do multiplayer
|
||||
}
|
||||
_boolButtons.Clear();
|
||||
_boolButtons = _mg.GetBoolButtons();
|
||||
}
|
||||
|
||||
public void ClearInput()
|
||||
{
|
||||
foreach (var key in BoolButtons.Keys)
|
||||
{
|
||||
BoolButtons[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public MovieRecord(IController controller, bool captureState)
|
||||
{
|
||||
SetInput(controller);
|
||||
|
||||
if (captureState)
|
||||
{
|
||||
Lagged = Global.Emulator.IsLagFrame;
|
||||
_state = Global.Emulator.SaveStateBinary();
|
||||
}
|
||||
_boolButtons.Clear();
|
||||
}
|
||||
|
||||
public bool HasState
|
||||
{
|
||||
get
|
||||
{
|
||||
return State.Count() > 0;
|
||||
}
|
||||
get { return State.Count() > 0; }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//TODO: consider the fileformat of binary and lagged data
|
||||
return Input;
|
||||
return Input; // TODO: consider the fileformat of binary and lagged data
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace BizHawk.Client.Common
|
|||
// TODO: preloading, or benchmark and see how much of a performaance gain it really is
|
||||
// TODO: support loop Offset
|
||||
|
||||
private IController _source = Global.MovieOutputHardpoint; //TODO: don't do it this way;
|
||||
|
||||
public MovieRecord this[int index]
|
||||
{
|
||||
get
|
||||
|
@ -21,6 +23,18 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
|
||||
public List<string> ActivePlayers { get; set; }
|
||||
|
||||
public Dictionary<string, char> AvailableMnemonics
|
||||
{
|
||||
get
|
||||
{
|
||||
NewMnemonicsGenerator mg = new NewMnemonicsGenerator(_source);
|
||||
mg.ActivePlayers = ActivePlayers;
|
||||
return mg.AvailableMnemonics;
|
||||
}
|
||||
}
|
||||
|
||||
#region Implementation
|
||||
|
||||
public TasMovie(string filename, bool startsFromSavestate = false)
|
||||
|
@ -199,7 +213,7 @@ namespace BizHawk.Client.Common
|
|||
if (frame < _records.Count)
|
||||
{
|
||||
Changes = true;
|
||||
_records[frame].SetInput(source);
|
||||
_records[frame].SetInput();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -649,8 +649,9 @@ namespace BizHawk.Client.EmuHawk
|
|||
//
|
||||
// TASView
|
||||
//
|
||||
this.TASView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.TASView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.TASView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.Frame,
|
||||
this.Log});
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
public partial class TAStudio : Form, IToolForm
|
||||
{
|
||||
private const string MarkerColumn = "";
|
||||
private const string FrameColumn = "Frame#";
|
||||
private const string MarkerColumnName = "MarkerColumn";
|
||||
private const string FrameColumnName = "FrameColumn";
|
||||
|
||||
private int _defaultWidth;
|
||||
private int _defaultHeight;
|
||||
|
@ -98,23 +98,24 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
text = String.Empty;
|
||||
var columnName = TASView.Columns[column].Name;
|
||||
var columnText = TASView.Columns[column].Text;
|
||||
|
||||
if (columnName == MarkerColumn)
|
||||
if (columnName == MarkerColumnName)
|
||||
{
|
||||
text = "X";
|
||||
text = "";
|
||||
}
|
||||
else if (columnName == FrameColumn)
|
||||
else if (columnName == FrameColumnName)
|
||||
{
|
||||
text = index.ToString().PadLeft(5, '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
text = _tas[index].IsPressed(1, columnName) ? columnName : String.Empty;
|
||||
text = _tas[index].IsPressed(columnName) ? columnText : String.Empty;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
text = "";
|
||||
text = String.Empty;
|
||||
MessageBox.Show("oops\n" + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
@ -138,20 +139,37 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
LoadConfigSettings();
|
||||
|
||||
|
||||
_tas.ActivePlayers = new List<string> { "Player 1", "Player 2" };
|
||||
SetUpColumns();
|
||||
}
|
||||
|
||||
private void SetUpColumns()
|
||||
{
|
||||
TASView.Columns.Clear();
|
||||
ToolHelpers.AddColumn(TASView, "", true, 18);
|
||||
ToolHelpers.AddColumn(TASView, "Frame#", true, 68);
|
||||
AddColumn(MarkerColumnName, "", 18);
|
||||
AddColumn(FrameColumnName, "Frame#", 68);
|
||||
|
||||
var mnemonics = MnemonicConstants.BUTTONS[Global.Emulator.Controller.Type.Name].Select(x => x.Value);
|
||||
|
||||
foreach (var mnemonic in mnemonics)
|
||||
foreach(var kvp in _tas.AvailableMnemonics)
|
||||
{
|
||||
ToolHelpers.AddColumn(TASView, mnemonic, true, 20);
|
||||
AddColumn(kvp.Key, kvp.Value.ToString(), 20);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddColumn(string columnName, string columnText, int columnWidth)
|
||||
{
|
||||
if (TASView.Columns[columnName] == null)
|
||||
{
|
||||
var column = new ColumnHeader
|
||||
{
|
||||
Name = columnName,
|
||||
Text = columnText,
|
||||
Width = columnWidth,
|
||||
};
|
||||
|
||||
TASView.Columns.Add(column);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue