mirror of
https://github.com/ppy/osu.git
synced 2024-12-05 10:33:22 +08:00
fix mix changehandler and command handler
This commit is contained in:
parent
8cbd40f0e8
commit
75eefcfc9b
@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private readonly List<byte[]> savedStates = new List<byte[]>();
|
||||
|
||||
private int currentState = -1;
|
||||
public int CurrentState { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// A SHA-2 hash representing the current visible editor state.
|
||||
@ -38,7 +38,7 @@ namespace osu.Game.Screens.Edit
|
||||
{
|
||||
ensureStateSaved();
|
||||
|
||||
using (var stream = new MemoryStream(savedStates[currentState]))
|
||||
using (var stream = new MemoryStream(savedStates[CurrentState]))
|
||||
return stream.ComputeSHA2Hash();
|
||||
}
|
||||
}
|
||||
@ -71,17 +71,17 @@ namespace osu.Game.Screens.Edit
|
||||
byte[] newState = stream.ToArray();
|
||||
|
||||
// if the previous state is binary equal we don't need to push a new one, unless this is the initial state.
|
||||
if (savedStates.Count > 0 && newState.SequenceEqual(savedStates[currentState])) return;
|
||||
if (savedStates.Count > 0 && newState.SequenceEqual(savedStates[CurrentState])) return;
|
||||
|
||||
if (currentState < savedStates.Count - 1)
|
||||
savedStates.RemoveRange(currentState + 1, savedStates.Count - currentState - 1);
|
||||
if (CurrentState < savedStates.Count - 1)
|
||||
savedStates.RemoveRange(CurrentState + 1, savedStates.Count - CurrentState - 1);
|
||||
|
||||
if (savedStates.Count > MAX_SAVED_STATES)
|
||||
savedStates.RemoveAt(0);
|
||||
|
||||
savedStates.Add(newState);
|
||||
|
||||
currentState = savedStates.Count - 1;
|
||||
CurrentState = savedStates.Count - 1;
|
||||
|
||||
OnStateChange?.Invoke();
|
||||
updateBindables();
|
||||
@ -96,15 +96,15 @@ namespace osu.Game.Screens.Edit
|
||||
if (savedStates.Count == 0)
|
||||
return;
|
||||
|
||||
int newState = Math.Clamp(currentState + direction, 0, savedStates.Count - 1);
|
||||
if (currentState == newState)
|
||||
int newState = Math.Clamp(CurrentState + direction, 0, savedStates.Count - 1);
|
||||
if (CurrentState == newState)
|
||||
return;
|
||||
|
||||
isRestoring = true;
|
||||
|
||||
ApplyStateChange(savedStates[currentState], savedStates[newState]);
|
||||
ApplyStateChange(savedStates[CurrentState], savedStates[newState]);
|
||||
|
||||
currentState = newState;
|
||||
CurrentState = newState;
|
||||
|
||||
isRestoring = false;
|
||||
|
||||
@ -128,8 +128,8 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private void updateBindables()
|
||||
{
|
||||
CanUndo.Value = savedStates.Count > 0 && currentState > 0;
|
||||
CanRedo.Value = currentState < savedStates.Count - 1;
|
||||
CanUndo.Value = savedStates.Count > 0 && CurrentState > 0;
|
||||
CanRedo.Value = CurrentState < savedStates.Count - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
public bool HasUncommittedChanges => currentTransaction.UndoCommands.Count != 0;
|
||||
|
||||
private bool suppressStateChange;
|
||||
private bool ignoreCommandStateChange;
|
||||
private bool ignoreChangeHandlerStateChange;
|
||||
|
||||
private Transaction currentTransaction;
|
||||
|
||||
@ -44,12 +45,21 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
if (this.changeHandler != null)
|
||||
{
|
||||
// Ensure mutually exclusive state changes.
|
||||
TransactionBegan += () => this.changeHandler.SuppressStateChange = true;
|
||||
TransactionEnded += () => this.changeHandler.SuppressStateChange = false;
|
||||
this.changeHandler.TransactionBegan += () => suppressStateChange = true;
|
||||
this.changeHandler.TransactionEnded += () => suppressStateChange = false;
|
||||
this.changeHandler.SaveStateTriggered += commitChangeHandlerTransaction;
|
||||
TransactionBegan += () =>
|
||||
{
|
||||
ignoreChangeHandlerStateChange = !ignoreCommandStateChange;
|
||||
// The change handler should save states even when a change is recorded as commands,
|
||||
// because it needs to know the state after the commands in order to restore it.
|
||||
this.changeHandler.BeginChange();
|
||||
};
|
||||
TransactionEnded += () =>
|
||||
{
|
||||
this.changeHandler.EndChange();
|
||||
ignoreChangeHandlerStateChange = false;
|
||||
};
|
||||
this.changeHandler.TransactionBegan += () => ignoreCommandStateChange = !ignoreChangeHandlerStateChange;
|
||||
this.changeHandler.TransactionEnded += () => ignoreCommandStateChange = false;
|
||||
this.changeHandler.OnStateChange += commitChangeHandlerStateChange;
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +102,7 @@ namespace osu.Game.Screens.Edit
|
||||
return;
|
||||
}
|
||||
|
||||
if (!suppressStateChange)
|
||||
if (!ignoreCommandStateChange)
|
||||
{
|
||||
undoStack.Push(currentTransaction);
|
||||
redoStack.Clear();
|
||||
@ -105,8 +115,11 @@ namespace osu.Game.Screens.Edit
|
||||
historyChanged();
|
||||
}
|
||||
|
||||
private void commitChangeHandlerTransaction()
|
||||
private void commitChangeHandlerStateChange()
|
||||
{
|
||||
if (ignoreChangeHandlerStateChange || changeHandler!.CurrentState <= 0)
|
||||
return;
|
||||
|
||||
undoStack.Push(new Transaction(isChangeHandlerTransaction: true));
|
||||
redoStack.Clear();
|
||||
|
||||
@ -128,10 +141,21 @@ namespace osu.Game.Screens.Edit
|
||||
var redoTransaction = transaction.Reverse();
|
||||
|
||||
if (transaction.IsChangeHandlerTransaction)
|
||||
{
|
||||
ignoreChangeHandlerStateChange = true;
|
||||
changeHandler!.RestoreState(-1);
|
||||
ignoreChangeHandlerStateChange = false;
|
||||
Logger.Log("Undo handled by change handler");
|
||||
}
|
||||
else
|
||||
{
|
||||
revertTransaction(transaction);
|
||||
|
||||
if (changeHandler != null)
|
||||
changeHandler.CurrentState--;
|
||||
Logger.Log("Undo handled by command handler");
|
||||
}
|
||||
|
||||
redoStack.Push(redoTransaction);
|
||||
|
||||
historyChanged();
|
||||
@ -152,10 +176,21 @@ namespace osu.Game.Screens.Edit
|
||||
var undoTransaction = transaction.Reverse();
|
||||
|
||||
if (transaction.IsChangeHandlerTransaction)
|
||||
{
|
||||
ignoreChangeHandlerStateChange = true;
|
||||
changeHandler!.RestoreState(1);
|
||||
ignoreChangeHandlerStateChange = false;
|
||||
Logger.Log("Redo handled by change handler");
|
||||
}
|
||||
else
|
||||
{
|
||||
revertTransaction(transaction);
|
||||
|
||||
if (changeHandler != null)
|
||||
changeHandler.CurrentState++;
|
||||
Logger.Log("Redo handled by command handler");
|
||||
}
|
||||
|
||||
undoStack.Push(undoTransaction);
|
||||
|
||||
historyChanged();
|
||||
@ -181,6 +216,7 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private void revertTransaction(Transaction transaction)
|
||||
{
|
||||
// We are navigating history so we don't want to write a new state.
|
||||
if (changeHandler != null)
|
||||
changeHandler.SuppressStateChange = true;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user