diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs index f15be94b8a..dfbb503cbf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Connects hit objects visually, for example with follow points. /// - public abstract class ConnectionRenderer : Container + public abstract class ConnectionRenderer : LifetimeManagementContainer where T : HitObject { /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 61219d9bb9..ebcf6b33ba 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private void update() { - Clear(); + ClearInternal(); if (hitObjects == null) return; @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections FollowPoint fp; - Add(fp = new FollowPoint + AddInternal(fp = new FollowPoint { Position = pointStartPosition, Rotation = rotation, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 9b562745fa..c5d5717618 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -118,6 +118,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); + ApproachCircle.Expire(true); } protected override void UpdateCurrentState(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index 07d99bda42..59d7b24ca9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -12,6 +12,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class ApproachCircle : Container { + public override bool RemoveWhenNotAlive => false; + public ApproachCircle() { Anchor = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 3399fdb9a0..732ba5d7e8 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.UI { public class OsuPlayfield : Playfield { - private readonly Container approachCircles; + private readonly ApproachCircleProxyContainer approachCircles; private readonly JudgementContainer judgementLayer; private readonly ConnectionRenderer connectionLayer; @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.UI Depth = 1, }, HitObjectContainer, - approachCircles = new Container + approachCircles = new ApproachCircleProxyContainer { RelativeSizeAxes = Axes.Both, Depth = -1, @@ -60,11 +60,23 @@ namespace osu.Game.Rulesets.Osu.UI var c = h as IDrawableHitObjectWithProxiedApproach; if (c != null) - approachCircles.Add(c.ProxiedLayer.CreateProxy()); + { + var original = c.ProxiedLayer; + // lifetime is set on LoadComplete so wait until it. + original.OnLoadComplete += addApproachCircleProxy; + } base.Add(h); } + private void addApproachCircleProxy(Drawable d) + { + var proxy = d.CreateProxy(); + proxy.LifetimeStart = d.LifetimeStart; + proxy.LifetimeEnd = d.LifetimeEnd; + approachCircles.Add(proxy); + } + public override void PostProcess() { connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); @@ -86,5 +98,10 @@ namespace osu.Game.Rulesets.Osu.UI } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos); + + private class ApproachCircleProxyContainer : LifetimeManagementContainer + { + public void Add(Drawable approachCircleProxy) => AddInternal(approachCircleProxy); + } } } diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 261132c56b..73d44cca13 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.UI { - public class HitObjectContainer : CompositeDrawable + public class HitObjectContainer : LifetimeManagementContainer { public IEnumerable Objects => InternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); public IEnumerable AliveObjects => AliveInternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 74eaab33ca..e06d226adf 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardLayer : Container + public class DrawableStoryboardLayer : LifetimeManagementContainer { public StoryboardLayer Layer { get; private set; } public bool Enabled; @@ -29,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables foreach (var element in Layer.Elements) { if (element.IsDrawable) - Add(element.CreateDrawable()); + AddInternal(element.CreateDrawable()); } } }