diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs
index 3a92938d75..d1928bd4bb 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs
@@ -47,6 +47,11 @@ protected override void OnParentReceived(DrawableHitObject parent)
base.OnParentReceived(parent);
drawableSlider = (DrawableSlider)parent;
+ }
+
+ protected override void OnApply()
+ {
+ base.OnApply();
pathVersion.BindTo(drawableSlider.PathVersion);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs
index 0735d48ae1..f368615e77 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs
@@ -65,6 +65,11 @@ protected override void OnParentReceived(DrawableHitObject parent)
base.OnParentReceived(parent);
drawableSlider = (DrawableSlider)parent;
+ }
+
+ protected override void OnApply()
+ {
+ base.OnApply();
Position = HitObject.Position - drawableSlider.Position;
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
index faccf5d4d1..d40b6aea6e 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
@@ -23,6 +23,7 @@ public class DrawableSliderTick : DrawableOsuHitObject, IRequireTracking
public override bool DisplayResult => false;
private SkinnableDrawable scaleContainer;
+ private DrawableSlider drawableSlider;
public DrawableSliderTick()
: base(null)
@@ -66,7 +67,14 @@ protected override void OnParentReceived(DrawableHitObject parent)
{
base.OnParentReceived(parent);
- Position = HitObject.Position - ((DrawableSlider)parent).HitObject.Position;
+ drawableSlider = (DrawableSlider)parent;
+ }
+
+ protected override void OnApply()
+ {
+ base.OnApply();
+
+ Position = HitObject.Position - drawableSlider.HitObject.Position;
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
index f37d933e11..d10c4f7511 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
@@ -24,6 +24,7 @@ public DrawableSpinnerTick(SpinnerTick spinnerTick)
protected override void OnParentReceived(DrawableHitObject parent)
{
base.OnParentReceived(parent);
+
drawableSpinner = (DrawableSpinner)parent;
}
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index a922da0aa9..37c36ace7b 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -230,12 +230,12 @@ public void Apply([NotNull] HitObject hitObject, [CanBeNull] HitObjectLifetimeEn
foreach (var h in HitObject.NestedHitObjects)
{
- var pooledDrawableNested = pooledObjectProvider?.GetPooledDrawableRepresentation(h);
+ var pooledDrawableNested = pooledObjectProvider?.GetPooledDrawableRepresentation(h, this);
var drawableNested = pooledDrawableNested
?? CreateNestedHitObject(h)
?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}.");
- // Invoke the event only if this nested object is just created by `CreateNestedHitObject`.
+ // Only invoke the event for non-pooled DHOs, otherwise the event will be fired by the playfield.
if (pooledDrawableNested == null)
OnNestedDrawableCreated?.Invoke(drawableNested);
@@ -243,10 +243,12 @@ public void Apply([NotNull] HitObject hitObject, [CanBeNull] HitObjectLifetimeEn
drawableNested.OnRevertResult += onRevertResult;
drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState;
+ // ApplyParent() should occur before Apply() in all cases, so it's invoked before the nested DHO is added to the hierarchy below, but after its events are initialised.
+ if (pooledDrawableNested == null)
+ drawableNested.ApplyParent(this);
+
nestedHitObjects.Value.Add(drawableNested);
AddNestedHitObject(drawableNested);
-
- drawableNested.OnParentReceived(this);
}
StartTimeBindable.BindTo(HitObject.StartTimeBindable);
@@ -348,6 +350,12 @@ protected virtual void OnFree()
{
}
+ ///
+ /// Applies a parenting to this .
+ ///
+ /// The parenting .
+ public void ApplyParent(DrawableHitObject parent) => OnParentReceived(parent);
+
///
/// Invoked when this receives a new parenting .
///
diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs
index ac5d281ddc..12e39d4fbf 100644
--- a/osu.Game/Rulesets/UI/HitObjectContainer.cs
+++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs
@@ -105,7 +105,7 @@ private void addDrawable(HitObjectLifetimeEntry entry)
{
Debug.Assert(!drawableMap.ContainsKey(entry));
- var drawable = pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject);
+ var drawable = pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject, null);
if (drawable == null)
throw new InvalidOperationException($"A drawable representation could not be retrieved for hitobject type: {entry.HitObject.GetType().ReadableName()}.");
diff --git a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs
index 315926dfc6..2d700076d6 100644
--- a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs
+++ b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs
@@ -13,8 +13,9 @@ internal interface IPooledHitObjectProvider
/// Attempts to retrieve the poolable representation of a .
///
/// The to retrieve the representation of.
+ /// The parenting , if any.
/// The representing , or null if no poolable representation exists.
[CanBeNull]
- DrawableHitObject GetPooledDrawableRepresentation([NotNull] HitObject hitObject);
+ DrawableHitObject GetPooledDrawableRepresentation([NotNull] HitObject hitObject, [CanBeNull] DrawableHitObject parent);
}
}
diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs
index a2ac234471..01b25c9717 100644
--- a/osu.Game/Rulesets/UI/Playfield.cs
+++ b/osu.Game/Rulesets/UI/Playfield.cs
@@ -323,7 +323,7 @@ protected void RegisterPool([NotNull] DrawablePool