Make consecutive recorded frames while unpaused be a single undo action.

This commit is contained in:
SuuperW 2025-07-27 01:03:06 -05:00
parent 136017e67d
commit 6437490137
No known key found for this signature in database
6 changed files with 54 additions and 1 deletions

View File

@ -28,6 +28,12 @@ namespace BizHawk.Client.Common
/// If not already recording a batch, does nothing.
/// </summary>
void EndBatch();
/// <summary>
/// Combine the last two undo actions, making them part of one batch action.
/// </summary>
void MergeLastActions();
/// <summary>
/// Undoes the most recent action batch, if any exist.
/// </summary>
@ -178,6 +184,17 @@ namespace BizHawk.Client.Common
}
}
public void MergeLastActions()
{
Debug.Assert(UndoIndex + 1 == _history.Count, "Don't merge the last actions if they aren't the last actions.");
Debug.Assert(_history.Count > 1, "Don't merge when there aren't actions to merge.");
_history[_history.Count - 2].AddRange(_history[_history.Count - 1]);
_history.RemoveAt(_history.Count - 1);
Names.RemoveAt(Names.Count - 1);
UndoIndex--;
}
public void Undo()
{
if (UndoIndex == -1)

View File

@ -1041,6 +1041,7 @@ namespace BizHawk.Client.EmuHawk
InitializeFpsData();
}
if (value != _emulatorPaused) Tools.OnPauseToggle(value);
_emulatorPaused = value;
}
}

View File

@ -21,6 +21,8 @@ namespace BizHawk.Client.EmuHawk
private int _lastRefresh;
private bool _doPause;
private bool _extended;
private bool _extendNeedsMerge;
private void UpdateProgressBar()
{
@ -55,7 +57,8 @@ namespace BizHawk.Client.EmuHawk
protected override void UpdateBefore()
{
if (CurrentTasMovie.IsAtEnd() && !CurrentTasMovie.IsRecording())
_extended = CurrentTasMovie.IsAtEnd() && !CurrentTasMovie.IsRecording();
if (_extended)
{
CurrentTasMovie.RecordFrame(CurrentTasMovie.Emulator.Frame, MovieSession.StickySource);
}
@ -108,6 +111,18 @@ namespace BizHawk.Client.EmuHawk
protected override void FastUpdateAfter()
{
// Recording multiple frames, or auto-extending the movie, while unpaused should count as a single undo action.
// And do this before stopping the seek, which could puase.
if (!MainForm.EmulatorPaused && (CurrentTasMovie.IsRecording() || _extended))
{
if (_extendNeedsMerge) CurrentTasMovie.ChangeLog.MergeLastActions();
_extendNeedsMerge = true;
}
else
{
_extendNeedsMerge = false;
}
if (_seekingTo != -1 && Emulator.Frame >= _seekingTo)
{
StopSeeking();

View File

@ -890,6 +890,13 @@ namespace BizHawk.Client.EmuHawk
MainForm.TogglePause();
}
public override void OnPauseToggle(bool newPauseState)
{
// Consecutively recorded frames are merged into one undo action, until we pause.
// Then a new undo action should be used.
if (newPauseState) _extendNeedsMerge = false;
}
private void SetSplicer()
{
// TODO: columns selected?

View File

@ -136,5 +136,7 @@ namespace BizHawk.Client.EmuHawk
}
public virtual void HandleHotkeyUpdate() { }
public virtual void OnPauseToggle(bool newPauseState) { }
}
}

View File

@ -804,6 +804,17 @@ namespace BizHawk.Client.EmuHawk
}
}
public void OnPauseToggle(bool newPauseState)
{
foreach (var tool in _tools)
{
if (tool.IsActive && tool is ToolFormBase toolForm)
{
toolForm.OnPauseToggle(newPauseState);
}
}
}
private static readonly IList<string> PossibleToolTypeNames = EmuHawk.ReflectionCache.Types.Select(t => t.AssemblyQualifiedName).ToList();
public bool IsAvailable(Type tool)