From 0cb3926e1d090b7c336b16a5512f31f696d18661 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Oct 2020 15:44:32 +0900 Subject: [PATCH 1/5] Add event on EditorChangeHandler state change --- .../Editing/EditorChangeHandlerTest.cs | 22 ++++++++++++++++++- osu.Game/Screens/Edit/EditorChangeHandler.cs | 5 +++++ osu.Game/Screens/Edit/IEditorChangeHandler.cs | 6 +++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs b/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs index ff2c9fb1a9..b7a41ffd1c 100644 --- a/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs +++ b/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs @@ -12,6 +12,14 @@ namespace osu.Game.Tests.Editing [TestFixture] public class EditorChangeHandlerTest { + private int stateChangedFired; + + [SetUp] + public void SetUp() + { + stateChangedFired = 0; + } + [Test] public void TestSaveRestoreState() { @@ -23,6 +31,8 @@ namespace osu.Game.Tests.Editing addArbitraryChange(beatmap); handler.SaveState(); + Assert.That(stateChangedFired, Is.EqualTo(1)); + Assert.That(handler.CanUndo.Value, Is.True); Assert.That(handler.CanRedo.Value, Is.False); @@ -30,6 +40,8 @@ namespace osu.Game.Tests.Editing Assert.That(handler.CanUndo.Value, Is.False); Assert.That(handler.CanRedo.Value, Is.True); + + Assert.That(stateChangedFired, Is.EqualTo(2)); } [Test] @@ -45,6 +57,7 @@ namespace osu.Game.Tests.Editing Assert.That(handler.CanUndo.Value, Is.True); Assert.That(handler.CanRedo.Value, Is.False); + Assert.That(stateChangedFired, Is.EqualTo(1)); string hash = handler.CurrentStateHash; @@ -52,6 +65,7 @@ namespace osu.Game.Tests.Editing handler.SaveState(); Assert.That(hash, Is.EqualTo(handler.CurrentStateHash)); + Assert.That(stateChangedFired, Is.EqualTo(1)); handler.RestoreState(-1); @@ -60,6 +74,7 @@ namespace osu.Game.Tests.Editing // 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); + Assert.That(stateChangedFired, Is.EqualTo(2)); } [Test] @@ -71,6 +86,8 @@ namespace osu.Game.Tests.Editing for (int i = 0; i < EditorChangeHandler.MAX_SAVED_STATES; i++) { + Assert.That(stateChangedFired, Is.EqualTo(i)); + addArbitraryChange(beatmap); handler.SaveState(); } @@ -114,7 +131,10 @@ namespace osu.Game.Tests.Editing { var beatmap = new EditorBeatmap(new Beatmap()); - return (new EditorChangeHandler(beatmap), beatmap); + var changeHandler = new EditorChangeHandler(beatmap); + + changeHandler.OnStateChange += () => stateChangedFired++; + return (changeHandler, beatmap); } private void addArbitraryChange(EditorBeatmap beatmap) diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 617c436ee0..616d0608c0 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -21,6 +21,8 @@ namespace osu.Game.Screens.Edit public readonly Bindable CanUndo = new Bindable(); public readonly Bindable CanRedo = new Bindable(); + public event Action OnStateChange; + private readonly LegacyEditorBeatmapPatcher patcher; private readonly List savedStates = new List(); @@ -109,6 +111,8 @@ namespace osu.Game.Screens.Edit savedStates.Add(newState); currentState = savedStates.Count - 1; + + OnStateChange?.Invoke(); updateBindables(); } } @@ -136,6 +140,7 @@ namespace osu.Game.Screens.Edit isRestoring = false; + OnStateChange?.Invoke(); updateBindables(); } diff --git a/osu.Game/Screens/Edit/IEditorChangeHandler.cs b/osu.Game/Screens/Edit/IEditorChangeHandler.cs index c1328252d4..a23a956e14 100644 --- a/osu.Game/Screens/Edit/IEditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/IEditorChangeHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit @@ -10,6 +11,11 @@ namespace osu.Game.Screens.Edit /// public interface IEditorChangeHandler { + /// + /// Fired whenever a state change occurs. + /// + public event Action OnStateChange; + /// /// Begins a bulk state change event. should be invoked soon after. /// From 501e02db097eab45553f0376caf420457b6cbb2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Oct 2020 15:44:37 +0900 Subject: [PATCH 2/5] Only regenerate autoplay on editor state change --- osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index 1070b8cbd2..d259a89055 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -40,17 +40,21 @@ namespace osu.Game.Rulesets.Edit Playfield.DisplayJudgements.Value = false; } + [Resolved] + private IEditorChangeHandler changeHandler { get; set; } + protected override void LoadComplete() { base.LoadComplete(); beatmap.HitObjectAdded += addHitObject; - beatmap.HitObjectUpdated += updateReplay; beatmap.HitObjectRemoved += removeHitObject; + + // for now only regenerate replay on a finalised state change, not HitObjectUpdated. + changeHandler.OnStateChange += updateReplay; } - private void updateReplay(HitObject obj = null) => - drawableRuleset.RegenerateAutoplay(); + private void updateReplay() => drawableRuleset.RegenerateAutoplay(); private void addHitObject(HitObject hitObject) { @@ -69,7 +73,7 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.Remove(drawableObject); drawableRuleset.Playfield.PostProcess(); - drawableRuleset.RegenerateAutoplay(); + updateReplay(); } public override bool PropagatePositionalInputSubTree => false; From b7c276093db90227293a4fc8505e3d3aaa46f5cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Oct 2020 16:21:50 +0900 Subject: [PATCH 3/5] Add fallback case when EditorChangeHandler is not present (for tests) --- .../Rulesets/Edit/DrawableEditRulesetWrapper.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index d259a89055..43e5153f24 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Edit Playfield.DisplayJudgements.Value = false; } - [Resolved] + [Resolved(canBeNull: true)] private IEditorChangeHandler changeHandler { get; set; } protected override void LoadComplete() @@ -50,8 +50,15 @@ namespace osu.Game.Rulesets.Edit beatmap.HitObjectAdded += addHitObject; beatmap.HitObjectRemoved += removeHitObject; - // for now only regenerate replay on a finalised state change, not HitObjectUpdated. - changeHandler.OnStateChange += updateReplay; + if (changeHandler != null) + { + // for now only regenerate replay on a finalised state change, not HitObjectUpdated. + changeHandler.OnStateChange += updateReplay; + } + else + { + beatmap.HitObjectUpdated += _ => updateReplay(); + } } private void updateReplay() => drawableRuleset.RegenerateAutoplay(); From 66f5187e6a26ea480fb777d9f5abef93ce7a4e13 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Oct 2020 18:20:59 +0900 Subject: [PATCH 4/5] Remove redundant access permission --- osu.Game/Screens/Edit/IEditorChangeHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/IEditorChangeHandler.cs b/osu.Game/Screens/Edit/IEditorChangeHandler.cs index a23a956e14..1774ec6c04 100644 --- a/osu.Game/Screens/Edit/IEditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/IEditorChangeHandler.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Edit /// /// Fired whenever a state change occurs. /// - public event Action OnStateChange; + event Action OnStateChange; /// /// Begins a bulk state change event. should be invoked soon after. From 575046e5fdc34bc13797cab78517f337136734c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Oct 2020 18:21:13 +0900 Subject: [PATCH 5/5] Don't update reply on add/remove (will be automatically handled by change handler events) --- osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index 43e5153f24..8ed7885101 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -69,8 +69,6 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.Add(drawableObject); drawableRuleset.Playfield.PostProcess(); - - updateReplay(); } private void removeHitObject(HitObject hitObject) @@ -79,8 +77,6 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.Remove(drawableObject); drawableRuleset.Playfield.PostProcess(); - - updateReplay(); } public override bool PropagatePositionalInputSubTree => false;