diff --git a/BizHawk.Client.Common/FilesystemFilter.cs b/BizHawk.Client.Common/FilesystemFilter.cs index 438be7c373..ee394c3478 100644 --- a/BizHawk.Client.Common/FilesystemFilter.cs +++ b/BizHawk.Client.Common/FilesystemFilter.cs @@ -51,7 +51,7 @@ namespace BizHawk.Client.Common public static readonly FilesystemFilter Archives = new FilesystemFilter("Archives", ArchiveExtensions); - public static readonly FilesystemFilter BizHawkMovies = new FilesystemFilter("Movie Files", new[] { MovieService.DefaultExtension }); + public static readonly FilesystemFilter BizHawkMovies = new FilesystemFilter("Movie Files", new[] { MovieService.StandardMovieExtension }); public static readonly FilesystemFilter EmuHawkSaveStates = new FilesystemFilter("Save States", new[] { "State" }); @@ -61,7 +61,7 @@ namespace BizHawk.Client.Common public static readonly FilesystemFilter PNGs = new FilesystemFilter("PNG Files", new[] { "png" }); - public static readonly FilesystemFilter TAStudioProjects = new FilesystemFilter("TAS Project Files", new[] { TasMovie.Extension }); + public static readonly FilesystemFilter TAStudioProjects = new FilesystemFilter("TAS Project Files", new[] { MovieService.TasMovieExtension }); public static readonly FilesystemFilter TextFiles = new FilesystemFilter("Text Files", new[] { "txt" }); diff --git a/BizHawk.Client.Common/SavestateManager.cs b/BizHawk.Client.Common/SavestateManager.cs index 0e1a96d99c..dd0d40f8c8 100644 --- a/BizHawk.Client.Common/SavestateManager.cs +++ b/BizHawk.Client.Common/SavestateManager.cs @@ -90,7 +90,7 @@ namespace BizHawk.Client.Common bs.PutLump(BinaryStateLump.LagLog, delegate(TextWriter tw) { - ((TasMovie)Global.MovieSession.Movie).TasLagLog.Save(tw); + ((TasMovie)Global.MovieSession.Movie).LagLog.Save(tw); }); } } @@ -187,7 +187,7 @@ namespace BizHawk.Client.Common { bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { - ((TasMovie)Global.MovieSession.Movie).TasLagLog.Load(tr); + ((TasMovie)Global.MovieSession.Movie).LagLog.Load(tr); }); } } diff --git a/BizHawk.Client.Common/movie/MovieService.cs b/BizHawk.Client.Common/movie/MovieService.cs index d94e8e6c99..bb2c5207b1 100644 --- a/BizHawk.Client.Common/movie/MovieService.cs +++ b/BizHawk.Client.Common/movie/MovieService.cs @@ -18,24 +18,30 @@ namespace BizHawk.Client.Common } /// - /// Gets the file extension for the default movie implementation used in the client + /// Creates a standard instance, + /// no path is specified so this is in a minimal state that would not be able to be saved /// - public const string DefaultExtension = "bk2"; + public static IMovie Create() => new Bk2Movie(); + + /// + /// Creates a instance + /// + public static ITasMovie CreateTas(bool startsFromSavestate = false) + { + return new TasMovie(startsFromSavestate: startsFromSavestate); + } + + public static string StandardMovieExtension => Bk2Movie.Extension; + public static string TasMovieExtension => TasMovie.Extension; /// /// Gets a list of extensions for all implementations /// - public static IEnumerable MovieExtensions => new[] { DefaultExtension, TasMovie.Extension }; + public static IEnumerable MovieExtensions => new[] { Bk2Movie.Extension, TasMovie.Extension }; public static bool IsValidMovieExtension(string ext) { return MovieExtensions.Contains(ext.ToLower().Replace(".", "")); } - - /// - /// Creates a default instance of the default implementation, - /// no path is specified so this is in a minimal state that would not be able to be saved - /// - public static IMovie DefaultInstance => new Bk2Movie(); } } diff --git a/BizHawk.Client.Common/movie/MovieSession.cs b/BizHawk.Client.Common/movie/MovieSession.cs index 8d31dfde28..9c71eb351e 100644 --- a/BizHawk.Client.Common/movie/MovieSession.cs +++ b/BizHawk.Client.Common/movie/MovieSession.cs @@ -35,7 +35,7 @@ namespace BizHawk.Client.Common _modeChangedCallback = modeChangedCallback ?? throw new ArgumentNullException($"{nameof(modeChangedCallback)} CannotUnloadAppDomainException be null."); - Movie = MovieService.DefaultInstance; + Movie = MovieService.Create(); } public IMovie Movie { get; private set; } @@ -146,7 +146,7 @@ namespace BizHawk.Client.Common public void HandleFrameAfter() { - if (Movie is TasMovie tasMovie) + if (Movie is ITasMovie tasMovie) { tasMovie.GreenzoneCurrentFrame(); if (tasMovie.IsPlaying() && Global.Emulator.Frame >= tasMovie.InputLogLength) @@ -352,7 +352,7 @@ namespace BizHawk.Client.Common MultiTrack.Restart(Global.Emulator.ControllerDefinition.PlayerCount); _modeChangedCallback(); - Movie = MovieService.DefaultInstance; + Movie = MovieService.Create(); } public void ConvertToTasProj() @@ -471,7 +471,7 @@ namespace BizHawk.Client.Common private void HandleFrameLoopForRecordMode() { // 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()) + if (Movie is ITasMovie && Movie.IsPlaying()) { MovieController.SetFromSticky(Global.InputManager.AutofireStickyXorAdapter); } diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs index cc115feb18..02f9b0046a 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.HeaderApi.cs @@ -3,7 +3,7 @@ using System.Text; namespace BizHawk.Client.Common { - public partial class Bk2Movie + internal partial class Bk2Movie { protected readonly Bk2Header Header = new Bk2Header(); private string _syncSettingsJson = ""; diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs index 94bc788293..bedc700e82 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs @@ -6,7 +6,7 @@ using BizHawk.Common.IOExtensions; namespace BizHawk.Client.Common { - public partial class Bk2Movie + internal partial class Bk2Movie { public void Save() { diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs index f40538d299..e72c7e04ee 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs @@ -6,7 +6,7 @@ using BizHawk.Common; namespace BizHawk.Client.Common { - public partial class Bk2Movie + internal partial class Bk2Movie { protected IStringLog Log { get; set; } = StringLogUtil.MakeStringLog(); protected string LogKey { get; set; } = ""; diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.ModeApi.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.ModeApi.cs index e755fcf853..5b5e8fd284 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.ModeApi.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.ModeApi.cs @@ -2,7 +2,7 @@ namespace BizHawk.Client.Common { - public partial class Bk2Movie + internal partial class Bk2Movie { public MovieMode Mode { get; protected set; } = MovieMode.Inactive; diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs index decb6d8d02..2dcee13cef 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.cs @@ -4,7 +4,7 @@ using BizHawk.Emulation.Cores.Nintendo.Gameboy; namespace BizHawk.Client.Common { - public partial class Bk2Movie : IMovie + internal partial class Bk2Movie : IMovie { private Bk2Controller _adapter; diff --git a/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs b/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs index 1e7f997e4a..d6d073f58a 100644 --- a/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs +++ b/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs @@ -15,7 +15,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions { public static class MovieConversionExtensions { - public static TasMovie ToTasMovie(this IMovie old, bool copy = false) + public static ITasMovie ToTasMovie(this IMovie old, bool copy = false) { string newFilename = $"{old.Filename}.{TasMovie.Extension}"; @@ -77,7 +77,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions return tas; } - public static Bk2Movie ToBk2(this IMovie old, bool copy = false, bool backup = false) + public static IMovie ToBk2(this IMovie old, bool copy = false, bool backup = false) { var bk2 = new Bk2Movie(old.Filename.Replace(old.PreferredExtension, Bk2Movie.Extension)); @@ -124,7 +124,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions return bk2; } - public static TasMovie ConvertToSavestateAnchoredMovie(this TasMovie old, int frame, byte[] savestate) + public static ITasMovie ConvertToSavestateAnchoredMovie(this ITasMovie old, int frame, byte[] savestate) { string newFilename = old.Filename; @@ -157,7 +157,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions } var tas = new TasMovie(newFilename, true) { BinarySavestate = savestate }; - tas.ClearLagLog(); + tas.LagLog.Clear(); var entries = old.GetLogEntries(); @@ -170,8 +170,8 @@ namespace BizHawk.Client.Common.MovieConversionExtensions old.TasStateManager.Clear(); // Lag Log - tas.TasLagLog.FromLagLog(old.TasLagLog); - tas.TasLagLog.StartFromFrame(frame); + tas.LagLog.FromLagLog(old.LagLog); + tas.LagLog.StartFromFrame(frame); tas.HeaderEntries.Clear(); foreach (var kvp in old.HeaderEntries) @@ -208,7 +208,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions return tas; } - public static TasMovie ConvertToSaveRamAnchoredMovie(this TasMovie old, byte[] saveRam) + public static ITasMovie ConvertToSaveRamAnchoredMovie(this ITasMovie old, byte[] saveRam) { string newFilename = old.Filename; @@ -242,7 +242,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions var tas = new TasMovie(newFilename, true) { SaveRam = saveRam }; tas.TasStateManager.Clear(); - tas.ClearLagLog(); + tas.LagLog.Clear(); var entries = old.GetLogEntries(); diff --git a/BizHawk.Client.Common/movie/interfaces/IMovie.cs b/BizHawk.Client.Common/movie/interfaces/IMovie.cs index 6ca0e4fa3f..a0faf9ecc9 100644 --- a/BizHawk.Client.Common/movie/interfaces/IMovie.cs +++ b/BizHawk.Client.Common/movie/interfaces/IMovie.cs @@ -48,6 +48,8 @@ namespace BizHawk.Client.Common #region Properties + string Name { get; } + /// /// Gets the total number of frames that count towards the completion time of the movie /// Possibly (but unlikely different from InputLogLength (could be infinity, or maybe an implementation automatically discounts empty frames at the end of a movie, etc) @@ -292,5 +294,11 @@ namespace BizHawk.Client.Common emulator.AsSaveRam().StoreSaveRam(movie.SaveRam); } } + + public static bool BoolIsPressed(this IMovie movie, int frame, string buttonName) + => movie.GetInputState(frame).IsPressed(buttonName); + + public static float GetFloatState(this IMovie movie, int frame, string buttonName) + => movie.GetInputState(frame).AxisValue(buttonName); } } diff --git a/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs b/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs new file mode 100644 index 0000000000..86b5504aa8 --- /dev/null +++ b/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Client.Common +{ + public interface ITasMovie : IMovie, INotifyPropertyChanged + { + bool BindMarkersToInput { get; set; } + bool LastPositionStable { get; set; } + + IMovieChangeLog ChangeLog { get; } + IStateManager TasStateManager { get; } + Func ClientSettingsForSave { set; } + Action GetClientSettingsOnLoad { set; } + ITasMovieRecord this[int index] { get; } + ITasSession Session { get; } + TasMovieMarkerList Markers { get; } + ITasBranchCollection Branches { get; } + TasLagLog LagLog { get; } + IStringLog VerificationLog { get; } + int LastEditedFrame { get; } + + string DisplayValue(int frame, string buttonName); + void FlagChanges(); + void ClearChanges(); + IStringLog GetLogEntries(); + + void GreenzoneCurrentFrame(); + void ToggleBoolState(int frame, string buttonName); + void SetFloatState(int frame, string buttonName, float val); + void SetFloatStates(int frame, int count, string buttonName, float val); + void SetBoolState(int frame, string buttonName, bool val); + void SetBoolStates(int frame, int count, string buttonName, bool val); + void InsertInput(int frame, string inputState); + void InsertInput(int frame, IEnumerable inputLog); + void InsertInput(int frame, IEnumerable inputStates); + + void InsertEmptyFrame(int frame, int count = 1, bool fromHistory = false); + int CopyOverInput(int frame, IEnumerable inputStates); + + void RemoveFrame(int frame); + void RemoveFrames(ICollection frames); + void RemoveFrames(int removeStart, int removeUpTo, bool fromHistory = false); + void SetFrame(int frame, string source); + + void LoadBranch(TasBranch branch); + } +} diff --git a/BizHawk.Client.Common/movie/tasproj/StateManagerDecay.cs b/BizHawk.Client.Common/movie/tasproj/StateManagerDecay.cs index 48a3ad6077..e2cee4bf93 100644 --- a/BizHawk.Client.Common/movie/tasproj/StateManagerDecay.cs +++ b/BizHawk.Client.Common/movie/tasproj/StateManagerDecay.cs @@ -45,7 +45,7 @@ namespace BizHawk.Client.Common // TODO: interface me internal class StateManagerDecay { - private readonly TasMovie _movie; + private readonly ITasMovie _movie; private readonly IStateManager _tsm; private List _zeros; // amount of least significant zeros in bitwise view (also max pattern step) @@ -56,7 +56,7 @@ namespace BizHawk.Client.Common private int _step; // initial memory state gap private bool _align; // extra care about fine alignment. TODO: do we want it? - public StateManagerDecay(TasMovie movie, IStateManager tsm) + public StateManagerDecay(ITasMovie movie, IStateManager tsm) { _movie = movie; _tsm = tsm; diff --git a/BizHawk.Client.Common/movie/tasproj/TasBranch.cs b/BizHawk.Client.Common/movie/tasproj/TasBranch.cs index a9ad7f805a..f2287fed02 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasBranch.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasBranch.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Newtonsoft.Json; using BizHawk.Bizware.BizwareGL; @@ -16,25 +17,95 @@ namespace BizHawk.Client.Common public TasMovieChangeLog ChangeLog { get; set; } public DateTime TimeStamp { get; set; } public TasMovieMarkerList Markers { get; set; } - public Guid UniqueIdentifier { get; set; } + public Guid Uuid { get; set; } public string UserText { get; set; } - public TasBranch Clone() - { - return (TasBranch)MemberwiseClone(); - } + public TasBranch Clone() => (TasBranch)MemberwiseClone(); } - public class TasBranchCollection : List + public interface ITasBranchCollection : IList { + int Current { get; set; } + string NewBranchText { get; set; } + + void Swap(int b1, int b2); + void Replace(TasBranch old, TasBranch newBranch); + + void Save(BinaryStateSaver bs); + void Load(BinaryStateLoader bl, ITasMovie movie); + } + + public class TasBranchCollection : List, ITasBranchCollection + { + private readonly ITasMovie _movie; + public TasBranchCollection(ITasMovie movie) + { + _movie = movie; + } + + public int Current { get; set; } = -1; + public string NewBranchText { get; set; } = ""; + + public void Swap(int b1, int b2) + { + var branch = this[b1]; + + if (b2 >= Count) + { + b2 = Count - 1; + } + + Remove(branch); + Insert(b2, branch); + _movie.FlagChanges(); + } + + public void Replace(TasBranch old, TasBranch newBranch) + { + int index = IndexOf(old); + newBranch.Uuid = old.Uuid; + if (newBranch.UserText == "") + { + newBranch.UserText = old.UserText; + } + + this[index] = newBranch; + _movie.FlagChanges(); + } + + public new TasBranch this[int index] + { + get => index >= Count || index < 0 + ? null + : base [index]; + set => base[index] = value; + } + public new void Add(TasBranch item) { - if (item.UniqueIdentifier == Guid.Empty) + if (item == null) { - item.UniqueIdentifier = Guid.NewGuid(); + throw new ArgumentNullException($"{nameof(item)} cannot be null"); + } + + if (item.Uuid == Guid.Empty) + { + item.Uuid = Guid.NewGuid(); } base.Add(item); + _movie.FlagChanges(); + } + + public new bool Remove(TasBranch item) + { + var result = base.Remove(item); + if (result) + { + _movie.FlagChanges(); + } + + return result; } public void Save(BinaryStateSaver bs) @@ -55,7 +126,7 @@ namespace BizHawk.Client.Common { b.Frame, b.TimeStamp, - b.UniqueIdentifier + UniqueIdentifier = b.Uuid })); }); @@ -105,7 +176,7 @@ namespace BizHawk.Client.Common } } - public void Load(BinaryStateLoader bl, TasMovie movie) + public void Load(BinaryStateLoader bl, ITasMovie movie) { var nheader = new IndexedStateLump(BinaryStateLump.BranchHeader); var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData); @@ -140,11 +211,11 @@ namespace BizHawk.Client.Common var identifier = header.UniqueIdentifier; if (identifier != null) { - b.UniqueIdentifier = (Guid)identifier; + b.Uuid = (Guid)identifier; } else { - b.UniqueIdentifier = Guid.NewGuid(); + b.Uuid = Guid.NewGuid(); } })) { @@ -218,4 +289,28 @@ namespace BizHawk.Client.Common } } } + + public static class TasBranchExtensions + { + public static int IndexOfFrame(this IList list, int frame) + { + var branch = list + .Where(b => b.Frame == frame) + .OrderByDescending(b => b.TimeStamp) + .FirstOrDefault(); + + return branch == null + ? -1 + : list.IndexOf(branch); + } + + // TODO: stop relying on the index value of a branch + public static int IndexOfHash(this IList list, Guid uuid) + { + var branch = list.SingleOrDefault(b => b.Uuid == uuid); + return branch == null + ? -1 + : list.IndexOf(branch); + } + } } diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs index 7598d6d7d8..91dfc949b8 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs @@ -5,9 +5,9 @@ using BizHawk.Emulation.Common; namespace BizHawk.Client.Common { - public partial class TasMovie + internal partial class TasMovie { - public TasMovieChangeLog ChangeLog { get; set; } + public IMovieChangeLog ChangeLog { get; set; } public override void RecordFrame(int frame, IController source) { @@ -18,8 +18,8 @@ namespace BizHawk.Client.Common base.RecordFrame(frame, source); - TasLagLog.RemoveFrom(frame); - TasLagLog[frame] = Global.Emulator.AsInputPollable().IsLagFrame; + LagLog.RemoveFrom(frame); + LagLog[frame] = Global.Emulator.AsInputPollable().IsLagFrame; if (this.IsRecording()) { @@ -44,7 +44,7 @@ namespace BizHawk.Client.Common base.Truncate(frame); - TasLagLog.RemoveFrom(frame); + LagLog.RemoveFrom(frame); TasStateManager.Invalidate(frame); Markers.TruncateAt(frame); @@ -100,7 +100,7 @@ namespace BizHawk.Client.Common { for (int i = firstIndex; i < Markers.Count; i++) { - TasMovieMarker m = Markers[i]; + var m = Markers[i]; if (m.Frame == frame) { Markers.Remove(m); @@ -538,24 +538,5 @@ namespace BizHawk.Client.Common ChangeLog.SetGeneralRedo(); } - - #region LagLog - - public void RemoveLagHistory(int frame) - { - TasLagLog.RemoveHistoryAt(frame); - } - - public void InsertLagHistory(int frame, bool isLag) - { - TasLagLog.InsertHistoryAt(frame, isLag); - } - - public void SetLag(int frame, bool? value) - { - TasLagLog[frame] = value; - } - - #endregion } } diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs index 35ec22f35d..062da7e657 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs @@ -4,15 +4,40 @@ using System.Linq; namespace BizHawk.Client.Common { - public class TasMovieChangeLog + public interface IMovieChangeLog { - public TasMovieChangeLog(TasMovie movie) + List Names { get; } + int UndoIndex { get; } + string NextUndoStepName { get; } + bool IsRecording { get; set; } + void AddInputBind(int frame, bool isDelete, string name = "", bool force = false); + void Clear(int upTo = -1); + bool BeginNewBatch(string name = "", bool keepOldBatch = false); + void EndBatch(); + int Undo(); + int Redo(); + bool CanUndo { get; } + bool CanRedo { get; } + int PreviousUndoFrame { get; } + int PreviousRedoFrame { get; } + int MaxSteps { get; set; } + + void AddGeneralUndo(int first, int last, string name = "", bool force = false); + void SetGeneralRedo(bool force = false); + void AddBoolToggle(int frame, string button, bool oldState, string name = "", bool force = false); + void AddFloatChange(int frame, string button, float oldState, float newState, string name = "", bool force = false); + void AddMarkerChange(TasMovieMarker newMarker, int oldPosition = -1, string oldMessage = "", string name = "", bool force = false); + } + + public class TasMovieChangeLog : IMovieChangeLog + { + public TasMovieChangeLog(ITasMovie movie) { _movie = movie; } private readonly List> _history = new List>(); - private readonly TasMovie _movie; + private readonly ITasMovie _movie; private int _maxSteps = 100; private int _totalSteps; @@ -31,11 +56,11 @@ namespace BizHawk.Client.Common { if (_history.Count <= value) { - ClearLog(); + Clear(); } else { - ClearLog(_history.Count - value); + Clear(_history.Count - value); } } } @@ -48,7 +73,7 @@ namespace BizHawk.Client.Common /// public bool IsRecording { get; set; } = true; - public void ClearLog(int upTo = -1) + public void Clear(int upTo = -1) { if (upTo == -1) { @@ -362,8 +387,8 @@ namespace BizHawk.Client.Common public interface IMovieAction { - void Undo(TasMovie movie); - void Redo(TasMovie movie); + void Undo(ITasMovie movie); + void Redo(ITasMovie movie); int FirstFrame { get; } int LastFrame { get; } @@ -383,7 +408,7 @@ namespace BizHawk.Client.Common private List _newLog; private readonly bool _bindMarkers; - public MovieAction(int firstFrame, int lastFrame, TasMovie movie) + public MovieAction(int firstFrame, int lastFrame, ITasMovie movie) { FirstFrame = firstFrame; LastFrame = lastFrame; @@ -392,23 +417,23 @@ namespace BizHawk.Client.Common for (int i = 0; i < _undoLength; i++) { - _oldLog.Add(movie.GetLogEntries()[FirstFrame + i]); + _oldLog.Add(movie.GetInputLogEntry(FirstFrame + i)); } _bindMarkers = movie.BindMarkersToInput; } - public void SetRedoLog(TasMovie movie) + public void SetRedoLog(ITasMovie movie) { _redoLength = Math.Min(LastFrame + 1, movie.InputLogLength) - FirstFrame; _newLog = new List(); for (int i = 0; i < _redoLength; i++) { - _newLog.Add(movie.GetLogEntries()[FirstFrame + i]); + _newLog.Add(movie.GetInputLogEntry(FirstFrame + i)); } } - public void Undo(TasMovie movie) + public void Undo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; movie.ChangeLog.IsRecording = false; @@ -433,7 +458,7 @@ namespace BizHawk.Client.Common movie.BindMarkersToInput = _bindMarkers; } - public void Redo(TasMovie movie) + public void Redo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; movie.ChangeLog.IsRecording = false; @@ -483,7 +508,7 @@ namespace BizHawk.Client.Common } } - public void Undo(TasMovie movie) + public void Undo(ITasMovie movie) { if (FirstFrame == -1) // Action: Place marker { @@ -500,7 +525,7 @@ namespace BizHawk.Client.Common } } - public void Redo(TasMovie movie) + public void Redo(ITasMovie movie) { if (FirstFrame == -1) // Action: Place marker { @@ -546,7 +571,7 @@ namespace BizHawk.Client.Common _isFloat = true; } - public void Undo(TasMovie movie) + public void Undo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; movie.ChangeLog.IsRecording = false; @@ -563,7 +588,7 @@ namespace BizHawk.Client.Common movie.ChangeLog.IsRecording = wasRecording; } - public void Redo(TasMovie movie) + public void Redo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; movie.ChangeLog.IsRecording = false; @@ -590,7 +615,7 @@ namespace BizHawk.Client.Common private readonly string _buttonName; private readonly bool _isFloat = false; - public MovieActionPaint(int startFrame, int endFrame, string button, bool newS, TasMovie movie) + public MovieActionPaint(int startFrame, int endFrame, string button, bool newS, ITasMovie movie) { _newState = newS ? 1 : 0; FirstFrame = startFrame; @@ -604,7 +629,7 @@ namespace BizHawk.Client.Common } } - public MovieActionPaint(int startFrame, int endFrame, string button, float newS, TasMovie movie) + public MovieActionPaint(int startFrame, int endFrame, string button, float newS, ITasMovie movie) { _newState = newS; FirstFrame = startFrame; @@ -619,7 +644,7 @@ namespace BizHawk.Client.Common } } - public void Undo(TasMovie movie) + public void Undo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; movie.ChangeLog.IsRecording = false; @@ -642,7 +667,7 @@ namespace BizHawk.Client.Common movie.ChangeLog.IsRecording = wasRecording; } - public void Redo(TasMovie movie) + public void Redo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; movie.ChangeLog.IsRecording = false; @@ -670,7 +695,7 @@ namespace BizHawk.Client.Common private readonly bool _bindMarkers; - public MovieActionBindInput(TasMovie movie, int frame, bool isDelete) + public MovieActionBindInput(ITasMovie movie, int frame, bool isDelete) { FirstFrame = LastFrame = frame; _log = movie.GetInputLogEntry(frame); @@ -678,7 +703,7 @@ namespace BizHawk.Client.Common _bindMarkers = movie.BindMarkersToInput; } - public void Undo(TasMovie movie) + public void Undo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; bool wasBinding = movie.BindMarkersToInput; @@ -688,19 +713,19 @@ namespace BizHawk.Client.Common if (_delete) // Insert { movie.InsertInput(FirstFrame, _log); - movie.InsertLagHistory(FirstFrame + 1, true); + movie.LagLog.InsertHistoryAt(FirstFrame + 1, true); } else // Delete { movie.RemoveFrame(FirstFrame); - movie.RemoveLagHistory(FirstFrame + 1); + movie.LagLog.RemoveHistoryAt(FirstFrame + 1); } movie.ChangeLog.IsRecording = wasRecording; movie.BindMarkersToInput = _bindMarkers; } - public void Redo(TasMovie movie) + public void Redo(ITasMovie movie) { bool wasRecording = movie.ChangeLog.IsRecording; bool wasBinding = movie.BindMarkersToInput; @@ -710,12 +735,12 @@ namespace BizHawk.Client.Common if (_delete) { movie.RemoveFrame(FirstFrame); - movie.RemoveLagHistory(FirstFrame + 1); + movie.LagLog.RemoveHistoryAt(FirstFrame + 1); } else { movie.InsertInput(FirstFrame, _log); - movie.InsertLagHistory(FirstFrame + 1, true); + movie.LagLog.InsertHistoryAt(FirstFrame + 1, true); } movie.ChangeLog.IsRecording = wasRecording; diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs index 4f11929fc7..8d38c05680 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs @@ -5,7 +5,7 @@ using Newtonsoft.Json; namespace BizHawk.Client.Common { - public partial class TasMovie + internal partial class TasMovie { public Func ClientSettingsForSave { get; set; } public Action GetClientSettingsOnLoad { get; set; } @@ -29,7 +29,7 @@ namespace BizHawk.Client.Common var settings = JsonConvert.SerializeObject(TasStateManager.Settings); bs.PutLump(BinaryStateLump.StateHistorySettings, tw => tw.WriteLine(settings)); - bs.PutLump(BinaryStateLump.LagLog, tw => TasLagLog.Save(tw)); + bs.PutLump(BinaryStateLump.LagLog, tw => LagLog.Save(tw)); bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString())); if (StartsFromSavestate) @@ -179,7 +179,7 @@ namespace BizHawk.Client.Common // TasMovie enhanced information bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { - TasLagLog.Load(tr); + LagLog.Load(tr); }); bl.GetLump(BinaryStateLump.StateHistorySettings, false, delegate(TextReader tr) @@ -285,10 +285,10 @@ namespace BizHawk.Client.Common private void ClearTasprojExtras() { - ClearLagLog(); + LagLog.Clear(); TasStateManager.Clear(); Markers.Clear(); - ChangeLog.ClearLog(); + ChangeLog.Clear(); } } } diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs index 8e5fdee3a3..65c3436b40 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovie.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.cs @@ -3,42 +3,14 @@ using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; -using System.Linq; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common { - public sealed partial class TasMovie : Bk2Movie, INotifyPropertyChanged + internal sealed partial class TasMovie : Bk2Movie, ITasMovie { - public IStringLog VerificationLog { get; } = StringLogUtil.MakeStringLog(); // For movies that do not begin with power-on, this is the input required to get into the initial state - public TasBranchCollection Branches { get; } = new TasBranchCollection(); - public TasSession Session { get; private set; } = new TasSession(); - public new const string Extension = "tasproj"; - public const string DefaultProjectName = "default"; - public string NewBranchText { get; set; } = ""; - public int LastEditedFrame { get; private set; } = -1; - public bool LastPositionStable { get; set; } = true; - public TasMovieMarkerList Markers { get; private set; } - public bool BindMarkersToInput { get; set; } - public int CurrentBranch { get; set; } = -1; - - public TasLagLog TasLagLog { get; } = new TasLagLog(); - - public int LastStatedFrame => TasStateManager.Last; - public override string PreferredExtension => Extension; - public IStateManager TasStateManager { get; } - - public IStringLog CloneInput() => Log.Clone(); - - public TasMovieRecord this[int index] => new TasMovieRecord - { - HasState = TasStateManager.HasState(index), - LogEntry = GetInputLogEntry(index), - Lagged = TasLagLog[index + 1], - WasLagged = TasLagLog.History(index + 1) - }; /// loaded core does not implement public TasMovie(string path = null, bool startsFromSavestate = false) : base(path) @@ -48,6 +20,7 @@ namespace BizHawk.Client.Common throw new InvalidOperationException($"Cannot create a {nameof(TasMovie)} against a core that does not implement {nameof(IStatable)}"); } + Branches = new TasBranchCollection(this); ChangeLog = new TasMovieChangeLog(this); TasStateManager = new TasStateManager(this, Global.Config.DefaultTasStateManagerSettings); Header[HeaderKeys.MovieVersion] = "BizHawk v2.0 Tasproj v1.0"; @@ -56,6 +29,28 @@ namespace BizHawk.Client.Common Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); } + public IStringLog VerificationLog { get; } = StringLogUtil.MakeStringLog(); // For movies that do not begin with power-on, this is the input required to get into the initial state + public ITasBranchCollection Branches { get; } + public ITasSession Session { get; private set; } = new TasSession(); + + public int LastEditedFrame { get; private set; } = -1; + public bool LastPositionStable { get; set; } = true; + public TasMovieMarkerList Markers { get; private set; } + public bool BindMarkersToInput { get; set; } + + public TasLagLog LagLog { get; } = new TasLagLog(); + + public override string PreferredExtension => Extension; + public IStateManager TasStateManager { get; } + + public ITasMovieRecord this[int index] => new TasMovieRecord + { + HasState = TasStateManager.HasState(index), + LogEntry = GetInputLogEntry(index), + Lagged = LagLog[index + 1], + WasLagged = LagLog.History(index + 1) + }; + public override void StartNewRecording() { ClearTasprojExtras(); @@ -65,13 +60,10 @@ namespace BizHawk.Client.Common base.StartNewRecording(); } - /// - /// Removes lag log and greenzone after this frame - /// - /// The last frame that can be valid. + // Removes lag log and greenzone after this frame private void InvalidateAfter(int frame) { - var anyInvalidated = TasLagLog.RemoveFrom(frame); + var anyInvalidated = LagLog.RemoveFrom(frame); TasStateManager.Invalidate(frame + 1); Changes = anyInvalidated; LastEditedFrame = frame; @@ -109,21 +101,6 @@ namespace BizHawk.Client.Common return "!"; } - public bool BoolIsPressed(int frame, string buttonName) - => GetInputState(frame).IsPressed(buttonName); - - public float GetFloatState(int frame, string buttonName) - => GetInputState(frame).AxisValue(buttonName); - - public void ClearGreenzone() - { - if (TasStateManager.Any()) - { - TasStateManager.Clear(); - Changes = true; - } - } - public void GreenzoneCurrentFrame() { // todo: this isn't working quite right when autorestore is off and we're editing while seeking @@ -134,7 +111,7 @@ namespace BizHawk.Client.Common LastPositionStable = false; } - TasLagLog[Global.Emulator.Frame] = Global.Emulator.AsInputPollable().IsLagFrame; + LagLog[Global.Emulator.Frame] = Global.Emulator.AsInputPollable().IsLagFrame; if (!TasStateManager.HasState(Global.Emulator.Frame)) { @@ -142,12 +119,7 @@ namespace BizHawk.Client.Common } } - public void ClearLagLog() - { - TasLagLog.Clear(); - } - - public void CopyLog(IEnumerable log) + internal void CopyLog(IEnumerable log) { Log.Clear(); foreach (var entry in log) @@ -156,7 +128,7 @@ namespace BizHawk.Client.Common } } - public void CopyVerificationLog(IEnumerable log) + internal void CopyVerificationLog(IEnumerable log) { foreach (string entry in log) { @@ -322,75 +294,13 @@ namespace BizHawk.Client.Common if (_timelineBranchFrame.HasValue) { - TasLagLog.RemoveFrom(_timelineBranchFrame.Value); + LagLog.RemoveFrom(_timelineBranchFrame.Value); TasStateManager.Invalidate(_timelineBranchFrame.Value); } return true; } - #region Branches - - public TasBranch GetBranch(int index) - { - if (index >= Branches.Count || index < 0) - { - return null; - } - - return Branches[index]; - } - - public TasBranch GetBranch(Guid id) - { - return Branches.SingleOrDefault(b => b.UniqueIdentifier == id); - } - - public Guid BranchGuidByIndex(int index) - { - return index >= Branches.Count - ? Guid.Empty - : Branches[index].UniqueIdentifier; - } - - public int BranchIndexByHash(Guid uuid) - { - TasBranch branch = Branches.SingleOrDefault(b => b.UniqueIdentifier == uuid); - if (branch == null) - { - return -1; - } - - return Branches.IndexOf(branch); - } - - public int BranchIndexByFrame(int frame) - { - TasBranch branch = Branches - .Where(b => b.Frame == frame) - .OrderByDescending(b => b.TimeStamp) - .FirstOrDefault(); - - if (branch == null) - { - return -1; - } - - return Branches.IndexOf(branch); - } - - public void AddBranch(TasBranch branch) - { - Branches.Add(branch); - Changes = true; - } - - public void RemoveBranch(TasBranch branch) - { - Branches.Remove(branch); - Changes = true; - } - public void LoadBranch(TasBranch branch) { int? divergentPoint = Log.DivergentPoint(branch.InputLog); @@ -408,35 +318,6 @@ namespace BizHawk.Client.Common Changes = true; } - public void UpdateBranch(TasBranch old, TasBranch newBranch) - { - int index = Branches.IndexOf(old); - newBranch.UniqueIdentifier = old.UniqueIdentifier; - if (newBranch.UserText == "") - { - newBranch.UserText = old.UserText; - } - - Branches[index] = newBranch; - Changes = true; - } - - public void SwapBranches(int b1, int b2) - { - TasBranch branch = Branches[b1]; - - if (b2 >= Branches.Count) - { - b2 = Branches.Count - 1; - } - - Branches.Remove(branch); - Branches.Insert(b2, branch); - Changes = true; - } - - #endregion - #region Events and Handlers public event PropertyChangedEventHandler PropertyChanged; diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs b/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs index 3a672bb5b1..3694501aac 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs @@ -69,9 +69,9 @@ namespace BizHawk.Client.Common public class TasMovieMarkerList : List { - private readonly TasMovie _movie; + private readonly ITasMovie _movie; - public TasMovieMarkerList(TasMovie movie) + public TasMovieMarkerList(ITasMovie movie) { _movie = movie; } diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs b/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs index 65084ae26e..459c9bcc2b 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasMovieRecord.cs @@ -1,10 +1,18 @@ namespace BizHawk.Client.Common { - public class TasMovieRecord + public interface ITasMovieRecord { - public bool? Lagged { get; set; } - public bool? WasLagged { get; set; } - public string LogEntry { get; set; } - public bool HasState { get; set; } + bool? Lagged { get; } + bool? WasLagged { get; } + string LogEntry { get; } + bool HasState { get; } + } + + public class TasMovieRecord : ITasMovieRecord + { + public bool? Lagged { get; internal set; } + public bool? WasLagged { get; internal set; } + public string LogEntry { get; internal set; } + public bool HasState { get; internal set; } } } diff --git a/BizHawk.Client.Common/movie/tasproj/TasSession.cs b/BizHawk.Client.Common/movie/tasproj/TasSession.cs index 349fedc0c5..1a8de6bac6 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasSession.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasSession.cs @@ -1,9 +1,16 @@ namespace BizHawk.Client.Common { - public class TasSession + public interface ITasSession { - public int CurrentFrame { get; set; } - public int CurrentBranch { get; set; } = -1; + int CurrentFrame { get; } + int CurrentBranch { get; } + void UpdateValues(int frame, int currentBranch); + } + + public class TasSession : ITasSession + { + public int CurrentFrame { get; private set; } + public int CurrentBranch { get; private set; } = -1; public void UpdateValues(int frame, int currentBranch) { diff --git a/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs b/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs index a1a8974ea4..e2bf7cc8d0 100644 --- a/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs +++ b/BizHawk.Client.Common/movie/tasproj/TasStateManager.cs @@ -22,7 +22,7 @@ namespace BizHawk.Client.Common private IEmulator Emulator => Global.Emulator; private readonly StateManagerDecay _decay; - private readonly TasMovie _movie; + private readonly ITasMovie _movie; private readonly SortedList _states; private readonly ulong _expectedStateSize; @@ -35,7 +35,7 @@ namespace BizHawk.Client.Common private int FileStateGap => 1 << Settings.FileStateGap; /// loaded core expects savestate size of 0 B - public TasStateManager(TasMovie movie, TasStateManagerSettings settings) + public TasStateManager(ITasMovie movie, TasStateManagerSettings settings) { _movie = movie; Settings = new TasStateManagerSettings(settings); @@ -160,6 +160,8 @@ namespace BizHawk.Client.Common SetState(0, power); _used = (ulong)power.Length; } + + _movie.FlagChanges(); } } diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 73505a42f5..a2e2207701 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -3015,7 +3015,7 @@ namespace BizHawk.Client.EmuHawk if (PauseOnFrame.HasValue && PauseOnFrame.Value <= Tools.TAStudio.LastPositionFrame) { - TasMovieRecord record = (MovieSession.Movie as TasMovie)[Emulator.Frame]; + var record = (MovieSession.Movie as ITasMovie)[Emulator.Frame]; if (!record.Lagged.HasValue && IsSeeking) { // haven't yet greenzoned the frame, hence it's after editing diff --git a/BizHawk.Client.EmuHawk/movie/PlayMovie.cs b/BizHawk.Client.EmuHawk/movie/PlayMovie.cs index 05f6d7a3a0..cb9cd41ef8 100644 --- a/BizHawk.Client.EmuHawk/movie/PlayMovie.cs +++ b/BizHawk.Client.EmuHawk/movie/PlayMovie.cs @@ -263,8 +263,10 @@ namespace BizHawk.Client.EmuHawk } // add movies - fpTodo.AddRange(Directory.GetFiles(dp, $"*.{MovieService.DefaultExtension}")); - fpTodo.AddRange(Directory.GetFiles(dp, $"*.{TasMovie.Extension}")); + foreach (var extension in MovieService.MovieExtensions) + { + fpTodo.AddRange(Directory.GetFiles(dp, $"*.{extension}")); + } } // in parallel, scan each movie diff --git a/BizHawk.Client.EmuHawk/movie/RecordMovie.cs b/BizHawk.Client.EmuHawk/movie/RecordMovie.cs index e5dbc18bbf..e12a60bc06 100644 --- a/BizHawk.Client.EmuHawk/movie/RecordMovie.cs +++ b/BizHawk.Client.EmuHawk/movie/RecordMovie.cs @@ -70,7 +70,7 @@ namespace BizHawk.Client.EmuHawk if (!MovieService.MovieExtensions.Contains(Path.GetExtension(path))) { // If no valid movie extension, add movie extension - path += $".{MovieService.DefaultExtension}"; + path += $".{MovieService.StandardMovieExtension}"; } } } diff --git a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 32ad9fcd6f..e212f3e041 100644 --- a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -111,7 +111,7 @@ namespace BizHawk.Client.EmuHawk { if (Engaged()) { - Tastudio.CurrentTasMovie.SetLag(frame, value); + Tastudio.CurrentTasMovie.LagLog[frame] = value; } } @@ -337,11 +337,15 @@ namespace BizHawk.Client.EmuHawk { if (index != null) { - Tastudio.CurrentTasMovie.GetBranch(index.Value).UserText = text; + var branch = Tastudio.CurrentTasMovie.Branches[index.Value]; + if (branch != null) + { + branch.UserText = text; + } } else { - Tastudio.CurrentTasMovie.NewBranchText = text; + Tastudio.CurrentTasMovie.Branches.NewBranchText = text; } } @@ -354,7 +358,7 @@ namespace BizHawk.Client.EmuHawk return Tastudio.CurrentTasMovie.Branches .Select(b => new { - Id = b.UniqueIdentifier.ToString(), + Id = b.Uuid.ToString(), b.Frame, Text = b.UserText }) @@ -372,7 +376,7 @@ namespace BizHawk.Client.EmuHawk if (Engaged()) { - var branch = Tastudio.CurrentTasMovie.Branches.FirstOrDefault(b => b.UniqueIdentifier.ToString() == branchId); + var branch = Tastudio.CurrentTasMovie.Branches.FirstOrDefault(b => b.Uuid.ToString() == branchId); if (branch != null && frame < branch.InputLog.Count) { var controller = Global.MovieSession.GenerateMovieController(); diff --git a/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs b/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs index 310a57446a..2f1fce72c3 100644 --- a/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs +++ b/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs @@ -45,9 +45,7 @@ namespace BizHawk.Client.EmuHawk return; } - ReplaceBox.Enabled = CurrentMovie is TasMovie; - OverlayBox.Enabled = CurrentMovie is TasMovie; - PlaceNum.Enabled = CurrentMovie is TasMovie; + ReplaceBox.Enabled = OverlayBox.Enabled = PlaceNum.Enabled = CurrentMovie is ITasMovie; var main = new MovieZone(CurrentMovie, Emulator, Tools, MovieSession, 0, CurrentMovie.InputLogLength) { @@ -223,7 +221,7 @@ namespace BizHawk.Client.EmuHawk return; } - if (!(CurrentMovie is TasMovie)) + if (!(CurrentMovie is ITasMovie)) { SelectedZone.Start = Emulator.Frame; } @@ -254,7 +252,7 @@ namespace BizHawk.Client.EmuHawk ZonesList.Items.Add($"{loadZone.Name} - length: {loadZone.Length}"); // Options only for TasMovie - if (!(CurrentMovie is TasMovie)) + if (!(CurrentMovie is ITasMovie)) { loadZone.Replace = false; loadZone.Overlay = false; diff --git a/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs b/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs index 5d374a6624..39a248ca05 100644 --- a/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs +++ b/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs @@ -128,7 +128,7 @@ namespace BizHawk.Client.EmuHawk public void PlaceZone(IMovie movie) { - if (movie is TasMovie tasMovie) + if (movie is ITasMovie tasMovie) { tasMovie.ChangeLog.BeginNewBatch($"Place Macro at {Start}"); } @@ -139,8 +139,9 @@ namespace BizHawk.Client.EmuHawk return; } - if (!Replace && movie is TasMovie tasMovie2) - { // Can't be done with a regular movie. + // Can't be done with a regular movie. + if (!Replace && movie is ITasMovie tasMovie2) + { tasMovie2.InsertEmptyFrame(Start, Length); } @@ -156,15 +157,16 @@ namespace BizHawk.Client.EmuHawk } else { + // Copy over the frame. for (int i = 0; i < Length; i++) - { // Copy over the frame. + { _controller.SetFromMnemonic(_log[i]); LatchFromSourceButtons(_targetController, _controller); movie.PokeFrame(i + Start, _targetController); } } - if (movie is TasMovie tasMovie3) // Assume TAStudio is open? + if (movie is ITasMovie tasMovie3) // Assume TAStudio is open? { tasMovie3.ChangeLog.EndBatch(); if (_emulator.Frame > Start) diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs index c57d405d59..d9fdf47c61 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs @@ -17,7 +17,9 @@ namespace BizHawk.Client.EmuHawk private readonly ScreenshotForm _screenshot = new ScreenshotForm(); - private TasMovie Movie => Tastudio.CurrentTasMovie; + private ITasMovie Movie => Tastudio.CurrentTasMovie; + private ITasBranchCollection Branches => Movie.Branches; + private MainForm MainForm => Tastudio.MainForm; private TasBranch _backupBranch; private BranchUndo _branchUndo = BranchUndo.None; @@ -81,7 +83,7 @@ namespace BizHawk.Client.EmuHawk { text = ""; - if (index >= Movie.Branches.Count) + if (index >= Branches.Count) { return; } @@ -89,19 +91,19 @@ namespace BizHawk.Client.EmuHawk text = column.Name switch { BranchNumberColumnName => index.ToString(), - FrameColumnName => GetBranch(index).Frame.ToString(), - UserTextColumnName => GetBranch(index).UserText, + FrameColumnName => Branches[index].Frame.ToString(), + UserTextColumnName => Branches[index].UserText, _ => text }; } private void QueryItemBkColor(int index, RollColumn column, ref Color color) { - TasBranch branch = GetBranch(index); + var branch = Branches[index]; if (branch != null) { var record = Movie[branch.Frame]; - if (index == Movie.CurrentBranch) + if (index == Branches.Current) { color = TAStudio.CurrentFrame_InputLog; } @@ -127,28 +129,23 @@ namespace BizHawk.Client.EmuHawk #region Actions - private TasBranch GetBranch(int index) - { - return Movie.GetBranch(index); - } - public void Branch() { - TasBranch branch = CreateBranch(); - Movie.NewBranchText = ""; // reset every time it's used - Movie.AddBranch(branch); - BranchView.RowCount = Movie.Branches.Count; - Movie.CurrentBranch = Movie.Branches.Count - 1; - Movie.Session.UpdateValues(Global.Emulator.Frame, Movie.CurrentBranch); // TODO: pass in emulator dependency - BranchView.ScrollToIndex(Movie.CurrentBranch); - Select(Movie.CurrentBranch, true); + var branch = CreateBranch(); + Movie.Branches.NewBranchText = ""; // reset every time it's used + Branches.Add(branch); + BranchView.RowCount = Branches.Count; + Branches.Current = Branches.Count - 1; + Movie.Session.UpdateValues(Tastudio.Emulator.Frame, Branches.Current); + BranchView.ScrollToIndex(Branches.Current); + Select(Branches.Current, true); BranchView.Refresh(); Tastudio.RefreshDialog(); MainForm.UpdateStatusSlots(); } public TasBranch SelectedBranch => BranchView.AnyRowsSelected - ? GetBranch(BranchView.SelectedRows.First()) + ? Branches[BranchView.SelectedRows.First()] : null; private TasBranch CreateBranch() @@ -156,14 +153,14 @@ namespace BizHawk.Client.EmuHawk return new TasBranch { Frame = Tastudio.Emulator.Frame, - CoreData = (byte[])(Tastudio.StatableEmulator.SaveStateBinary().Clone()), - InputLog = Movie.CloneInput(), + CoreData = (byte[])Tastudio.StatableEmulator.SaveStateBinary().Clone(), + InputLog = Movie.GetLogEntries().Clone(), CoreFrameBuffer = MainForm.MakeScreenshotImage(), OSDFrameBuffer = MainForm.CaptureOSD(), ChangeLog = new TasMovieChangeLog(Movie), TimeStamp = DateTime.Now, Markers = Movie.Markers.DeepClone(), - UserText = Movie.NewBranchText + UserText = Movie.Branches.NewBranchText }; } @@ -190,7 +187,7 @@ namespace BizHawk.Client.EmuHawk private void UpdateBranch(TasBranch branch) { - Movie.UpdateBranch(branch, CreateBranch()); + Branches.Replace(branch, CreateBranch()); Tastudio.RefreshDialog(); } @@ -199,10 +196,10 @@ namespace BizHawk.Client.EmuHawk if (SelectedBranch != null) { int index = BranchView.SelectedRows.First(); - Movie.CurrentBranch = index; + Branches.Current = index; LoadBranch(SelectedBranch); BranchView.Refresh(); - Tastudio.MainForm.AddOnScreenMessage($"Loaded branch {Movie.CurrentBranch}"); + Tastudio.MainForm.AddOnScreenMessage($"Loaded branch {Branches.Current}"); } } @@ -219,28 +216,28 @@ namespace BizHawk.Client.EmuHawk private void AddBranchToolStripMenuItem_Click(object sender, EventArgs e) { Branch(); - SavedCallback?.Invoke(Movie.Branches.Count - 1); - Tastudio.MainForm.AddOnScreenMessage($"Added branch {Movie.CurrentBranch}"); + SavedCallback?.Invoke(Branches.Count - 1); + Tastudio.MainForm.AddOnScreenMessage($"Added branch {Branches.Current}"); } private void AddBranchWithTexToolStripMenuItem_Click(object sender, EventArgs e) { Branch(); - EditBranchTextPopUp(Movie.CurrentBranch); - SavedCallback?.Invoke(Movie.Branches.Count - 1); - Tastudio.MainForm.AddOnScreenMessage($"Added branch {Movie.CurrentBranch}"); + EditBranchTextPopUp(Branches.Current); + SavedCallback?.Invoke(Branches.Count - 1); + Tastudio.MainForm.AddOnScreenMessage($"Added branch {Branches.Current}"); } private void LoadBranchToolStripMenuItem_Click(object sender, EventArgs e) { _backupBranch = CreateBranch(); - var currentHashes = Movie.Branches.Select(b => b.UniqueIdentifier.GetHashCode()).ToList(); + var currentHashes = Branches.Select(b => b.Uuid.GetHashCode()).ToList(); do { - _backupBranch.UniqueIdentifier = Guid.NewGuid(); + _backupBranch.Uuid = Guid.NewGuid(); } - while (currentHashes.Contains(_backupBranch.UniqueIdentifier.GetHashCode())); + while (currentHashes.Contains(_backupBranch.Uuid.GetHashCode())); UndoBranchToolStripMenuItem.Enabled = UndoBranchButton.Enabled = true; UndoBranchToolStripMenuItem.Text = "Undo Branch Load"; @@ -261,7 +258,7 @@ namespace BizHawk.Client.EmuHawk return; } - Movie.CurrentBranch = BranchView.SelectedRows.First(); + Branches.Current = BranchView.SelectedRows.First(); _backupBranch = SelectedBranch.Clone(); UndoBranchToolStripMenuItem.Enabled = UndoBranchButton.Enabled = true; @@ -270,8 +267,8 @@ namespace BizHawk.Client.EmuHawk _branchUndo = BranchUndo.Update; UpdateBranch(SelectedBranch); - SavedCallback?.Invoke(Movie.CurrentBranch); - Tastudio.MainForm.AddOnScreenMessage($"Saved branch {Movie.CurrentBranch}"); + SavedCallback?.Invoke(Branches.Current); + Tastudio.MainForm.AddOnScreenMessage($"Saved branch {Branches.Current}"); } private void EditBranchTextToolStripMenuItem_Click(object sender, EventArgs e) @@ -305,7 +302,7 @@ namespace BizHawk.Client.EmuHawk } int index = BranchView.SelectedRows.First(); - TasBranch branch = Movie.GetBranch(index); + var branch = Branches[index]; Tastudio.GoToFrame(branch.Frame); } @@ -317,13 +314,13 @@ namespace BizHawk.Client.EmuHawk } int index = BranchView.SelectedRows.First(); - if (index == Movie.CurrentBranch) + if (index == Branches.Current) { - Movie.CurrentBranch = -1; + Branches.Current = -1; } - else if (index < Movie.CurrentBranch) + else if (index < Branches.Current) { - Movie.CurrentBranch--; + Branches.Current--; } _backupBranch = SelectedBranch.Clone(); @@ -332,13 +329,13 @@ namespace BizHawk.Client.EmuHawk toolTip1.SetToolTip(UndoBranchButton, "Undo Branch Removal"); _branchUndo = BranchUndo.Remove; - Movie.RemoveBranch(SelectedBranch); - BranchView.RowCount = Movie.Branches.Count; + Branches.Remove(SelectedBranch); + BranchView.RowCount = Branches.Count; - if (index == Movie.Branches.Count) + if (index == Branches.Count) { BranchView.DeselectAll(); - Select(Movie.Branches.Count - 1, true); + Select(Branches.Count - 1, true); } RemovedCallback?.Invoke(index); @@ -352,25 +349,34 @@ namespace BizHawk.Client.EmuHawk if (_branchUndo == BranchUndo.Load) { LoadBranch(_backupBranch); - LoadedCallback?.Invoke(Movie.Branches.IndexOf(_backupBranch)); + LoadedCallback?.Invoke(Branches.IndexOf(_backupBranch)); Tastudio.MainForm.AddOnScreenMessage("Branch Load canceled"); } else if (_branchUndo == BranchUndo.Update) { - Movie.UpdateBranch(Movie.GetBranch(_backupBranch.UniqueIdentifier), _backupBranch); - SavedCallback?.Invoke(Movie.Branches.IndexOf(_backupBranch)); - Tastudio.MainForm.AddOnScreenMessage("Branch Update canceled"); + var branch = Branches.SingleOrDefault(b => b.Uuid == _backupBranch.Uuid); + if (branch != null) + { + Branches.Replace(branch, _backupBranch); + SavedCallback?.Invoke(Branches.IndexOf(_backupBranch)); + Tastudio.MainForm.AddOnScreenMessage("Branch Update canceled"); + } } else if (_branchUndo == BranchUndo.Text) { - Movie.GetBranch(_backupBranch.UniqueIdentifier).UserText = _backupBranch.UserText; + var branch = Branches.SingleOrDefault(b => b.Uuid == _backupBranch.Uuid); + if (branch != null) + { + branch.UserText = _backupBranch.UserText; + } + Tastudio.MainForm.AddOnScreenMessage("Branch Text Edit canceled"); } else if (_branchUndo == BranchUndo.Remove) { - Movie.AddBranch(_backupBranch); - BranchView.RowCount = Movie.Branches.Count; - SavedCallback?.Invoke(Movie.Branches.IndexOf(_backupBranch)); + Branches.Add(_backupBranch); + BranchView.RowCount = Branches.Count; + SavedCallback?.Invoke(Branches.IndexOf(_backupBranch)); Tastudio.MainForm.AddOnScreenMessage("Branch Removal canceled"); } @@ -382,7 +388,7 @@ namespace BizHawk.Client.EmuHawk public void AddBranchExternal() { AddBranchToolStripMenuItem_Click(null, null); - Select(Movie.CurrentBranch, true); + Select(Branches.Current, true); BranchView.Refresh(); } @@ -395,7 +401,7 @@ namespace BizHawk.Client.EmuHawk if (slot != -1) { - if (GetBranch(slot) != null) + if (Branches[slot] != null) { Select(slot, true); } @@ -418,7 +424,7 @@ namespace BizHawk.Client.EmuHawk if (slot != -1) { - if (GetBranch(slot) != null) + if (Branches[slot] != null) { Select(slot, true); } @@ -445,7 +451,7 @@ namespace BizHawk.Client.EmuHawk return; } - if (GetBranch(slot) != null) + if (Branches[slot] != null) { Select(slot, true); BranchView.Refresh(); @@ -460,7 +466,7 @@ namespace BizHawk.Client.EmuHawk { if (SelectedBranch == null) { - Select(Movie.CurrentBranch, true); + Select(Branches.Current, true); BranchView.Refresh(); return; } @@ -468,7 +474,7 @@ namespace BizHawk.Client.EmuHawk int sel = BranchView.SelectedRows.First(); if (next) { - if (GetBranch(sel + 1) != null) + if (Branches[sel + 1] != null) { Select(sel, false); Select(sel + 1, true); @@ -476,7 +482,7 @@ namespace BizHawk.Client.EmuHawk } else // previous { - if (GetBranch(sel - 1) != null) + if (Branches[sel - 1] != null) { Select(sel, false); Select(sel - 1, true); @@ -509,12 +515,12 @@ namespace BizHawk.Client.EmuHawk public void UpdateValues() { - BranchView.RowCount = Movie.Branches.Count; + BranchView.RowCount = Branches.Count; } public void Restart() { - BranchView.RowCount = Movie.Branches.Count; + BranchView.RowCount = Branches.Count; if (BranchView.RowCount == 0) { @@ -526,9 +532,9 @@ namespace BizHawk.Client.EmuHawk public void UpdateTextColumnWidth() { - if (Movie.Branches.Any()) + if (Branches.Any()) { - var longestBranchText = Movie.Branches + var longestBranchText = Branches .OrderBy(b => b.UserText?.Length ?? 0) .Last() .UserText; @@ -539,7 +545,7 @@ namespace BizHawk.Client.EmuHawk public bool EditBranchTextPopUp(int index) { - TasBranch branch = Movie.GetBranch(index); + var branch = Branches[index]; if (branch == null) { return false; @@ -557,7 +563,7 @@ namespace BizHawk.Client.EmuHawk point.Offset(i.Width / -2, i.Height / -2); var result = i.ShowHawkDialog(position: point); - if (result == DialogResult.OK) + if (result.IsOk()) { branch.UserText = i.PromptText; UpdateTextColumnWidth(); @@ -622,25 +628,28 @@ namespace BizHawk.Client.EmuHawk private void BranchView_CellDropped(object sender, InputRoll.CellEventArgs e) { - if (e.NewCell.IsDataCell() && e.OldCell.RowIndex < Movie.Branches.Count) + if (e.NewCell.IsDataCell() && e.OldCell.RowIndex < Branches.Count) { - var guid = Movie.BranchGuidByIndex(Movie.CurrentBranch); - Movie.SwapBranches(e.OldCell.RowIndex.Value, e.NewCell.RowIndex.Value); - int newIndex = Movie.BranchIndexByHash(guid); - Movie.CurrentBranch = newIndex; + var guid = Branches.Current > Branches.Count + ? Guid.Empty + : Branches[Branches.Current].Uuid; + + Branches.Swap(e.OldCell.RowIndex.Value, e.NewCell.RowIndex.Value); + int newIndex = Branches.IndexOfHash(guid); + Branches.Current = newIndex; Select(newIndex, true); } } private void BranchView_PointedCellChanged(object sender, InputRoll.CellEventArgs e) { - if (e.NewCell?.RowIndex != null && e.NewCell.Column != null && e.NewCell.RowIndex < Movie.Branches.Count) + if (e.NewCell?.RowIndex != null && e.NewCell.Column != null && e.NewCell.RowIndex < Branches.Count) { if (BranchView.CurrentCell.Column.Name == BranchNumberColumnName && BranchView.CurrentCell.RowIndex.HasValue && - BranchView.CurrentCell.RowIndex < Movie.Branches.Count) + BranchView.CurrentCell.RowIndex < Branches.Count) { - TasBranch branch = GetBranch(BranchView.CurrentCell.RowIndex.Value); + var branch = Branches[BranchView.CurrentCell.RowIndex.Value]; Point location = PointToScreen(Location); int width = branch.OSDFrameBuffer.Width; int height = branch.OSDFrameBuffer.Height; diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs index 8829e158e6..09637ddda5 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs @@ -51,7 +51,7 @@ namespace BizHawk.Client.EmuHawk refreshNeeded = AutoAdjustInput(); } - CurrentTasMovie.Session.UpdateValues(Emulator.Frame, CurrentTasMovie.CurrentBranch); + CurrentTasMovie.Session.UpdateValues(Emulator.Frame, CurrentTasMovie.Branches.Current); MaybeFollowCursor(); if (TasView.IsPartiallyVisible(Emulator.Frame) || TasView.IsPartiallyVisible(_lastRefresh)) diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs index d6beea36e1..843f8038a3 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs @@ -196,7 +196,7 @@ namespace BizHawk.Client.EmuHawk } else if (columnName == FrameColumnName) { - TasMovieRecord record = CurrentTasMovie[index]; + var record = CurrentTasMovie[index]; offsetX = -3; offsetY = 1; @@ -262,7 +262,7 @@ namespace BizHawk.Client.EmuHawk private void TasView_QueryRowBkColor(int index, ref Color color) { - TasMovieRecord record = CurrentTasMovie[index]; + var record = CurrentTasMovie[index]; if (MainForm.IsSeeking && MainForm.PauseOnFrame == index) { @@ -315,7 +315,7 @@ namespace BizHawk.Client.EmuHawk if (columnName == CursorColumnName) { - int branchIndex = CurrentTasMovie.BranchIndexByFrame(index); + int branchIndex = CurrentTasMovie.Branches.IndexOfFrame(index); if (branchIndex != -1) { text = branchIndex.ToString(); @@ -356,10 +356,9 @@ namespace BizHawk.Client.EmuHawk } } - // SuuperW: Used in InputRoll.cs to hide lag frames. private bool TasView_QueryFrameLag(int index, bool hideWasLag) { - TasMovieRecord lag = CurrentTasMovie[index]; + var lag = CurrentTasMovie[index]; return (lag.Lagged.HasValue && lag.Lagged.Value) || (hideWasLag && lag.WasLagged.HasValue && lag.WasLagged.Value); } @@ -518,7 +517,7 @@ namespace BizHawk.Client.EmuHawk { if (MainForm.EmulatorPaused) { - TasMovieRecord record = CurrentTasMovie[LastPositionFrame]; + var record = CurrentTasMovie[LastPositionFrame]; if (!record.Lagged.HasValue && LastPositionFrame > Emulator.Frame) { StartSeeking(LastPositionFrame, true); @@ -744,7 +743,7 @@ namespace BizHawk.Client.EmuHawk else { _rightClickInput = new string[1]; - _rightClickInput[0] = CurrentTasMovie.GetLogEntries()[frame]; + _rightClickInput[0] = CurrentTasMovie.GetInputLogEntry(frame); _rightClickFrame = frame; } diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs index a410015306..d903b05925 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs @@ -42,7 +42,7 @@ namespace BizHawk.Client.EmuHawk { int index = Emulator.Frame; - TasMovie newProject = CurrentTasMovie.ConvertToSavestateAnchoredMovie( + var newProject = CurrentTasMovie.ConvertToSavestateAnchoredMovie( index, (byte[])StatableEmulator.SaveStateBinary().Clone()); MainForm.PauseEmulator(); @@ -63,7 +63,7 @@ namespace BizHawk.Client.EmuHawk } GoToFrame(index); - TasMovie newProject = CurrentTasMovie.ConvertToSaveRamAnchoredMovie( + var newProject = CurrentTasMovie.ConvertToSaveRamAnchoredMovie( SaveRamEmulator.CloneSaveRam()); MainForm.PauseEmulator(); LoadFile(new FileInfo(newProject.Filename), true); @@ -114,11 +114,11 @@ namespace BizHawk.Client.EmuHawk var result = ofd.ShowHawkDialog(); if (result.IsOk()) { - if (ofd.FileName.EndsWith(TasMovie.Extension)) + if (ofd.FileName.EndsWith(MovieService.TasMovieExtension)) { LoadFile(new FileInfo(ofd.FileName)); } - else if (ofd.FileName.EndsWith(Bk2Movie.Extension)) + else if (ofd.FileName.EndsWith(MovieService.StandardMovieExtension)) { var result1 = MessageBox.Show("This is a regular movie, a new project must be created from it, in order to use in TAStudio\nProceed?", "Convert movie", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (result1.IsOk()) @@ -759,7 +759,7 @@ namespace BizHawk.Client.EmuHawk private void ClearGreenzoneMenuItem_Click(object sender, EventArgs e) { - CurrentTasMovie.ClearGreenzone(); + CurrentTasMovie.TasStateManager.Clear(); RefreshDialog(); } @@ -775,7 +775,7 @@ namespace BizHawk.Client.EmuHawk GoToFrame(0); int lastState = 0; - int goToFrame = CurrentTasMovie.LastStatedFrame; + int goToFrame = CurrentTasMovie.TasStateManager.Last; do { MainForm.FrameAdvance(); diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs index c5c955bfd0..dfdb4c3466 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs @@ -16,7 +16,7 @@ namespace BizHawk.Client.EmuHawk public partial class TAStudio : ToolFormBase, IToolFormAutoConfig, IControlMainform { // TODO: UI flow that conveniently allows to start from savestate - public TasMovie CurrentTasMovie => MovieSession.Movie as TasMovie; + public ITasMovie CurrentTasMovie => MovieSession.Movie as ITasMovie; public bool IsInMenuLoop { get; private set; } public string StatesPath => Config.PathEntries.TastudioStatesAbsolutePath(); @@ -322,7 +322,7 @@ namespace BizHawk.Client.EmuHawk } // Start Scenario 1: A regular movie is active - if (MovieSession.Movie.IsActive() && !(MovieSession.Movie is TasMovie)) + if (MovieSession.Movie.IsActive() && !(MovieSession.Movie is ITasMovie)) { var result = MessageBox.Show("In order to use Tastudio, a new project must be created from the current movie\nThe current movie will be saved and closed, and a new project file will be created\nProceed?", "Convert movie", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (result.IsOk()) @@ -338,7 +338,7 @@ namespace BizHawk.Client.EmuHawk } // Start Scenario 2: A tasproj is already active - else if (MovieSession.Movie.IsActive() && MovieSession.Movie is TasMovie) + else if (MovieSession.Movie.IsActive() && MovieSession.Movie is ITasMovie) { bool result = LoadFile(new FileInfo(CurrentTasMovie.Filename), gotoFrame: Emulator.Frame); if (!result) @@ -375,7 +375,7 @@ namespace BizHawk.Client.EmuHawk return true; } - private void SetTasMovieCallbacks(TasMovie movie) + private void SetTasMovieCallbacks(ITasMovie movie) { movie.ClientSettingsForSave = ClientSettingsForSave; movie.GetClientSettingsOnLoad = GetClientSettingsOnLoad; @@ -628,11 +628,9 @@ namespace BizHawk.Client.EmuHawk return false; } - var newMovie = new TasMovie(startsFromSavestate: startsFromSavestate) - { - Filename = file.FullName, - BindMarkersToInput = Settings.BindMarkersToInput - }; + var newMovie = MovieService.CreateTas(startsFromSavestate: startsFromSavestate); + newMovie.Filename = file.FullName; + newMovie.BindMarkersToInput = Settings.BindMarkersToInput; newMovie.TasStateManager.InvalidateCallback = GreenzoneInvalidated; @@ -666,7 +664,7 @@ namespace BizHawk.Client.EmuHawk SetUpToolStripColumns(); CurrentTasMovie.PropertyChanged += TasMovie_OnPropertyChanged; - CurrentTasMovie.CurrentBranch = CurrentTasMovie.Session.CurrentBranch; + CurrentTasMovie.Branches.Current = CurrentTasMovie.Session.CurrentBranch; BookMarkControl.UpdateTextColumnWidth(); MarkerControl.UpdateTextColumnWidth(); // clear all selections @@ -685,11 +683,9 @@ namespace BizHawk.Client.EmuHawk return; } - var tasMovie = new TasMovie - { - BindMarkersToInput = Settings.BindMarkersToInput, - Filename = DefaultTasProjName() // TODO don't do this, take over any mainform actions that can crash without a filename - }; + var tasMovie = MovieService.CreateTas(); + tasMovie.BindMarkersToInput = Settings.BindMarkersToInput; + tasMovie.Filename = DefaultTasProjName(); // TODO don't do this, take over any mainform actions that can crash without a filename tasMovie.TasStateManager.InvalidateCallback = GreenzoneInvalidated; tasMovie.PropertyChanged += TasMovie_OnPropertyChanged; @@ -721,7 +717,7 @@ namespace BizHawk.Client.EmuHawk TasView.Refresh(); } - private bool HandleMovieLoadStuff(TasMovie movie) + private bool HandleMovieLoadStuff(ITasMovie movie) { WantsToControlStopMovie = false; var result = StartNewMovieWrapper(movie); @@ -733,7 +729,7 @@ namespace BizHawk.Client.EmuHawk WantsToControlStopMovie = true; - CurrentTasMovie.ChangeLog.ClearLog(); + CurrentTasMovie.ChangeLog.Clear(); CurrentTasMovie.ClearChanges(); SetTextProperty(); @@ -742,7 +738,7 @@ namespace BizHawk.Client.EmuHawk return true; } - private bool StartNewMovieWrapper(TasMovie movie) + private bool StartNewMovieWrapper(ITasMovie movie) { _initializing = true; @@ -825,12 +821,14 @@ namespace BizHawk.Client.EmuHawk MainForm.SetMainformMovieInfo(); } + private const string DefaultTasProjectName = "default"; + // Used when starting a new project private string DefaultTasProjName() { return Path.Combine( Config.PathEntries.MovieAbsolutePath(), - $"{TasMovie.DefaultProjectName}.{TasMovie.Extension}"); + $"{DefaultTasProjectName}.{MovieService.TasMovieExtension}"); } // Used for things like SaveFile dialogs to suggest a name to the user @@ -838,7 +836,7 @@ namespace BizHawk.Client.EmuHawk { return Path.Combine( Config.PathEntries.MovieAbsolutePath(), - $"{Global.Game.FilesystemSafeName()}.{TasMovie.Extension}"); + $"{Global.Game.FilesystemSafeName()}.{MovieService.TasMovieExtension}"); } private void SaveTas() @@ -1178,7 +1176,7 @@ namespace BizHawk.Client.EmuHawk } var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop); - if (Path.GetExtension(filePaths[0]) == $".{TasMovie.Extension}") + if (Path.GetExtension(filePaths[0]) == $".{MovieService.TasMovieExtension}") { FileInfo file = new FileInfo(filePaths[0]); if (file.Exists) @@ -1209,7 +1207,7 @@ namespace BizHawk.Client.EmuHawk private bool AutoAdjustInput() { - TasMovieRecord lagLog = CurrentTasMovie[Emulator.Frame - 1]; // Minus one because get frame is +1; + var lagLog = CurrentTasMovie[Emulator.Frame - 1]; // Minus one because get frame is +1; bool isLag = Emulator.AsInputPollable().IsLagFrame; if (lagLog.WasLagged.HasValue) @@ -1222,7 +1220,7 @@ namespace BizHawk.Client.EmuHawk CurrentTasMovie.ChangeLog.IsRecording = false; CurrentTasMovie.RemoveFrame(Emulator.Frame - 1); - CurrentTasMovie.RemoveLagHistory(Emulator.Frame); // Removes from WasLag + CurrentTasMovie.LagLog.RemoveHistoryAt(Emulator.Frame); // Removes from WasLag CurrentTasMovie.ChangeLog.IsRecording = wasRecording; GoToFrame(Emulator.Frame - 1); @@ -1236,7 +1234,7 @@ namespace BizHawk.Client.EmuHawk CurrentTasMovie.ChangeLog.IsRecording = false; CurrentTasMovie.InsertInput(Emulator.Frame - 1, CurrentTasMovie.GetInputLogEntry(Emulator.Frame - 2)); - CurrentTasMovie.InsertLagHistory(Emulator.Frame, true); + CurrentTasMovie.LagLog.InsertHistoryAt(Emulator.Frame, true); CurrentTasMovie.ChangeLog.IsRecording = wasRecording; return true; diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs index 028ca501fa..bf25b973da 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs @@ -13,7 +13,7 @@ namespace BizHawk.Client.EmuHawk private readonly TAStudio _tastudio; private string _lastUndoAction; - private TasMovieChangeLog Log => _tastudio.CurrentTasMovie.ChangeLog; + private IMovieChangeLog Log => _tastudio.CurrentTasMovie.ChangeLog; public UndoHistoryForm(TAStudio owner) { @@ -69,7 +69,7 @@ namespace BizHawk.Client.EmuHawk private void ClearButton_Click(object sender, EventArgs e) { - Log.ClearLog(); + Log.Clear(); UpdateValues(); } @@ -164,7 +164,7 @@ namespace BizHawk.Client.EmuHawk { if (SelectedItem != -1) { - Log.ClearLog(SelectedItem); + Log.Clear(SelectedItem); } UpdateValues();