diff --git a/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs b/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs new file mode 100644 index 0000000000..5c933468be --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestSceneSelectionBlueprintDeselection.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Beatmaps; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Editing +{ + public class TestSceneSelectionBlueprintDeselection : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + + [Test] + public void TestSingleDeleteAtSameTime() + { + HitCircle? circle1 = null; + + AddStep("add two circles at the same time", () => + { + EditorClock.Seek(0); + circle1 = new HitCircle(); + var circle2 = new HitCircle(); + + EditorBeatmap.Add(circle1); + EditorBeatmap.Add(circle2); + + EditorBeatmap.SelectedHitObjects.Add(circle1); + EditorBeatmap.SelectedHitObjects.Add(circle2); + }); + + AddStep("delete the first circle", () => EditorBeatmap.Remove(circle1)); + AddAssert("one hitobject remains", () => EditorBeatmap.HitObjects.Count == 1); + AddAssert("one hitobject selected", () => EditorBeatmap.SelectedHitObjects.Count == 1); + } + + [Test] + public void TestBigStackDeleteAtSameTime() + { + AddStep("add 20 circles at the same time", () => + { + EditorClock.Seek(0); + + for (int i = 0; i < 20; i++) + { + EditorBeatmap.Add(new HitCircle()); + } + }); + + AddStep("select half of the circles", () => + { + foreach (var hitObject in EditorBeatmap.HitObjects.SkipLast(10).Reverse()) + { + EditorBeatmap.SelectedHitObjects.Add(hitObject); + } + }); + + AddStep("delete all selected circles", () => + { + InputManager.PressKey(Key.Delete); + InputManager.ReleaseKey(Key.Delete); + }); + + AddAssert("10 hitobjects remain", () => EditorBeatmap.HitObjects.Count == 10); + AddAssert("no hitobjects selected", () => EditorBeatmap.SelectedHitObjects.Count == 0); + } + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs index d6fd07c998..18bb6284b8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs @@ -24,11 +24,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.LoadComplete(); - editorBeatmap.HitObjectUpdated += hitObjectUpdated; + editorBeatmap.BeatmapReprocessed += SortInternal; } - private void hitObjectUpdated(HitObject _) => SortInternal(); - public override void Add(SelectionBlueprint drawable) { SortInternal(); @@ -72,7 +70,7 @@ namespace osu.Game.Screens.Edit.Compose.Components base.Dispose(isDisposing); if (editorBeatmap != null) - editorBeatmap.HitObjectUpdated -= hitObjectUpdated; + editorBeatmap.BeatmapReprocessed -= SortInternal; } } } diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 8aa754b305..16c0064e80 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -48,6 +48,15 @@ namespace osu.Game.Screens.Edit /// public event Action HitObjectUpdated; + /// + /// Invoked after any state changes occurred which triggered a beatmap reprocess via an . + /// + /// + /// Beatmap processing may change the order of hitobjects. This event gives external components a chance to handle any changes + /// not covered by the / / events. + /// + public event Action BeatmapReprocessed; + /// /// All currently selected s. /// @@ -331,6 +340,8 @@ namespace osu.Game.Screens.Edit beatmapProcessor?.PostProcess(); + BeatmapReprocessed?.Invoke(); + // callbacks may modify the lists so let's be safe about it var deletes = batchPendingDeletes.ToArray(); batchPendingDeletes.Clear();