diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs
index 1593a24edb..4a7f3a9422 100644
--- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs
+++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs
@@ -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;
}
diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs
index 38cd64e404..789beba5c2 100644
--- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs
+++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs
@@ -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
}
}
+ ///
+ /// Begins a batch of edits, for auto-restore purposes. Auto-restore will be delayed until EndBatchEdit is called.
+ ///
+ private void BeginBatchEdit()
+ {
+ _batchEditing = true;
+ }
+ /// Returns true if the input list was redrawn.
+ 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;
+ }
+
///
/// 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.
///
- private void FrameEdited(int frame)
+ /// The frame that was just edited, or the earliest one if multiple were edited.
+ /// Returns true if the input list was redrawn.
+ 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();
}
}
}
diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
index aa5adf686f..2e9e601779 100644
--- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
+++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs
@@ -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);
}
}
diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
index 419b018fd1..c02b17c8a1 100644
--- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
+++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
@@ -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);
- }
- }
-
///
/// 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;
}