Convert remaining auto-restore points to the new system. Also include refreshing in FrameEdited. Fixes more bugs.

This commit is contained in:
SuuperW 2025-06-08 02:10:29 -05:00
parent ffc50444f9
commit bbf3560bd0
4 changed files with 100 additions and 141 deletions

View File

@ -300,6 +300,11 @@ namespace BizHawk.Client.EmuHawk
[LuaMethod("applyinputchanges", "")]
public void ApplyInputChanges()
{
if (_changeList.Count == 0)
{
return;
}
if (Engaged())
{
if (_luaLibsImpl.IsInInputOrMemoryCallback)
@ -309,7 +314,7 @@ namespace BizHawk.Client.EmuHawk
_luaLibsImpl.IsUpdateSupressed = true;
if (_changeList.Count > 0)
Tastudio.ApiHawkBatchEdit(() =>
{
int size = _changeList.Count;
@ -327,7 +332,7 @@ namespace BizHawk.Client.EmuHawk
Tastudio.CurrentTasMovie.SetAxisState(_changeList[i].Frame, _changeList[i].Button, _changeList[i].ValueAxis);
break;
}
Tastudio.RefreshForInputChange(_changeList[i].Frame);
Tastudio.FrameEdited(_changeList[i].Frame);
break;
case LuaChangeTypes.InsertFrames:
Tastudio.InsertNumFrames(_changeList[i].Frame, _changeList[i].Number);
@ -341,9 +346,7 @@ namespace BizHawk.Client.EmuHawk
}
}
_changeList.Clear();
Tastudio.JumpToGreenzone();
Tastudio.DoAutoRestore();
}
});
_luaLibsImpl.IsUpdateSupressed = false;
}

View File

@ -25,7 +25,9 @@ namespace BizHawk.Client.EmuHawk
private bool _selectionDragState;
private bool _suppressContextMenu;
private int _startRow;
private int _mouseEditMinFrame = -1;
private int _batchEditMinFrame = -1;
private bool _batchEditing;
private bool _editIsFromLua;
// Editing analog input
private string _axisEditColumn = "";
@ -66,14 +68,6 @@ namespace BizHawk.Client.EmuHawk
public AutoPatternBool[] BoolPatterns;
public AutoPatternAxis[] AxisPatterns;
public void JumpToGreenzone(bool OnLeftMouseDown = false)
{
if (Emulator.Frame > CurrentTasMovie.LastEditedFrame)
{
GoToLastEmulatedFrameIfNecessary(CurrentTasMovie.LastEditedFrame, OnLeftMouseDown);
}
}
private void StartSeeking(int? frame, bool fromMiddleClick = false)
{
if (!frame.HasValue || frame <= Emulator.Frame)
@ -393,6 +387,7 @@ namespace BizHawk.Client.EmuHawk
if (columnName == FrameColumnName)
{
CurrentTasMovie.Markers.Add(TasView.SelectionEndIndex!.Value, "");
RefreshDialog();
}
else if (columnName != CursorColumnName)
{
@ -433,8 +428,6 @@ namespace BizHawk.Client.EmuHawk
FrameEdited(CurrentTasMovie.LastEditedFrame);
}
RefreshDialog();
}
}
@ -653,7 +646,6 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.SetBoolStates(firstSel, lastSel - firstSel + 1, buttonName, !allPressed);
_boolPaintState = CurrentTasMovie.BoolIsPressed(lastSel, buttonName);
FrameEdited(CurrentTasMovie.LastEditedFrame);
RefreshDialog();
}
#if false // to match previous behaviour
else if (altOrShift4State is not 0)
@ -668,7 +660,6 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.ToggleBoolState(frame, buttonName);
_boolPaintState = CurrentTasMovie.BoolIsPressed(frame, buttonName);
FrameEdited(CurrentTasMovie.LastEditedFrame);
RefreshDialog();
}
}
else
@ -685,6 +676,7 @@ namespace BizHawk.Client.EmuHawk
{
AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].Reset();
CurrentTasMovie.SetAxisState(frame, buttonName, AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].GetNextValue());
FrameEdited(frame);
_patternPaint = true;
}
else
@ -779,33 +771,93 @@ namespace BizHawk.Client.EmuHawk
}
}
/// <summary>
/// Begins a batch of edits, for auto-restore purposes. Auto-restore will be delayed until EndBatchEdit is called.
/// </summary>
private void BeginBatchEdit()
{
_batchEditing = true;
}
/// <returns>Returns true if the input list was redrawn.</returns>
private bool EndBatchEdit()
{
_batchEditing = false;
if (_batchEditMinFrame != -1)
{
return FrameEdited(_batchEditMinFrame);
}
return false;
}
public void ApiHawkBatchEdit(Action action)
{
// This is only caled from Lua.
_editIsFromLua = true;
BeginBatchEdit();
action();
EndBatchEdit();
_editIsFromLua = false;
}
/// <summary>
/// Disables recording mode, ensures we are in the greenzone, and does autorestore if needed.
/// If a mouse button is down, only tracks the edit so we can do this stuff on mouse up.
/// </summary>
private void FrameEdited(int frame)
/// <param name="frame">The frame that was just edited, or the earliest one if multiple were edited.</param>
/// <returns>Returns true if the input list was redrawn.</returns>
public bool FrameEdited(int frame)
{
if (MouseButtonHeld)
bool needsRefresh = !_batchEditing;
if (MouseButtonHeld || _batchEditing)
{
if (_mouseEditMinFrame == -1)
if (_batchEditMinFrame == -1)
{
_mouseEditMinFrame = frame;
_batchEditMinFrame = frame;
}
else
{
_mouseEditMinFrame = Math.Min(_mouseEditMinFrame, frame);
_batchEditMinFrame = Math.Min(_batchEditMinFrame, frame);
}
}
else
{
TastudioPlayMode(true);
if (!_editIsFromLua)
{
// Lua users will want to preserve recording mode.
TastudioPlayMode(true);
}
if (Emulator.Frame > frame)
{
GoToLastEmulatedFrameIfNecessary(frame);
DoAutoRestore();
if (Settings.AutoRestoreLastPosition && RestorePositionFrame != -1)
{
StartSeeking(RestorePositionFrame);
}
needsRefresh = false; // Refresh will happen via GoToFrame.
}
_mouseEditMinFrame = -1;
_batchEditMinFrame = -1;
}
if (needsRefresh)
{
if (TasView.IsPartiallyVisible(frame) || frame < TasView.FirstVisibleRow)
{
// frame < FirstVisibleRow: Greenzone in visible rows has been invalidated
RefreshDialog();
return true;
}
else if (TasView.RowCount != CurrentTasMovie.InputLogLength + 1)
{
// Row count must always be kept up to date even if last row is not directly visible.
TasView.RowCount = CurrentTasMovie.InputLogLength + 1;
return true;
}
}
return false;
}
private void ClearLeftMouseStates()
@ -822,7 +874,6 @@ namespace BizHawk.Client.EmuHawk
{
AxisEditRow = -1;
FrameEdited(_axisEditRow);
RefreshDialog();
}
_axisPaintState = 0;
_axisEditYPos = -1;
@ -892,10 +943,7 @@ namespace BizHawk.Client.EmuHawk
}
}
if (_mouseEditMinFrame != -1)
{
FrameEdited(_mouseEditMinFrame);
}
EndBatchEdit(); // We didn't call BeginBatchEdit, but implicitly began one with mouse down. We must explicitly end it.
_suppressContextMenu = false;
}
@ -1014,6 +1062,7 @@ namespace BizHawk.Client.EmuHawk
}
SetSplicer();
RefreshDialog();
}
else if (_rightClickFrame != -1)
{
@ -1171,7 +1220,6 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.SetAxisState(i, _startAxisDrawColumn, setVal); // Notice it uses new row, old column, you can only paint across a single column
FrameEdited(CurrentTasMovie.LastEditedFrame);
RefreshDialog();
}
}
@ -1181,8 +1229,6 @@ namespace BizHawk.Client.EmuHawk
{
TasView.MakeIndexVisible(TasView.CurrentCell.RowIndex.Value); // todo: limit scrolling speed
}
SetTasViewRowCount();
}
private void TasView_MouseMove(object sender, MouseEventArgs e)
@ -1405,7 +1451,11 @@ namespace BizHawk.Client.EmuHawk
}
}
RefreshDialog();
bool didRefresh = EndBatchEdit();
if (!didRefresh && (prevTyped != _axisTypedValue || !AxisEditingMode))
{
RefreshDialog();
}
}
private void TasView_KeyDown(object sender, KeyEventArgs e)
@ -1436,8 +1486,6 @@ namespace BizHawk.Client.EmuHawk
{
EditAnalogProgrammatically(e);
}
RefreshDialog();
}
}
}

View File

@ -425,11 +425,8 @@ namespace BizHawk.Client.EmuHawk
var rollbackFrame = CurrentTasMovie.CopyOverInput(TasView.SelectionStartIndex ?? 0, _tasClipboard.Select(static x => x.ControllerState));
if (rollbackFrame > 0)
{
GoToLastEmulatedFrameIfNecessary(rollbackFrame);
DoAutoRestore();
FrameEdited(rollbackFrame);
}
RefreshDialog();
}
}
}
@ -465,15 +462,8 @@ namespace BizHawk.Client.EmuHawk
}
var selectionStart = TasView.SelectionStartIndex;
var needsToRollback = selectionStart < Emulator.Frame;
CurrentTasMovie.InsertInput(selectionStart ?? 0, _tasClipboard.Select(static x => x.ControllerState));
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(selectionStart!.Value);
DoAutoRestore();
}
RefreshDialog();
FrameEdited(selectionStart!.Value);
}
}
}
@ -485,7 +475,6 @@ namespace BizHawk.Client.EmuHawk
if (TasView.Focused && TasView.AnyRowsSelected)
{
var selectionStart = TasView.SelectionStartIndex;
var needsToRollback = selectionStart < Emulator.Frame;
var rollBackFrame = selectionStart ?? 0;
_tasClipboard.Clear();
@ -508,13 +497,7 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.RemoveFrames(list);
SetSplicer();
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(rollBackFrame);
DoAutoRestore();
}
RefreshDialog();
FrameEdited(rollBackFrame);
}
}
@ -536,8 +519,7 @@ namespace BizHawk.Client.EmuHawk
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(rollBackFrame);
DoAutoRestore();
FrameEdited(rollBackFrame);
}
RefreshDialog();
@ -549,7 +531,6 @@ namespace BizHawk.Client.EmuHawk
if (TasView.Focused && TasView.AnyRowsSelected)
{
var selectionStart = TasView.SelectionStartIndex;
var needsToRollback = selectionStart < Emulator.Frame;
var rollBackFrame = selectionStart ?? 0;
if (rollBackFrame >= CurrentTasMovie.InputLogLength)
{
@ -562,13 +543,7 @@ namespace BizHawk.Client.EmuHawk
SetTasViewRowCount();
SetSplicer();
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(rollBackFrame);
DoAutoRestore();
}
RefreshDialog();
FrameEdited(rollBackFrame);
}
}
@ -594,7 +569,6 @@ namespace BizHawk.Client.EmuHawk
{
var framesToInsert = TasView.SelectedRows;
var insertionFrame = Math.Min((TasView.SelectionEndIndex ?? 0) + 1, CurrentTasMovie.InputLogLength);
var needsToRollback = TasView.SelectionStartIndex < Emulator.Frame;
var inputLog = framesToInsert
.Select(frame => CurrentTasMovie.GetInputLogEntry(frame))
@ -602,13 +576,7 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.InsertInput(insertionFrame, inputLog);
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(insertionFrame);
DoAutoRestore();
}
RefreshDialog();
FrameEdited(insertionFrame);
}
}
}
@ -619,17 +587,9 @@ namespace BizHawk.Client.EmuHawk
{
var selectionStart = TasView.SelectionStartIndex;
var insertionFrame = selectionStart ?? 0;
var needsToRollback = selectionStart < Emulator.Frame;
CurrentTasMovie.InsertEmptyFrame(insertionFrame);
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(insertionFrame);
DoAutoRestore();
}
RefreshDialog();
FrameEdited(insertionFrame);
}
}
@ -651,17 +611,11 @@ namespace BizHawk.Client.EmuHawk
if (TasView.Focused && TasView.AnyRowsSelected)
{
var rollbackFrame = TasView.SelectionEndIndex ?? 0;
var needsToRollback = TasView.SelectionStartIndex < Emulator.Frame;
CurrentTasMovie.Truncate(rollbackFrame);
MarkerControl.MarkerInputRoll.TruncateSelection(CurrentTasMovie.Markers.Count - 1);
if (needsToRollback)
{
GoToFrame(rollbackFrame);
}
RefreshDialog();
FrameEdited(rollbackFrame);
}
}

View File

@ -800,28 +800,12 @@ namespace BizHawk.Client.EmuHawk
}
}
public void RefreshForInputChange(int firstChangedFrame)
{
if (TasView.IsPartiallyVisible(firstChangedFrame) || firstChangedFrame < TasView.FirstVisibleRow)
{
RefreshDialog();
}
}
private void SetTasViewRowCount()
{
TasView.RowCount = CurrentTasMovie.InputLogLength + 1;
_lastRefresh = Emulator.Frame;
}
public void DoAutoRestore()
{
if (Settings.AutoRestoreLastPosition && RestorePositionFrame != -1)
{
StartSeeking(RestorePositionFrame);
}
}
/// <summary>
/// Get a savestate prior to the previous frame so code following the call can frame advance and have a framebuffer.
/// If frame is 0, return the initial state.
@ -875,19 +859,8 @@ namespace BizHawk.Client.EmuHawk
{
if (insertionFrame <= CurrentTasMovie.InputLogLength)
{
var needsToRollback = TasView.SelectionStartIndex < Emulator.Frame;
CurrentTasMovie.InsertEmptyFrame(insertionFrame, numberOfFrames);
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(insertionFrame);
DoAutoRestore();
}
else
{
RefreshForInputChange(insertionFrame);
}
FrameEdited(insertionFrame);
}
}
@ -899,16 +872,7 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.RemoveFrames(framesToRemove);
SetSplicer();
var needsToRollback = beginningFrame < Emulator.Frame;
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(beginningFrame);
DoAutoRestore();
}
else
{
RefreshForInputChange(beginningFrame);
}
FrameEdited(beginningFrame);
}
}
@ -916,22 +880,13 @@ namespace BizHawk.Client.EmuHawk
{
if (beginningFrame < CurrentTasMovie.InputLogLength)
{
var needsToRollback = TasView.SelectionStartIndex < Emulator.Frame;
int last = Math.Min(beginningFrame + numberOfFrames, CurrentTasMovie.InputLogLength);
for (int i = beginningFrame; i < last; i++)
{
CurrentTasMovie.ClearFrame(i);
}
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(beginningFrame);
DoAutoRestore();
}
else
{
RefreshForInputChange(beginningFrame);
}
FrameEdited(beginningFrame);
}
}
@ -1038,8 +993,7 @@ namespace BizHawk.Client.EmuHawk
}
CurrentTasMovie.ChangeLog.IsRecording = wasRecording;
GoToLastEmulatedFrameIfNecessary(Emulator.Frame - 1);
DoAutoRestore();
FrameEdited(Emulator.Frame - 1);
return true;
}