diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs index d74861b92df..887e2c1dd37 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs @@ -60,7 +60,10 @@ public interface IMovieChangeLog /// /// Undoes the most recent action batch, if any exist. /// - void Undo(); + /// If given, as many actions will be undone as needed to make the action + /// of the given ID the most recent action. The action with the given ID will not be undone. + /// + void Undo(int? untilId = null); /// /// Redoes the most recent undo, if any exist. @@ -248,13 +251,26 @@ public bool MergeActions(int action1, int action2) return true; } - public void Undo() + public void Undo(int? untilId = null) { if (UndoIndex == -1) { return; } + if (untilId != null) + { + int id = untilId.Value; + _movie.SingleInvalidation(() => + { + while (UndoIndex >= 0 && id < _history[UndoIndex].id) + { + Undo(); + } + }); + return; + } + List batch = _history[UndoIndex].actions; UndoIndex--; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs index f52b07f6133..b3c1114f12c 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs @@ -1,7 +1,6 @@ #nullable enable using System.Collections.Generic; -using System.Diagnostics; using BizHawk.Common; using BizHawk.Common.CollectionExtensions; @@ -106,7 +105,8 @@ public override void Add(Cell item) var i = _list.BinarySearch(item); if (i >= 0) { - Debug.Assert(false, $"{nameof(CellList)}'s distinctness invariant was almost broken! CellList.Add({(item is null ? "null" : item.ToString())})"); + // We can end up adding cells that are already selected pretty easily, by combining Alt multi-selection with Shift range-selection. + // System.Diagnostics.Debug.Assert(false, $"{nameof(CellList)}'s distinctness invariant was almost broken! CellList.Add({(item is null ? "null" : item.ToString())})"); return; } _list.Insert(~i, item); diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs index 0034e9519c3..2a39bf073f1 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs @@ -425,6 +425,12 @@ public int HoverInterval [Category("Virtual")] public event QueryFrameLagHandler QueryFrameLag; + /// + /// Fires when a cell that can be selected is clicked. Return null to use default selection logic. + /// + [Category("Mouse")] + public event QueryShouldSelectCellHandler QueryShouldSelectCell; + /// /// Fires when the mouse moves from one cell to another (including column header cells) /// @@ -502,6 +508,11 @@ public int HoverInterval /// public delegate bool QueryFrameLagHandler(int index, bool hideWasLag); + /// + /// Check if clicking the current cell should select it. + /// + public delegate bool? QueryShouldSelectCellHandler(MouseButtons button); + public delegate void CellChangeEventHandler(object sender, CellEventArgs e); public delegate void HoverEventHandler(object sender, CellEventArgs e); @@ -1115,7 +1126,6 @@ protected override void OnMouseLeave(EventArgs e) base.OnMouseLeave(e); } - // TODO add query callback of whether to select the cell or not protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) @@ -1140,17 +1150,37 @@ protected override void OnMouseDown(MouseEventArgs e) { RightButtonHeld = true; } + + // In the case that we have a context menu already open, we must manually update the CurrentCell as MouseMove isn't triggered while it is open. + if (AllowRightClickSelection && CurrentCell == null) + OnMouseMove(e); + } + + bool shouldSelect = false; + bool useDefaultSelection = true; + if (IsHoveringOnDataCell) + { + if (QueryShouldSelectCell != null) + { + bool? result = QueryShouldSelectCell(e.Button); + shouldSelect = result != false; + useDefaultSelection = result == null; + } + else + { + shouldSelect = true; + } } if (e.Button == MouseButtons.Left) { - if (IsHoveringOnDataCell) + if (shouldSelect) { if (ModifierKeys == Keys.Alt) { // do marker drag here } - else if (ModifierKeys is Keys.Shift && CurrentCell.Column! is { Type: ColumnType.Text } col) + else if (ModifierKeys is Keys.Shift && (!useDefaultSelection || CurrentCell.Column!.Type is ColumnType.Text)) { if (_selectedItems.Count is not 0) { @@ -1182,7 +1212,7 @@ protected override void OnMouseDown(MouseEventArgs e) additionEndExcl = targetRow + 1; } } - for (var i = additionStart; i < additionEndExcl; i++) SelectCell(new() { RowIndex = i, Column = col }); + for (var i = additionStart; i < additionEndExcl; i++) SelectCell(new() { RowIndex = i, Column = CurrentCell.Column }); } } else @@ -1195,7 +1225,7 @@ protected override void OnMouseDown(MouseEventArgs e) SelectCell(CurrentCell); } } - else if (ModifierKeys is Keys.Control && CurrentCell.Column!.Type is ColumnType.Text) + else if (ModifierKeys is Keys.Control && (!useDefaultSelection || CurrentCell.Column!.Type is ColumnType.Text)) { SelectCell(CurrentCell, toggle: true); } @@ -1213,11 +1243,7 @@ protected override void OnMouseDown(MouseEventArgs e) if (AllowRightClickSelection && e.Button == MouseButtons.Right) { - // In the case that we have a context menu already open, we must manually update the CurrentCell as MouseMove isn't triggered while it is open. - if (CurrentCell == null) - OnMouseMove(e); - - if (!IsHoveringOnColumnCell) + if (shouldSelect) { // If this cell is not currently selected, clear and select if (!_selectedItems.Contains(CurrentCell)) diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs index b3d1f55c246..2d2fd19072d 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs @@ -1,8 +1,10 @@ +using System.Diagnostics; using System.Drawing; using System.Linq; using System.Windows.Forms; using System.Collections.Generic; using System.Globalization; + using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Client.Common; @@ -18,7 +20,6 @@ public partial class TAStudio private string _startAxisDrawColumn = ""; private bool _boolPaintState; private int _axisPaintState; - private int _axisBackupState; private bool _patternPaint; private bool _startCursorDrag; private bool _startSelectionDrag; @@ -29,22 +30,59 @@ public partial class TAStudio private bool _batchEditing; // Editing analog input - private string _axisEditColumn = ""; - private int _axisEditRow = -1; - private string _axisTypedValue; - private int _axisEditYPos = -1; - private int AxisEditRow + private string/*?*/ __axisEditColumn = null; // __ do not access directly + private string/*?*/ AxisEditColumn { + get => __axisEditColumn; set { - _axisEditRow = value; - TasView.SuspendHotkeys = AxisEditingMode; + // If we're changing column, exit axis editing mode first. + if (AxisEditingMode && value != null) __axisEditColumn = null; + + __axisEditColumn = value; + _axisEditYPos = -1; + + if (AxisEditingMode) + { + _axisTypedValue = ""; + _didAxisType = false; + _axisRestoreId = CurrentTasMovie.ChangeLog.MostRecentId; + TasView.SuspendHotkeys = true; + } + else + { + if (_didAxisType) + { + _didAxisType = false; + CurrentTasMovie.ChangeLog.EndBatch(); + } + TasView.SuspendHotkeys = false; + } } } - public bool AxisEditingMode => _axisEditRow != -1; + private string _axisTypedValue = ""; + private bool _didAxisType; + private int _axisEditYPos = -1; + private int _axisRestoreId; + + /// + /// Begin editing an axis value by dragging the mouse. + /// + /// The initial vertical position of the cursor. + private void BeginAxisMouseEdit(int yPos) + { + Debug.Assert(AxisEditingMode, "Don't begin axis mouse edit outside of axis editing mode."); + + _axisEditYPos = yPos; + _axisTypedValue = ""; + _didAxisType = false; + _axisRestoreId = CurrentTasMovie.ChangeLog.MostRecentId; + + CurrentTasMovie.ChangeLog.BeginNewBatch($"Axis mouse edit, frame {TasView.SelectedRows.First()}"); + } - private readonly List _extraAxisRows = new List(); + public bool AxisEditingMode => AxisEditColumn != null; // Right-click dragging private string[] _rightClickInput; @@ -189,9 +227,7 @@ private void TasView_QueryItemBkColor(int index, RollColumn column, ref Color co color = Color.FromArgb(0x60, 0xFF, 0xFF, 0xFF); } } - else if (AxisEditingMode - && (index == _axisEditRow || _extraAxisRows.Contains(index)) - && columnName == _axisEditColumn) + else if (columnName == AxisEditColumn && TasView.IsRowSelected(index)) { color = Palette.AnalogEdit_Col; } @@ -250,6 +286,31 @@ private void TasView_QueryRowBkColor(int index, ref Color color) } } + private bool? TasView_QueryShouldSelect(MouseButtons button) + { + if (AxisEditingMode) + { + if (ModifierKeys == Keys.Shift || ModifierKeys == Keys.Control) + { + // This just makes it easier to select multiple rows with axis editing mode, by allowing multiple row selection when clicking columns that aren't the frame column. + return true; + } + else if (TasView.CurrentCell.Column.Name == AxisEditColumn && TasView.IsRowSelected(TasView.CurrentCell.RowIndex.Value)) + { + // We will start editing via mouse, so don't unselect if we have multiple selected rows. + return false; + } + else + { + // Exit axis editing mode (ideally we wouldn't change state in the query method, but we can't do this on mouse down because the selection will have already changed) + AxisEditColumn = null; + SetTasViewRowCount(); + } + } + + return null; + } + private readonly string[] _formatCache = Enumerable.Range(1, 10).Select(i => $"D{i}").ToArray(); /// with leading zeroes such that every frame in the movie will be printed with the same number of digits @@ -294,12 +355,10 @@ private void TasView_QueryItemText(int index, RollColumn column, out string text else if (column.Type is ColumnType.Boolean or ColumnType.Axis) { // Display typed float value (string "-" can't be parsed, so CurrentTasMovie.DisplayValue can't return it) - if ((index == _axisEditRow || _extraAxisRows.Contains(index)) - && columnName == _axisEditColumn) + bool axisEditing = columnName == AxisEditColumn && TasView.IsRowSelected(index); + if (axisEditing && _didAxisType) { - text = _axisTypedValue.Length == 0 - ? _axisBackupState.ToString() - : _axisTypedValue; + text = _axisTypedValue; } else if (index < CurrentTasMovie.InputLogLength) { @@ -307,7 +366,7 @@ private void TasView_QueryItemText(int index, RollColumn column, out string text if (column.Type == ColumnType.Axis) { // feos: this could be cached, but I don't notice any slowdown this way either - if (text == ((float) ControllerType.Axes[columnName].Neutral).ToString(NumberFormatInfo.InvariantInfo)) + if (!axisEditing && text == ((float) ControllerType.Axes[columnName].Neutral).ToString(NumberFormatInfo.InvariantInfo)) { text = ""; } @@ -512,39 +571,17 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) { _leftButtonHeld = true; - // SuuperW: Exit axis editing mode, or re-enter mouse editing if (AxisEditingMode) { if (ModifierKeys is Keys.Control or Keys.Shift) { - _extraAxisRows.Clear(); - _extraAxisRows.AddRange(TasView.SelectedRows); - _startSelectionDrag = true; - _selectionDragState = TasView.IsRowSelected(frame); - return; - } - - if (_axisEditColumn != buttonName - || !(_axisEditRow == frame || _extraAxisRows.Contains(frame))) - { - _extraAxisRows.Clear(); - AxisEditRow = -1; - SetTasViewRowCount(); + // User was selecting additional rows. } else { - if (_extraAxisRows.Contains(frame)) - { - _extraAxisRows.Clear(); - AxisEditRow = frame; - SetTasViewRowCount(); - } - - _axisEditYPos = e.Y; - _axisPaintState = CurrentTasMovie.GetAxisState(frame, buttonName); - - return; + BeginAxisMouseEdit(e.Y); } + return; } if (targetCol.Name is CursorColumnName) @@ -652,18 +689,14 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) } else // Double-click enters axis editing mode { - if (_axisEditColumn == buttonName && _axisEditRow == frame) + if (AxisEditColumn != null && (AxisEditColumn != buttonName || !TasView.IsRowSelected(frame))) { - AxisEditRow = -1; + AxisEditColumn = null; } else { - CurrentTasMovie.ChangeLog.BeginNewBatch($"Axis Edit: {frame}"); - _axisEditColumn = buttonName; - AxisEditRow = frame; - _axisTypedValue = ""; - _axisEditYPos = e.Y; - _axisBackupState = CurrentTasMovie.GetAxisState(_axisEditRow, _axisEditColumn); + AxisEditColumn = buttonName; + BeginAxisMouseEdit(e.Y); } RefreshDialog(); @@ -731,14 +764,6 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) } } - /// - /// 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() { @@ -874,20 +899,13 @@ private void ClearLeftMouseStates() _startAxisDrawColumn = ""; TasView.ReleaseCurrentCell(); - // Exit axis editing if value was changed with cursor - if (AxisEditingMode && _axisPaintState != CurrentTasMovie.GetAxisState(_axisEditRow, _axisEditColumn)) - { - AxisEditRow = -1; - } - _axisPaintState = 0; - _axisEditYPos = -1; + CurrentTasMovie.ChangeLog.EndBatch(); - if (!AxisEditingMode) - { - CurrentTasMovie.ChangeLog?.EndBatch(); - } + _axisEditYPos = -1; // exit mouse edit mode MainForm.BlockFrameAdvance = false; + + RefreshDialog(); // Even if no edits happened, the undo form may need updating because we potentially ended a batch. } private void TasView_MouseUp(object sender, MouseEventArgs e) @@ -925,15 +943,7 @@ private void TasView_MouseUp(object sender, MouseEventArgs e) } else if (e.Button == MouseButtons.Left) { - if (AxisEditingMode && ModifierKeys is Keys.Control or Keys.Shift) - { - _leftButtonHeld = false; - _startSelectionDrag = false; - } - else - { - ClearLeftMouseStates(); - } + ClearLeftMouseStates(); } if (e.Button == MouseButtons.Right) @@ -1070,10 +1080,6 @@ private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e { if (!TasView.IsRowSelected(i)) TasView.SelectRow(i, _selectionDragState); - if (AxisEditingMode && ModifierKeys is Keys.Control or Keys.Shift) - { - _extraAxisRows.SetMembership(i, shouldBeMember: _selectionDragState); - } } SetSplicer(); @@ -1266,19 +1272,14 @@ private void AxisPaint(int frame, int startVal, int endVal) private void TasView_MouseMove(object sender, MouseEventArgs e) { // For axis editing - if (AxisEditingMode) + if (_axisEditYPos == -1) { - int increment = (_axisEditYPos - e.Y) / 4; - if (_axisEditYPos == -1) - { - return; - } - - var value = (_axisPaintState + increment).ConstrainWithin(ControllerType.Axes[_axisEditColumn].Range); - CurrentTasMovie.SetAxisState(_axisEditRow, _axisEditColumn, value); - _axisTypedValue = value.ToString(); - RefreshDialog(); + return; } + + int increment = (_axisEditYPos - e.Y) / 4; + AnalogChangeBy(increment); + _axisEditYPos -= increment * 4; } private void TasView_SelectedIndexChanged(object sender, EventArgs e) @@ -1288,50 +1289,74 @@ private void TasView_SelectedIndexChanged(object sender, EventArgs e) public void AnalogIncrementByOne() { - if (AxisEditingMode) - { - EditAnalogProgrammatically(new KeyEventArgs(Keys.Up)); - } + AnalogChangeBy(1); } public void AnalogDecrementByOne() { - if (AxisEditingMode) - { - EditAnalogProgrammatically(new KeyEventArgs(Keys.Down)); - } + AnalogChangeBy(-1); } public void AnalogIncrementByTen() { - if (AxisEditingMode) - { - EditAnalogProgrammatically(new KeyEventArgs(Keys.Up | Keys.Shift)); - } + AnalogChangeBy(10); } public void AnalogDecrementByTen() { - if (AxisEditingMode) + AnalogChangeBy(-10); + } + + private void AnalogChangeBy(int change) + { + if (!AxisEditingMode) return; + + if (_didAxisType) { - EditAnalogProgrammatically(new KeyEventArgs(Keys.Down | Keys.Shift)); + _didAxisType = false; + CurrentTasMovie.ChangeLog.EndBatch(); } + + bool batch = CurrentTasMovie.ChangeLog.BeginNewBatch($"Axis change by {change}, frame {TasView.SelectedRows.First()}", true); + CurrentTasMovie.SingleInvalidation(() => + { + foreach (int frame in TasView.SelectedRows) + { + int value = CurrentTasMovie.GetAxisState(frame, AxisEditColumn) + change; + value = value.ConstrainWithin(ControllerType.Axes[AxisEditColumn].Range); + CurrentTasMovie.SetAxisState(frame, AxisEditColumn, value); + _axisTypedValue = value.ToString(); // Typing with multiple rows selected has undefined behavior if the values do not all match. + } + }); + if (batch) CurrentTasMovie.ChangeLog.EndBatch(); + + RefreshDialog(); } public void AnalogMax() { - if (AxisEditingMode) + if (!AxisEditingMode) return; + + int value = ControllerType.Axes[AxisEditColumn].Max; + foreach (int frame in TasView.SelectedRows) { - EditAnalogProgrammatically(new KeyEventArgs(Keys.Right)); + CurrentTasMovie.SetAxisState(frame, AxisEditColumn, value); } + _axisTypedValue = value.ToString(); + RefreshDialog(); } public void AnalogMin() { - if (AxisEditingMode) + if (!AxisEditingMode) return; + + int value = ControllerType.Axes[AxisEditColumn].Min; + foreach (int frame in TasView.SelectedRows) { - EditAnalogProgrammatically(new KeyEventArgs(Keys.Left)); + CurrentTasMovie.SetAxisState(frame, AxisEditColumn, value); } + _axisTypedValue = value.ToString(); + RefreshDialog(); } public void EditAnalogProgrammatically(KeyEventArgs e) @@ -1341,146 +1366,91 @@ public void EditAnalogProgrammatically(KeyEventArgs e) return; } - // TODO: properly handle axis editing batches - BeginBatchEdit(); - - int value = CurrentTasMovie.GetAxisState(_axisEditRow, _axisEditColumn); string prevTyped = _axisTypedValue; + AxisSpec axis = ControllerType.Axes[AxisEditColumn]; - var range = ControllerType.Axes[_axisEditColumn]; - - // feos: typing past max digits overwrites existing value, not touching the sign - // but doesn't handle situations where the range is like -50 through 100, where minimum is negative and has less digits - // it just uses 3 as maxDigits there too, leaving room for typing impossible values (that are still ignored by the game and then clamped) - int maxDigits = range.MaxDigits; - int curDigits = _axisTypedValue.Length; - string curMinus; - if (_axisTypedValue.StartsWith('-')) + int charToType = -1; + if (e.KeyCode is >= Keys.D0 and <= Keys.D9) { - curDigits -= 1; - curMinus = "-"; + charToType = e.KeyCode - Keys.D0; } - else + else if (e.KeyCode is >= Keys.NumPad0 and <= Keys.NumPad9) { - curMinus = ""; + charToType = e.KeyCode - Keys.NumPad0; } - if (e.KeyCode == Keys.Right) + if (charToType != -1) { - value = range.Max; - _axisTypedValue = value.ToString(NumberFormatInfo.InvariantInfo); - } - else if (e.KeyCode == Keys.Left) - { - value = range.Min; - _axisTypedValue = value.ToString(NumberFormatInfo.InvariantInfo); - } - else if (e.KeyCode is >= Keys.D0 and <= Keys.D9) - { - if (curDigits >= maxDigits) + if ((_axisTypedValue.StartsWith('-') && _axisTypedValue.Length < axis.Min.ToString().Length) + || (!_axisTypedValue.StartsWith('-') && _axisTypedValue.Length < axis.Max.ToString().Length)) { - _axisTypedValue = curMinus; + _axisTypedValue += charToType; } - - _axisTypedValue += e.KeyCode - Keys.D0; } - else if (e.KeyCode is >= Keys.NumPad0 and <= Keys.NumPad9) + else if (e.KeyCode is Keys.OemMinus or Keys.Subtract) { - if (curDigits >= maxDigits) + if (axis.Min < 0) { - _axisTypedValue = curMinus; + _axisTypedValue = _axisTypedValue.StartsWith('-') + ? _axisTypedValue.Substring(startIndex: 1) + : $"-{_axisTypedValue}"; } - - _axisTypedValue += e.KeyCode - Keys.NumPad0; - } - else if (e.KeyCode is Keys.OemMinus or Keys.Subtract) - { - _axisTypedValue = _axisTypedValue.StartsWith('-') - ? _axisTypedValue.Substring(startIndex: 1) - : $"-{_axisTypedValue}"; } else if (e.KeyCode == Keys.Back) { - if (_axisTypedValue.Length is 0) // Very first key press is backspace? + if (!_didAxisType) { - _axisTypedValue = value.ToString(NumberFormatInfo.InvariantInfo); + _axisTypedValue = CurrentTasMovie.GetAxisState(TasView.SelectedRows.First(), AxisEditColumn).ToString(); + _didAxisType = true; + } + if (_axisTypedValue.Length != 0) + { + _axisTypedValue = _axisTypedValue.Substring(startIndex: 0, length: _axisTypedValue.Length - 1); // drop last char } - - _axisTypedValue = _axisTypedValue.Substring(startIndex: 0, length: _axisTypedValue.Length - 1); // drop last char - if (!int.TryParse(_axisTypedValue, out value)) value = 0; } else if (e.KeyCode == Keys.Enter) { - _axisEditYPos = -1; - AxisEditRow = -1; + AxisEditColumn = null; } else if (e.KeyCode == Keys.Escape) { - _axisEditYPos = -1; - - if (_axisBackupState != _axisPaintState) - { - CurrentTasMovie.SetAxisState(_axisEditRow, _axisEditColumn, _axisBackupState); - } - - AxisEditRow = -1; + AxisEditColumn = null; + CurrentTasMovie.ChangeLog.Undo(_axisRestoreId); } - else - { - int changeBy = 0; - if (e.KeyCode == Keys.Up) - { - changeBy = 1; - } - else if (e.KeyCode == Keys.Down) - { - changeBy = -1; - } - if (e.Modifiers == Keys.Shift) - { - changeBy *= 10; - } - - value += changeBy; - if (changeBy != 0) - { - _axisTypedValue = value.ToString(NumberFormatInfo.InvariantInfo); - } - } - - if (!AxisEditingMode) - { - CurrentTasMovie.ChangeLog.EndBatch(); - } - else + if (_axisTypedValue != prevTyped) { + CurrentTasMovie.ChangeLog.BeginNewBatch($"Axis edit: {TasView.SelectedRows.First()}", true); + _didAxisType = true; + + int value; if (_axisTypedValue.Length is 0) { - if (prevTyped.Length is not 0) - { - value = ControllerType.Axes[_axisEditColumn].Neutral; - CurrentTasMovie.SetAxisState(_axisEditRow, _axisEditColumn, value); - } + value = axis.Neutral; } else { if (int.TryParse(_axisTypedValue, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out value)) // String "-" can't be parsed. { - value = value.ConstrainWithin(range.Range); - - CurrentTasMovie.SetAxisState(_axisEditRow, _axisEditColumn, value); + value = value.ConstrainWithin(axis.Range); + } + else + { + value = 0; } } - foreach (int row in _extraAxisRows) + CurrentTasMovie.SingleInvalidation(() => { - CurrentTasMovie.SetAxisState(row, _axisEditColumn, value); - } + foreach (int row in TasView.SelectedRows) + { + CurrentTasMovie.SetAxisState(row, AxisEditColumn, value); + } + }); } - bool didRefresh = EndBatchEdit(); - if (!didRefresh && (prevTyped != _axisTypedValue || !AxisEditingMode)) + // We (probably) need a refresh if the typed value changed or we've exited axis editing mode. + if (prevTyped != _axisTypedValue || !AxisEditingMode) { RefreshDialog(); } @@ -1498,11 +1468,7 @@ private void TasView_KeyDown(object sender, KeyEventArgs e) GoToFrame(CurrentTasMovie.InputLogLength-1); } - if (AxisEditingMode - && e.KeyCode != Keys.Right - && e.KeyCode != Keys.Left - && e.KeyCode != Keys.Up - && e.KeyCode != Keys.Down) + if (AxisEditingMode) { EditAnalogProgrammatically(e); } diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs index e5824157dbd..e763b4bbda7 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs @@ -168,6 +168,7 @@ public TAStudio() TasView.QueryRowBkColor += TasView_QueryRowBkColor; TasView.QueryItemIcon += TasView_QueryItemIcon; TasView.QueryFrameLag += TasView_QueryFrameLag; + TasView.QueryShouldSelectCell += TasView_QueryShouldSelect; TasView.PointedCellChanged += TasView_PointedCellChanged; TasView.MouseLeave += TAStudio_MouseLeave;