Skip to content

Commit

Permalink
combine change handler into command handler
Browse files Browse the repository at this point in the history
  • Loading branch information
OliBomby committed Oct 12, 2024
1 parent db29feb commit 8fee3f5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 14 deletions.
2 changes: 2 additions & 0 deletions osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.IO;
using System.Text;
using osu.Framework.Logging;
using osu.Game.Beatmaps.Formats;
using osu.Game.Rulesets.Objects;

Expand Down Expand Up @@ -30,6 +31,7 @@ public BeatmapEditorChangeHandler(EditorBeatmap editorBeatmap)

protected override void WriteCurrentStateToStream(MemoryStream stream)
{
Logger.Log("Writing save state");
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw);
}
Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Screens/Edit/Editor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ private void load(OsuConfigManager config)
dependencies.CacheAs<IEditorChangeHandler>(changeHandler);
}

commandHandler = new EditorCommandHandler();
commandHandler = new EditorCommandHandler(editorBeatmap, changeHandler);
dependencies.CacheAs(commandHandler);

beatDivisor.SetArbitraryDivisor(editorBeatmap.BeatmapInfo.BeatDivisor);
Expand Down
91 changes: 78 additions & 13 deletions osu.Game/Screens/Edit/EditorCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ namespace osu.Game.Screens.Edit
{
public partial class EditorCommandHandler : TransactionalCommitComponent
{
private readonly EditorBeatmap editorBeatmap;

/// <summary>
/// This change handler will be suppressed while a transaction with this command handler is in progress.
/// Any save states of this change handler will be added to the undo stack.
/// </summary>
private readonly EditorChangeHandler? changeHandler;

public event Action<IEditorCommand>? CommandApplied;

public readonly Bindable<bool> CanUndo = new BindableBool();
Expand All @@ -20,6 +28,31 @@ public partial class EditorCommandHandler : TransactionalCommitComponent

public bool HasUncommittedChanges => currentTransaction.UndoCommands.Count != 0;

private bool suppressStateChange;

private Transaction currentTransaction;

private readonly Stack<Transaction> undoStack = new Stack<Transaction>();

private readonly Stack<Transaction> redoStack = new Stack<Transaction>();

public EditorCommandHandler(EditorBeatmap editorBeatmap, EditorChangeHandler? changeHandler)
{
this.editorBeatmap = editorBeatmap;
this.changeHandler = changeHandler;
currentTransaction = new Transaction();

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;
}
}

/// <summary>
/// Submits a command to be applied and added to the history.
/// </summary>
Expand Down Expand Up @@ -59,16 +92,29 @@ protected override void UpdateState()
return;
}

undoStack.Push(currentTransaction);
redoStack.Clear();
if (!suppressStateChange)
{
undoStack.Push(currentTransaction);
redoStack.Clear();

Logger.Log($"Added {currentTransaction.UndoCommands.Count} command(s) to undo stack");
Logger.Log($"Added {currentTransaction.UndoCommands.Count} command(s) to undo stack");
}

currentTransaction = new Transaction();

historyChanged();
}

private void commitChangeHandlerTransaction()
{
undoStack.Push(new Transaction(isChangeHandlerTransaction: true));
redoStack.Clear();

Logger.Log("Added change handler transaction to undo stack");

historyChanged();
}

/// <summary>
/// Undoes the last transaction from the undo stack.
/// Returns false if there are is nothing to undo.
Expand All @@ -81,7 +127,10 @@ public bool Undo()
var transaction = undoStack.Pop();
var redoTransaction = transaction.Reverse();

revertTransaction(transaction);
if (transaction.IsChangeHandlerTransaction)
changeHandler!.RestoreState(-1);
else
revertTransaction(transaction);

redoStack.Push(redoTransaction);

Expand All @@ -102,7 +151,10 @@ public bool Redo()
var transaction = redoStack.Pop();
var undoTransaction = transaction.Reverse();

revertTransaction(transaction);
if (transaction.IsChangeHandlerTransaction)
changeHandler!.RestoreState(1);
else
revertTransaction(transaction);

undoStack.Push(undoTransaction);

Expand All @@ -129,8 +181,18 @@ public bool RevertUncommitedChanges()

private void revertTransaction(Transaction transaction)
{
if (changeHandler != null)
changeHandler.SuppressStateChange = true;

editorBeatmap.BeginChange();

foreach (var command in transaction.UndoCommands)
apply(command);

editorBeatmap.EndChange();

if (changeHandler != null)
changeHandler.SuppressStateChange = false;
}

private void historyChanged()
Expand All @@ -139,12 +201,6 @@ private void historyChanged()
CanRedo.Value = redoStack.Count > 0;
}

private Transaction currentTransaction = new Transaction();

private readonly Stack<Transaction> undoStack = new Stack<Transaction>();

private readonly Stack<Transaction> redoStack = new Stack<Transaction>();

private void apply(IEditorCommand command)
{
command.Apply();
Expand All @@ -160,13 +216,22 @@ private void record(IEditorCommand command)

private readonly struct Transaction
{
public readonly bool IsChangeHandlerTransaction;

public Transaction()
{
undoCommands = new List<IEditorCommand>();
}

private Transaction(List<IEditorCommand> undoCommands)
public Transaction(bool isChangeHandlerTransaction = false)
{
IsChangeHandlerTransaction = isChangeHandlerTransaction;
undoCommands = new List<IEditorCommand>();
}

private Transaction(List<IEditorCommand> undoCommands, bool isChangeHandlerTransaction = false)
{
IsChangeHandlerTransaction = isChangeHandlerTransaction;
this.undoCommands = undoCommands;
}

Expand Down Expand Up @@ -204,7 +269,7 @@ public Transaction Reverse()
{
var commands = UndoCommands.Reverse().Select(command => command.CreateUndo()).ToList();

return new Transaction(commands);
return new Transaction(commands, IsChangeHandlerTransaction);
}
}
}
Expand Down

0 comments on commit 8fee3f5

Please sign in to comment.