From 4ef2e9548c01dce805c1ce02d89e40626146531a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Nov 2020 19:52:02 +0900 Subject: [PATCH] Pass HitObjectComposer to BlueprintContainer via ctor --- .../Edit/ManiaBlueprintContainer.cs | 5 +- .../Edit/ManiaHitObjectComposer.cs | 5 +- .../Edit/OsuBlueprintContainer.cs | 5 +- .../Edit/OsuHitObjectComposer.cs | 5 +- .../Edit/TaikoBlueprintContainer.cs | 5 +- .../Edit/TaikoHitObjectComposer.cs | 5 +- .../TestSceneTimelineBlueprintContainer.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 7 +- .../Compose/Components/BlueprintContainer.cs | 74 +++++++++++++------ .../Components/ComposeBlueprintContainer.cs | 26 +++---- .../Timeline/TimelineBlueprintContainer.cs | 3 +- .../Screens/Edit/Compose/ComposeScreen.cs | 2 +- 12 files changed, 83 insertions(+), 61 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index cea27498c3..2fa3f378ff 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -12,8 +11,8 @@ namespace osu.Game.Rulesets.Mania.Edit { public class ManiaBlueprintContainer : ComposeBlueprintContainer { - public ManiaBlueprintContainer(IEnumerable drawableHitObjects) - : base(drawableHitObjects) + public ManiaBlueprintContainer(HitObjectComposer composer) + : base(composer) { } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 7e2469a794..01d572447b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -13,7 +13,6 @@ using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; @@ -89,8 +88,8 @@ namespace osu.Game.Rulesets.Mania.Edit return drawableRuleset; } - protected override ComposeBlueprintContainer CreateBlueprintContainer(IEnumerable hitObjects) - => new ManiaBlueprintContainer(hitObjects); + protected override ComposeBlueprintContainer CreateBlueprintContainer() + => new ManiaBlueprintContainer(this); protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index 330f34b85c..a68ed34e6b 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; @@ -14,8 +13,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuBlueprintContainer : ComposeBlueprintContainer { - public OsuBlueprintContainer(IEnumerable drawableHitObjects) - : base(drawableHitObjects) + public OsuBlueprintContainer(HitObjectComposer composer) + : base(composer) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index edd684d886..bfa8ab4431 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -16,7 +16,6 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Components.TernaryButtons; @@ -80,8 +79,8 @@ namespace osu.Game.Rulesets.Osu.Edit updateDistanceSnapGrid(); } - protected override ComposeBlueprintContainer CreateBlueprintContainer(IEnumerable hitObjects) - => new OsuBlueprintContainer(hitObjects); + protected override ComposeBlueprintContainer CreateBlueprintContainer() + => new OsuBlueprintContainer(this); private DistanceSnapGrid distanceSnapGrid; private Container distanceSnapGridContainer; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs index 35227b3c64..8b41448c9d 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Edit.Blueprints; @@ -11,8 +10,8 @@ namespace osu.Game.Rulesets.Taiko.Edit { public class TaikoBlueprintContainer : ComposeBlueprintContainer { - public TaikoBlueprintContainer(IEnumerable hitObjects) - : base(hitObjects) + public TaikoBlueprintContainer(HitObjectComposer composer) + : base(composer) { } diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs index cdc9672a8e..161799c980 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -24,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Edit new SwellCompositionTool() }; - protected override ComposeBlueprintContainer CreateBlueprintContainer(IEnumerable hitObjects) - => new TaikoBlueprintContainer(hitObjects); + protected override ComposeBlueprintContainer CreateBlueprintContainer() + => new TaikoBlueprintContainer(this); } } diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs index e931be044c..5da63eddf1 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tests.Visual.Editing [TestFixture] public class TestSceneTimelineBlueprintContainer : TimelineTestScene { - public override Drawable CreateTestComponent() => new TimelineBlueprintContainer(); + public override Drawable CreateTestComponent() => new TimelineBlueprintContainer(null); protected override void LoadComplete() { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index c9dd061b48..b90aa6863a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Edit drawableRulesetWrapper, // layers above playfield drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer() - .WithChild(BlueprintContainer = CreateBlueprintContainer(HitObjects)) + .WithChild(BlueprintContainer = CreateBlueprintContainer()) } }, new FillFlowContainer @@ -182,9 +182,8 @@ namespace osu.Game.Rulesets.Edit /// /// Construct a relevant blueprint container. This will manage hitobject selection/placement input handling and display logic. /// - /// A live collection of all s in the editor beatmap. - protected virtual ComposeBlueprintContainer CreateBlueprintContainer(IEnumerable hitObjects) - => new ComposeBlueprintContainer(hitObjects); + protected virtual ComposeBlueprintContainer CreateBlueprintContainer() + => new ComposeBlueprintContainer(this); /// /// Construct a drawable ruleset for the provided ruleset. diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index b67f6a6ba6..3145616cf7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -44,12 +45,16 @@ namespace osu.Game.Screens.Edit.Compose.Components protected EditorBeatmap Beatmap { get; private set; } private readonly BindableList selectedHitObjects = new BindableList(); + private readonly HitObjectComposer composer; + private readonly Dictionary blueprintMap = new Dictionary(); [Resolved(canBeNull: true)] private IPositionSnapProvider snapProvider { get; set; } - protected BlueprintContainer() + protected BlueprintContainer(HitObjectComposer composer) { + this.composer = composer; + RelativeSizeAxes = Axes.Both; } @@ -68,8 +73,12 @@ namespace osu.Game.Screens.Edit.Compose.Components DragBox.CreateProxy().With(p => p.Depth = float.MinValue) }); - foreach (var obj in Beatmap.HitObjects) - AddBlueprintFor(obj); + // For non-pooled rulesets, hitobjects are already present in the playfield which allows the blueprints to be loaded in the async context. + if (composer != null) + { + foreach (var obj in composer.HitObjects) + addBlueprintFor(obj.HitObject); + } selectedHitObjects.BindTo(Beatmap.SelectedHitObjects); selectedHitObjects.CollectionChanged += (selectedObjects, args) => @@ -94,7 +103,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.LoadComplete(); - Beatmap.HitObjectAdded += AddBlueprintFor; + Beatmap.HitObjectAdded += addBlueprintFor; Beatmap.HitObjectRemoved += removeBlueprintFor; } @@ -247,29 +256,17 @@ namespace osu.Game.Screens.Edit.Compose.Components #region Blueprint Addition/Removal - private void removeBlueprintFor(HitObject hitObject) + private void addBlueprintFor(HitObject hitObject) { - var blueprint = SelectionBlueprints.SingleOrDefault(m => m.HitObject == hitObject); - if (blueprint == null) + if (blueprintMap.ContainsKey(hitObject)) return; - blueprint.Deselect(); - - blueprint.Selected -= onBlueprintSelected; - blueprint.Deselected -= onBlueprintDeselected; - - SelectionBlueprints.Remove(blueprint); - - if (movementBlueprint == blueprint) - finishSelectionMovement(); - } - - protected virtual void AddBlueprintFor(HitObject hitObject) - { var blueprint = CreateBlueprintFor(hitObject); if (blueprint == null) return; + blueprintMap[hitObject] = blueprint; + blueprint.Selected += onBlueprintSelected; blueprint.Deselected += onBlueprintDeselected; @@ -277,6 +274,41 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Select(); SelectionBlueprints.Add(blueprint); + + OnBlueprintAdded(hitObject); + } + + private void removeBlueprintFor(HitObject hitObject) + { + if (!blueprintMap.Remove(hitObject, out var blueprint)) + return; + + blueprint.Deselect(); + blueprint.Selected -= onBlueprintSelected; + blueprint.Deselected -= onBlueprintDeselected; + + SelectionBlueprints.Remove(blueprint); + + if (movementBlueprint == blueprint) + finishSelectionMovement(); + + OnBlueprintRemoved(hitObject); + } + + /// + /// Called after a blueprint has been added. + /// + /// The for which the blueprint has been added. + protected virtual void OnBlueprintAdded(HitObject hitObject) + { + } + + /// + /// Called after a blueprint has been removed. + /// + /// The for which the blueprint has been removed. + protected virtual void OnBlueprintRemoved(HitObject hitObject) + { } #endregion @@ -456,7 +488,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (Beatmap != null) { - Beatmap.HitObjectAdded -= AddBlueprintFor; + Beatmap.HitObjectAdded -= addBlueprintFor; Beatmap.HitObjectRemoved -= removeBlueprintFor; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 1527d20f54..27190e9aad 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -27,22 +27,18 @@ namespace osu.Game.Screens.Edit.Compose.Components /// public class ComposeBlueprintContainer : BlueprintContainer { - [Resolved] - private HitObjectComposer composer { get; set; } - - private PlacementBlueprint currentPlacement; - - private readonly Container placementBlueprintContainer; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + private readonly HitObjectComposer composer; + private readonly Container placementBlueprintContainer; + + private PlacementBlueprint currentPlacement; private InputManager inputManager; - private readonly IEnumerable drawableHitObjects; - - public ComposeBlueprintContainer(IEnumerable drawableHitObjects) + public ComposeBlueprintContainer(HitObjectComposer composer) + : base(composer) { - this.drawableHitObjects = drawableHitObjects; + this.composer = composer; placementBlueprintContainer = new Container { @@ -186,7 +182,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected sealed override SelectionBlueprint CreateBlueprintFor(HitObject hitObject) { - var drawable = drawableHitObjects.FirstOrDefault(d => d.HitObject == hitObject); + var drawable = composer.HitObjects.FirstOrDefault(d => d.HitObject == hitObject); if (drawable == null) return null; @@ -196,11 +192,11 @@ namespace osu.Game.Screens.Edit.Compose.Components public virtual OverlaySelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; - protected override void AddBlueprintFor(HitObject hitObject) + protected override void OnBlueprintAdded(HitObject hitObject) { - refreshTool(); + base.OnBlueprintAdded(hitObject); - base.AddBlueprintFor(hitObject); + refreshTool(); // on successful placement, the new combo button should be reset as this is the most common user interaction. if (Beatmap.SelectedHitObjects.Count == 0) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index 10913a8bb9..078a158e3d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -31,7 +31,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private SelectionBlueprint placementBlueprint; - public TimelineBlueprintContainer() + public TimelineBlueprintContainer(HitObjectComposer composer) + : base(composer) { RelativeSizeAxes = Axes.Both; Anchor = Anchor.Centre; diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 5282b4d998..d9948aa23c 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -53,6 +53,6 @@ namespace osu.Game.Screens.Edit.Compose return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } - protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineBlueprintContainer(); + protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineBlueprintContainer(composer); } }