From 3f78d81386db5deb57d42f55dcd841ead8d68a4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Nov 2020 15:59:48 +0900 Subject: [PATCH] Add nested osu! hitobject pooling --- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 18 +++----- .../Objects/Drawables/DrawableSliderHead.cs | 44 +++++++++++++++---- .../Objects/Drawables/DrawableSliderRepeat.cs | 31 +++++++++---- .../Objects/Drawables/DrawableSliderTail.cs | 12 +++-- .../Objects/Drawables/DrawableSliderTick.cs | 14 +++++- .../Objects/Drawables/DrawableSpinner.cs | 2 +- .../Drawables/DrawableSpinnerBonusTick.cs | 5 +++ .../Objects/Drawables/DrawableSpinnerTick.cs | 5 +++ .../UI/DrawableOsuRuleset.cs | 8 ++++ 10 files changed, 106 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index d17bf93fa0..bcaf73d34f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ??= GetContainingInputManager() as OsuInputManager; - protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); + public virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); protected override void UpdateInitialTransforms() { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 05e4587307..5bbdc5ee7b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -164,10 +164,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.ClearNestedHitObjects(); - headContainer.Clear(); - tailContainer.Clear(); - repeatContainer.Clear(); - tickContainer.Clear(); + headContainer.Clear(false); + tailContainer.Clear(false); + repeatContainer.Clear(false); + tickContainer.Clear(false); } protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) @@ -178,17 +178,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return new DrawableSliderTail(tail); case SliderHeadCircle head: - return new DrawableSliderHead(HitObject, head) - { - OnShake = Shake, - CheckHittable = (d, t) => CheckHittable?.Invoke(d, t) ?? true - }; + return new DrawableSliderHead(head); case SliderTick tick: - return new DrawableSliderTick(tick) { Position = tick.Position - HitObject.Position }; + return new DrawableSliderTick(tick); case SliderRepeat repeat: - return new DrawableSliderRepeat(repeat, this) { Position = repeat.Position - HitObject.Position }; + return new DrawableSliderRepeat(repeat); } return base.CreateNestedHitObject(hitObject); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 49ed9f12e3..fd0f35d20d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -4,6 +4,8 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -14,21 +16,43 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override OsuSkinComponents CirclePieceComponent => OsuSkinComponents.SliderHeadHitCircle; - private readonly Slider slider; + private DrawableSlider drawableSlider; - public DrawableSliderHead(Slider slider, SliderHeadCircle h) + private Slider slider => drawableSlider?.HitObject; + + public DrawableSliderHead() + { + } + + public DrawableSliderHead(SliderHeadCircle h) : base(h) { - this.slider = slider; } [BackgroundDependencyLoader] private void load() { - pathVersion.BindTo(slider.Path.Version); - PositionBindable.BindValueChanged(_ => updatePosition()); - pathVersion.BindValueChanged(_ => updatePosition(), true); + pathVersion.BindValueChanged(_ => updatePosition()); + } + + protected override void OnFree(HitObject hitObject) + { + base.OnFree(hitObject); + + pathVersion.UnbindFrom(drawableSlider.PathVersion); + } + + protected override void OnParentReceived(DrawableHitObject parent) + { + base.OnParentReceived(parent); + + drawableSlider = (DrawableSlider)parent; + + pathVersion.BindTo(drawableSlider.PathVersion); + + OnShake = drawableSlider.Shake; + CheckHittable = (d, t) => drawableSlider.CheckHittable?.Invoke(d, t) ?? true; } protected override void Update() @@ -44,8 +68,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public Action OnShake; - protected override void Shake(double maximumLength) => OnShake?.Invoke(maximumLength); + public override void Shake(double maximumLength) => OnShake?.Invoke(maximumLength); - private void updatePosition() => Position = HitObject.Position - slider.Position; + private void updatePosition() + { + if (slider != null) + Position = HitObject.Position - slider.Position; + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 9c382bd0a7..0735d48ae1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -16,8 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking { - private readonly SliderRepeat sliderRepeat; - private readonly DrawableSlider drawableSlider; + public new SliderRepeat HitObject => (SliderRepeat)base.HitObject; private double animDuration; @@ -27,11 +26,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool DisplayResult => false; - public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider) + private DrawableSlider drawableSlider; + + public DrawableSliderRepeat() + : base(null) + { + } + + public DrawableSliderRepeat(SliderRepeat sliderRepeat) : base(sliderRepeat) { - this.sliderRepeat = sliderRepeat; - this.drawableSlider = drawableSlider; } [BackgroundDependencyLoader] @@ -53,18 +57,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } }; - ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); + } + + protected override void OnParentReceived(DrawableHitObject parent) + { + base.OnParentReceived(parent); + + drawableSlider = (DrawableSlider)parent; + + Position = HitObject.Position - drawableSlider.Position; } protected override void CheckForResult(bool userTriggered, double timeOffset) { - if (sliderRepeat.StartTime <= Time.Current) + if (HitObject.StartTime <= Time.Current) ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? r.Judgement.MaxResult : r.Judgement.MinResult); } protected override void UpdateInitialTransforms() { - animDuration = Math.Min(300, sliderRepeat.SpanDuration); + animDuration = Math.Min(300, HitObject.SpanDuration); this.Animate( d => d.FadeIn(animDuration), @@ -100,7 +113,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // When the repeat is hit, the arrow should fade out on spot rather than following the slider if (IsHit) return; - bool isRepeatAtEnd = sliderRepeat.RepeatIndex % 2 == 0; + bool isRepeatAtEnd = HitObject.RepeatIndex % 2 == 0; List curve = ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; Position = isRepeatAtEnd ? end : start; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 3be5983c57..eff72168ee 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking { - private readonly SliderTailCircle tailCircle; + public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject; /// /// The judgement text is provided by the . @@ -25,10 +25,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private SkinnableDrawable circlePiece; private Container scaleContainer; + public DrawableSliderTail() + : base(null) + { + } + public DrawableSliderTail(SliderTailCircle tailCircle) : base(tailCircle) { - this.tailCircle = tailCircle; } [BackgroundDependencyLoader] @@ -52,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, }; - ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); } protected override void UpdateInitialTransforms() @@ -92,6 +96,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } public void UpdateSnakingPosition(Vector2 start, Vector2 end) => - Position = tailCircle.RepeatIndex % 2 == 0 ? end : start; + Position = HitObject.RepeatIndex % 2 == 0 ? end : start; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 2af51ea486..faccf5d4d1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -24,6 +24,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private SkinnableDrawable scaleContainer; + public DrawableSliderTick() + : base(null) + { + } + public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { @@ -54,7 +59,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Origin = Anchor.Centre, }; - ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); + } + + protected override void OnParentReceived(DrawableHitObject parent) + { + base.OnParentReceived(parent); + + Position = HitObject.Position - ((DrawableSlider)parent).HitObject.Position; } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index f04a914fe3..6b33517c33 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void ClearNestedHitObjects() { base.ClearNestedHitObjects(); - ticks.Clear(); + ticks.Clear(false); } protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs index 2e1c07c4c6..ffeb14b0a8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs @@ -5,6 +5,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSpinnerBonusTick : DrawableSpinnerTick { + public DrawableSpinnerBonusTick() + : base(null) + { + } + public DrawableSpinnerBonusTick(SpinnerBonusTick spinnerTick) : base(spinnerTick) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index e9cede1398..fc9a7c00e6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -7,6 +7,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public override bool DisplayResult => false; + public DrawableSpinnerTick() + : base(null) + { + } + public DrawableSpinnerTick(SpinnerTick spinnerTick) : base(spinnerTick) { diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 86c7305439..c89f138bcd 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -38,8 +38,16 @@ namespace osu.Game.Rulesets.Osu.UI private void load() { registerPool(10, 100); + registerPool(10, 100); + registerPool(10, 100); + registerPool(10, 100); + registerPool(10, 100); + registerPool(5, 50); + registerPool(2, 20); + registerPool(10, 100); + registerPool(10, 100); } private void registerPool(int initialSize, int? maximumSize = null)