mirror of
https://github.com/ppy/osu.git
synced 2025-02-15 14:42:56 +08:00
Merge pull request #10270 from peppy/editor-fix-noop-states-saving
Avoid saving state changes if nothing has changed (via binary comparison)
This commit is contained in:
commit
89c8fca3fa
@ -2,7 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Editing
|
namespace osu.Game.Tests.Editing
|
||||||
@ -13,11 +15,12 @@ namespace osu.Game.Tests.Editing
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestSaveRestoreState()
|
public void TestSaveRestoreState()
|
||||||
{
|
{
|
||||||
var handler = new EditorChangeHandler(new EditorBeatmap(new Beatmap()));
|
var (handler, beatmap) = createChangeHandler();
|
||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.False);
|
Assert.That(handler.CanUndo.Value, Is.False);
|
||||||
Assert.That(handler.CanRedo.Value, Is.False);
|
Assert.That(handler.CanRedo.Value, Is.False);
|
||||||
|
|
||||||
|
addArbitraryChange(beatmap);
|
||||||
handler.SaveState();
|
handler.SaveState();
|
||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.True);
|
Assert.That(handler.CanUndo.Value, Is.True);
|
||||||
@ -29,15 +32,48 @@ namespace osu.Game.Tests.Editing
|
|||||||
Assert.That(handler.CanRedo.Value, Is.True);
|
Assert.That(handler.CanRedo.Value, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSaveSameStateDoesNotSave()
|
||||||
|
{
|
||||||
|
var (handler, beatmap) = createChangeHandler();
|
||||||
|
|
||||||
|
Assert.That(handler.CanUndo.Value, Is.False);
|
||||||
|
Assert.That(handler.CanRedo.Value, Is.False);
|
||||||
|
|
||||||
|
addArbitraryChange(beatmap);
|
||||||
|
handler.SaveState();
|
||||||
|
|
||||||
|
Assert.That(handler.CanUndo.Value, Is.True);
|
||||||
|
Assert.That(handler.CanRedo.Value, Is.False);
|
||||||
|
|
||||||
|
string hash = handler.CurrentStateHash;
|
||||||
|
|
||||||
|
// save a save without making any changes
|
||||||
|
handler.SaveState();
|
||||||
|
|
||||||
|
Assert.That(hash, Is.EqualTo(handler.CurrentStateHash));
|
||||||
|
|
||||||
|
handler.RestoreState(-1);
|
||||||
|
|
||||||
|
Assert.That(hash, Is.Not.EqualTo(handler.CurrentStateHash));
|
||||||
|
|
||||||
|
// we should only be able to restore once even though we saved twice.
|
||||||
|
Assert.That(handler.CanUndo.Value, Is.False);
|
||||||
|
Assert.That(handler.CanRedo.Value, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestMaxStatesSaved()
|
public void TestMaxStatesSaved()
|
||||||
{
|
{
|
||||||
var handler = new EditorChangeHandler(new EditorBeatmap(new Beatmap()));
|
var (handler, beatmap) = createChangeHandler();
|
||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.False);
|
Assert.That(handler.CanUndo.Value, Is.False);
|
||||||
|
|
||||||
for (int i = 0; i < EditorChangeHandler.MAX_SAVED_STATES; i++)
|
for (int i = 0; i < EditorChangeHandler.MAX_SAVED_STATES; i++)
|
||||||
|
{
|
||||||
|
addArbitraryChange(beatmap);
|
||||||
handler.SaveState();
|
handler.SaveState();
|
||||||
|
}
|
||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.True);
|
Assert.That(handler.CanUndo.Value, Is.True);
|
||||||
|
|
||||||
@ -53,12 +89,15 @@ namespace osu.Game.Tests.Editing
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestMaxStatesExceeded()
|
public void TestMaxStatesExceeded()
|
||||||
{
|
{
|
||||||
var handler = new EditorChangeHandler(new EditorBeatmap(new Beatmap()));
|
var (handler, beatmap) = createChangeHandler();
|
||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.False);
|
Assert.That(handler.CanUndo.Value, Is.False);
|
||||||
|
|
||||||
for (int i = 0; i < EditorChangeHandler.MAX_SAVED_STATES * 2; i++)
|
for (int i = 0; i < EditorChangeHandler.MAX_SAVED_STATES * 2; i++)
|
||||||
|
{
|
||||||
|
addArbitraryChange(beatmap);
|
||||||
handler.SaveState();
|
handler.SaveState();
|
||||||
|
}
|
||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.True);
|
Assert.That(handler.CanUndo.Value, Is.True);
|
||||||
|
|
||||||
@ -70,5 +109,17 @@ namespace osu.Game.Tests.Editing
|
|||||||
|
|
||||||
Assert.That(handler.CanUndo.Value, Is.False);
|
Assert.That(handler.CanUndo.Value, Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private (EditorChangeHandler, EditorBeatmap) createChangeHandler()
|
||||||
|
{
|
||||||
|
var beatmap = new EditorBeatmap(new Beatmap());
|
||||||
|
|
||||||
|
return (new EditorChangeHandler(beatmap), beatmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addArbitraryChange(EditorBeatmap beatmap)
|
||||||
|
{
|
||||||
|
beatmap.Add(new HitCircle { StartTime = RNG.Next(0, 100000) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
@ -89,23 +90,27 @@ namespace osu.Game.Screens.Edit
|
|||||||
if (isRestoring)
|
if (isRestoring)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (currentState < savedStates.Count - 1)
|
|
||||||
savedStates.RemoveRange(currentState + 1, savedStates.Count - currentState - 1);
|
|
||||||
|
|
||||||
if (savedStates.Count > MAX_SAVED_STATES)
|
|
||||||
savedStates.RemoveAt(0);
|
|
||||||
|
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
||||||
new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw);
|
new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw);
|
||||||
|
|
||||||
savedStates.Add(stream.ToArray());
|
var 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.Last())) return;
|
||||||
|
|
||||||
|
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;
|
||||||
|
updateBindables();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentState = savedStates.Count - 1;
|
|
||||||
|
|
||||||
updateBindables();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user