1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-07 23:03:21 +08:00

Add mergeable commands

This commit is contained in:
Marvin Schürz 2024-10-10 14:05:50 +02:00
parent 4814ccbedd
commit 1924463465
4 changed files with 70 additions and 14 deletions

View File

@ -0,0 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Screens.Edit.Commands
{
public interface IMergeableCommand : IEditorCommand
{
public IEditorCommand? MergeWith(IEditorCommand previous);
}
}

View File

@ -6,7 +6,7 @@ using osuTK;
namespace osu.Game.Screens.Edit.Commands
{
public class MoveCommand : IEditorCommand
public class MoveCommand : IEditorCommand, IMergeableCommand
{
public readonly IHasMutablePosition Target;
@ -23,5 +23,13 @@ namespace osu.Game.Screens.Edit.Commands
public IEditorCommand CreateUndo() => new MoveCommand(Target, Target.Position);
public bool IsRedundant => Position == Target.Position;
public IEditorCommand? MergeWith(IEditorCommand previous)
{
if (previous is MoveCommand moveCommand)
return moveCommand.Target != Target ? null : this;
return null;
}
}
}

View File

@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit
public readonly Bindable<bool> CanRedo = new BindableBool();
public bool HasUncommittedChanges => currentTransaction.Entries.Count != 0;
public bool HasUncommittedChanges => currentTransaction.Commands.Count != 0;
public void Submit(IEditorCommand command, bool commitImmediately = false)
{
@ -56,7 +56,7 @@ namespace osu.Game.Screens.Edit
undoStack.Push(currentTransaction);
redoStack.Clear();
Logger.Log($"Added {currentTransaction.Entries.Count} command(s) to undo stack");
Logger.Log($"Added {currentTransaction.Commands.Count} command(s) to undo stack");
currentTransaction = new Transaction();
@ -71,10 +71,11 @@ namespace osu.Game.Screens.Edit
return false;
var transaction = undoStack.Pop();
var redoTransaction = transaction.Reverse();
revertTransaction(transaction);
redoStack.Push(transaction);
redoStack.Push(redoTransaction);
historyChanged();
@ -87,11 +88,12 @@ namespace osu.Game.Screens.Edit
return false;
var transaction = redoStack.Pop();
var undoTransaction = transaction.Reverse();
foreach (var entry in transaction.Entries)
apply(entry.Command);
foreach (var command in transaction.Commands)
apply(command);
undoStack.Push(transaction);
undoStack.Push(undoTransaction);
historyChanged();
@ -112,8 +114,8 @@ namespace osu.Game.Screens.Edit
private void revertTransaction(Transaction transaction)
{
foreach (var entry in transaction.Entries.Reverse())
apply(entry.Reverse);
foreach (var command in transaction.Commands.Reverse())
apply(command);
}
private void historyChanged()
@ -138,7 +140,7 @@ namespace osu.Game.Screens.Edit
{
var reverse = command.CreateUndo();
currentTransaction.Add(new HistoryEntry(command, reverse));
currentTransaction.Add(reverse);
}
private readonly record struct HistoryEntry(IEditorCommand Command, IEditorCommand Reverse);
@ -149,11 +151,47 @@ namespace osu.Game.Screens.Edit
{
}
private readonly List<HistoryEntry> entries = new List<HistoryEntry>();
private readonly List<IEditorCommand> commands = new List<IEditorCommand>();
public IReadOnlyList<HistoryEntry> Entries => entries;
public IReadOnlyList<IEditorCommand> Commands => commands;
public void Add(HistoryEntry entry) => entries.Add(entry);
public void Add(IEditorCommand command)
{
if (command is IMergeableCommand mergeable)
{
for (int i = 0; i < commands.Count; i++)
{
var merged = mergeable.MergeWith(commands[i]);
if (merged == null)
continue;
command = merged;
commands.RemoveAt(i--);
if (command is IMergeableCommand newMergeable)
{
mergeable = newMergeable;
}
else
{
break;
}
}
}
commands.Add(command);
}
public Transaction Reverse()
{
var reversed = new Transaction();
foreach (var command in Commands.Reverse())
reversed.Add(command.CreateUndo());
return reversed;
}
}
}
}

View File

@ -6,7 +6,7 @@ using osu.Game.Screens.Edit.Commands;
namespace osu.Game.Screens.Edit
{
public static class EditorCommandManagerExtension
public static class EditorCommandHandlerExtension
{
public static void SafeSubmit(this EditorCommandHandler? manager, IEditorCommand command, bool commitImmediately = false)
{