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

View File

@ -25,7 +25,9 @@ namespace BizHawk.Client.EmuHawk
private bool _selectionDragState; private bool _selectionDragState;
private bool _suppressContextMenu; private bool _suppressContextMenu;
private int _startRow; private int _startRow;
private int _mouseEditMinFrame = -1; private int _batchEditMinFrame = -1;
private bool _batchEditing;
private bool _editIsFromLua;
// Editing analog input // Editing analog input
private string _axisEditColumn = ""; private string _axisEditColumn = "";
@ -66,14 +68,6 @@ namespace BizHawk.Client.EmuHawk
public AutoPatternBool[] BoolPatterns; public AutoPatternBool[] BoolPatterns;
public AutoPatternAxis[] AxisPatterns; 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) private void StartSeeking(int? frame, bool fromMiddleClick = false)
{ {
if (!frame.HasValue || frame <= Emulator.Frame) if (!frame.HasValue || frame <= Emulator.Frame)
@ -393,6 +387,7 @@ namespace BizHawk.Client.EmuHawk
if (columnName == FrameColumnName) if (columnName == FrameColumnName)
{ {
CurrentTasMovie.Markers.Add(TasView.SelectionEndIndex!.Value, ""); CurrentTasMovie.Markers.Add(TasView.SelectionEndIndex!.Value, "");
RefreshDialog();
} }
else if (columnName != CursorColumnName) else if (columnName != CursorColumnName)
{ {
@ -433,8 +428,6 @@ namespace BizHawk.Client.EmuHawk
FrameEdited(CurrentTasMovie.LastEditedFrame); FrameEdited(CurrentTasMovie.LastEditedFrame);
} }
RefreshDialog();
} }
} }
@ -653,7 +646,6 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.SetBoolStates(firstSel, lastSel - firstSel + 1, buttonName, !allPressed); CurrentTasMovie.SetBoolStates(firstSel, lastSel - firstSel + 1, buttonName, !allPressed);
_boolPaintState = CurrentTasMovie.BoolIsPressed(lastSel, buttonName); _boolPaintState = CurrentTasMovie.BoolIsPressed(lastSel, buttonName);
FrameEdited(CurrentTasMovie.LastEditedFrame); FrameEdited(CurrentTasMovie.LastEditedFrame);
RefreshDialog();
} }
#if false // to match previous behaviour #if false // to match previous behaviour
else if (altOrShift4State is not 0) else if (altOrShift4State is not 0)
@ -668,7 +660,6 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.ToggleBoolState(frame, buttonName); CurrentTasMovie.ToggleBoolState(frame, buttonName);
_boolPaintState = CurrentTasMovie.BoolIsPressed(frame, buttonName); _boolPaintState = CurrentTasMovie.BoolIsPressed(frame, buttonName);
FrameEdited(CurrentTasMovie.LastEditedFrame); FrameEdited(CurrentTasMovie.LastEditedFrame);
RefreshDialog();
} }
} }
else else
@ -685,6 +676,7 @@ namespace BizHawk.Client.EmuHawk
{ {
AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].Reset(); AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].Reset();
CurrentTasMovie.SetAxisState(frame, buttonName, AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].GetNextValue()); CurrentTasMovie.SetAxisState(frame, buttonName, AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].GetNextValue());
FrameEdited(frame);
_patternPaint = true; _patternPaint = true;
} }
else 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> /// <summary>
/// Disables recording mode, ensures we are in the greenzone, and does autorestore if needed. /// 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. /// If a mouse button is down, only tracks the edit so we can do this stuff on mouse up.
/// </summary> /// </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 else
{ {
_mouseEditMinFrame = Math.Min(_mouseEditMinFrame, frame); _batchEditMinFrame = Math.Min(_batchEditMinFrame, frame);
} }
} }
else else
{ {
TastudioPlayMode(true); if (!_editIsFromLua)
{
// Lua users will want to preserve recording mode.
TastudioPlayMode(true);
}
if (Emulator.Frame > frame) if (Emulator.Frame > frame)
{ {
GoToLastEmulatedFrameIfNecessary(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() private void ClearLeftMouseStates()
@ -822,7 +874,6 @@ namespace BizHawk.Client.EmuHawk
{ {
AxisEditRow = -1; AxisEditRow = -1;
FrameEdited(_axisEditRow); FrameEdited(_axisEditRow);
RefreshDialog();
} }
_axisPaintState = 0; _axisPaintState = 0;
_axisEditYPos = -1; _axisEditYPos = -1;
@ -892,10 +943,7 @@ namespace BizHawk.Client.EmuHawk
} }
} }
if (_mouseEditMinFrame != -1) EndBatchEdit(); // We didn't call BeginBatchEdit, but implicitly began one with mouse down. We must explicitly end it.
{
FrameEdited(_mouseEditMinFrame);
}
_suppressContextMenu = false; _suppressContextMenu = false;
} }
@ -1014,6 +1062,7 @@ namespace BizHawk.Client.EmuHawk
} }
SetSplicer(); SetSplicer();
RefreshDialog();
} }
else if (_rightClickFrame != -1) 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 CurrentTasMovie.SetAxisState(i, _startAxisDrawColumn, setVal); // Notice it uses new row, old column, you can only paint across a single column
FrameEdited(CurrentTasMovie.LastEditedFrame); FrameEdited(CurrentTasMovie.LastEditedFrame);
RefreshDialog();
} }
} }
@ -1181,8 +1229,6 @@ namespace BizHawk.Client.EmuHawk
{ {
TasView.MakeIndexVisible(TasView.CurrentCell.RowIndex.Value); // todo: limit scrolling speed TasView.MakeIndexVisible(TasView.CurrentCell.RowIndex.Value); // todo: limit scrolling speed
} }
SetTasViewRowCount();
} }
private void TasView_MouseMove(object sender, MouseEventArgs e) 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) private void TasView_KeyDown(object sender, KeyEventArgs e)
@ -1436,8 +1486,6 @@ namespace BizHawk.Client.EmuHawk
{ {
EditAnalogProgrammatically(e); 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)); var rollbackFrame = CurrentTasMovie.CopyOverInput(TasView.SelectionStartIndex ?? 0, _tasClipboard.Select(static x => x.ControllerState));
if (rollbackFrame > 0) if (rollbackFrame > 0)
{ {
GoToLastEmulatedFrameIfNecessary(rollbackFrame); FrameEdited(rollbackFrame);
DoAutoRestore();
} }
RefreshDialog();
} }
} }
} }
@ -465,15 +462,8 @@ namespace BizHawk.Client.EmuHawk
} }
var selectionStart = TasView.SelectionStartIndex; var selectionStart = TasView.SelectionStartIndex;
var needsToRollback = selectionStart < Emulator.Frame;
CurrentTasMovie.InsertInput(selectionStart ?? 0, _tasClipboard.Select(static x => x.ControllerState)); CurrentTasMovie.InsertInput(selectionStart ?? 0, _tasClipboard.Select(static x => x.ControllerState));
if (needsToRollback) FrameEdited(selectionStart!.Value);
{
GoToLastEmulatedFrameIfNecessary(selectionStart!.Value);
DoAutoRestore();
}
RefreshDialog();
} }
} }
} }
@ -485,7 +475,6 @@ namespace BizHawk.Client.EmuHawk
if (TasView.Focused && TasView.AnyRowsSelected) if (TasView.Focused && TasView.AnyRowsSelected)
{ {
var selectionStart = TasView.SelectionStartIndex; var selectionStart = TasView.SelectionStartIndex;
var needsToRollback = selectionStart < Emulator.Frame;
var rollBackFrame = selectionStart ?? 0; var rollBackFrame = selectionStart ?? 0;
_tasClipboard.Clear(); _tasClipboard.Clear();
@ -508,13 +497,7 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.RemoveFrames(list); CurrentTasMovie.RemoveFrames(list);
SetSplicer(); SetSplicer();
if (needsToRollback) FrameEdited(rollBackFrame);
{
GoToLastEmulatedFrameIfNecessary(rollBackFrame);
DoAutoRestore();
}
RefreshDialog();
} }
} }
@ -536,8 +519,7 @@ namespace BizHawk.Client.EmuHawk
if (needsToRollback) if (needsToRollback)
{ {
GoToLastEmulatedFrameIfNecessary(rollBackFrame); FrameEdited(rollBackFrame);
DoAutoRestore();
} }
RefreshDialog(); RefreshDialog();
@ -549,7 +531,6 @@ namespace BizHawk.Client.EmuHawk
if (TasView.Focused && TasView.AnyRowsSelected) if (TasView.Focused && TasView.AnyRowsSelected)
{ {
var selectionStart = TasView.SelectionStartIndex; var selectionStart = TasView.SelectionStartIndex;
var needsToRollback = selectionStart < Emulator.Frame;
var rollBackFrame = selectionStart ?? 0; var rollBackFrame = selectionStart ?? 0;
if (rollBackFrame >= CurrentTasMovie.InputLogLength) if (rollBackFrame >= CurrentTasMovie.InputLogLength)
{ {
@ -562,13 +543,7 @@ namespace BizHawk.Client.EmuHawk
SetTasViewRowCount(); SetTasViewRowCount();
SetSplicer(); SetSplicer();
if (needsToRollback) FrameEdited(rollBackFrame);
{
GoToLastEmulatedFrameIfNecessary(rollBackFrame);
DoAutoRestore();
}
RefreshDialog();
} }
} }
@ -594,7 +569,6 @@ namespace BizHawk.Client.EmuHawk
{ {
var framesToInsert = TasView.SelectedRows; var framesToInsert = TasView.SelectedRows;
var insertionFrame = Math.Min((TasView.SelectionEndIndex ?? 0) + 1, CurrentTasMovie.InputLogLength); var insertionFrame = Math.Min((TasView.SelectionEndIndex ?? 0) + 1, CurrentTasMovie.InputLogLength);
var needsToRollback = TasView.SelectionStartIndex < Emulator.Frame;
var inputLog = framesToInsert var inputLog = framesToInsert
.Select(frame => CurrentTasMovie.GetInputLogEntry(frame)) .Select(frame => CurrentTasMovie.GetInputLogEntry(frame))
@ -602,13 +576,7 @@ namespace BizHawk.Client.EmuHawk
CurrentTasMovie.InsertInput(insertionFrame, inputLog); CurrentTasMovie.InsertInput(insertionFrame, inputLog);
if (needsToRollback) FrameEdited(insertionFrame);
{
GoToLastEmulatedFrameIfNecessary(insertionFrame);
DoAutoRestore();
}
RefreshDialog();
} }
} }
} }
@ -619,17 +587,9 @@ namespace BizHawk.Client.EmuHawk
{ {
var selectionStart = TasView.SelectionStartIndex; var selectionStart = TasView.SelectionStartIndex;
var insertionFrame = selectionStart ?? 0; var insertionFrame = selectionStart ?? 0;
var needsToRollback = selectionStart < Emulator.Frame;
CurrentTasMovie.InsertEmptyFrame(insertionFrame); CurrentTasMovie.InsertEmptyFrame(insertionFrame);
FrameEdited(insertionFrame);
if (needsToRollback)
{
GoToLastEmulatedFrameIfNecessary(insertionFrame);
DoAutoRestore();
}
RefreshDialog();
} }
} }
@ -651,17 +611,11 @@ namespace BizHawk.Client.EmuHawk
if (TasView.Focused && TasView.AnyRowsSelected) if (TasView.Focused && TasView.AnyRowsSelected)
{ {
var rollbackFrame = TasView.SelectionEndIndex ?? 0; var rollbackFrame = TasView.SelectionEndIndex ?? 0;
var needsToRollback = TasView.SelectionStartIndex < Emulator.Frame;
CurrentTasMovie.Truncate(rollbackFrame); CurrentTasMovie.Truncate(rollbackFrame);
MarkerControl.MarkerInputRoll.TruncateSelection(CurrentTasMovie.Markers.Count - 1); MarkerControl.MarkerInputRoll.TruncateSelection(CurrentTasMovie.Markers.Count - 1);
if (needsToRollback) FrameEdited(rollbackFrame);
{
GoToFrame(rollbackFrame);
}
RefreshDialog();
} }
} }

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