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:
adelikat 2013-12-07 17:29:47 +00:00
parent 0737f884bd
commit ba2c345608
7 changed files with 205 additions and 89 deletions

View File

@ -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" />

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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
}
}

View File

@ -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();
}
}

View File

@ -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});

View File

@ -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);
}
}