1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-22 17:22:58 +08:00

Add nested osu! hitobject pooling

This commit is contained in:
smoogipoo 2020-11-12 15:59:48 +09:00
parent 1ea526b5ef
commit 3f78d81386
10 changed files with 106 additions and 35 deletions

View File

@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private OsuInputManager osuActionInputManager; private OsuInputManager osuActionInputManager;
internal OsuInputManager OsuActionInputManager => osuActionInputManager ??= GetContainingInputManager() as OsuInputManager; 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() protected override void UpdateInitialTransforms()
{ {

View File

@ -164,10 +164,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.ClearNestedHitObjects(); base.ClearNestedHitObjects();
headContainer.Clear(); headContainer.Clear(false);
tailContainer.Clear(); tailContainer.Clear(false);
repeatContainer.Clear(); repeatContainer.Clear(false);
tickContainer.Clear(); tickContainer.Clear(false);
} }
protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)
@ -178,17 +178,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
return new DrawableSliderTail(tail); return new DrawableSliderTail(tail);
case SliderHeadCircle head: case SliderHeadCircle head:
return new DrawableSliderHead(HitObject, head) return new DrawableSliderHead(head);
{
OnShake = Shake,
CheckHittable = (d, t) => CheckHittable?.Invoke(d, t) ?? true
};
case SliderTick tick: case SliderTick tick:
return new DrawableSliderTick(tick) { Position = tick.Position - HitObject.Position }; return new DrawableSliderTick(tick);
case SliderRepeat repeat: case SliderRepeat repeat:
return new DrawableSliderRepeat(repeat, this) { Position = repeat.Position - HitObject.Position }; return new DrawableSliderRepeat(repeat);
} }
return base.CreateNestedHitObject(hitObject); return base.CreateNestedHitObject(hitObject);

View File

@ -4,6 +4,8 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
@ -14,21 +16,43 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override OsuSkinComponents CirclePieceComponent => OsuSkinComponents.SliderHeadHitCircle; 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) : base(h)
{ {
this.slider = slider;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
pathVersion.BindTo(slider.Path.Version);
PositionBindable.BindValueChanged(_ => updatePosition()); 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() protected override void Update()
@ -44,8 +68,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public Action<double> OnShake; public Action<double> 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;
}
} }
} }

View File

@ -16,8 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
public class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking public class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking
{ {
private readonly SliderRepeat sliderRepeat; public new SliderRepeat HitObject => (SliderRepeat)base.HitObject;
private readonly DrawableSlider drawableSlider;
private double animDuration; private double animDuration;
@ -27,11 +26,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public override bool DisplayResult => false; public override bool DisplayResult => false;
public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider) private DrawableSlider drawableSlider;
public DrawableSliderRepeat()
: base(null)
{
}
public DrawableSliderRepeat(SliderRepeat sliderRepeat)
: base(sliderRepeat) : base(sliderRepeat)
{ {
this.sliderRepeat = sliderRepeat;
this.drawableSlider = drawableSlider;
} }
[BackgroundDependencyLoader] [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) 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); ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? r.Judgement.MaxResult : r.Judgement.MinResult);
} }
protected override void UpdateInitialTransforms() protected override void UpdateInitialTransforms()
{ {
animDuration = Math.Min(300, sliderRepeat.SpanDuration); animDuration = Math.Min(300, HitObject.SpanDuration);
this.Animate( this.Animate(
d => d.FadeIn(animDuration), 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 // When the repeat is hit, the arrow should fade out on spot rather than following the slider
if (IsHit) return; if (IsHit) return;
bool isRepeatAtEnd = sliderRepeat.RepeatIndex % 2 == 0; bool isRepeatAtEnd = HitObject.RepeatIndex % 2 == 0;
List<Vector2> curve = ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; List<Vector2> curve = ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve;
Position = isRepeatAtEnd ? end : start; Position = isRepeatAtEnd ? end : start;

View File

@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking
{ {
private readonly SliderTailCircle tailCircle; public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject;
/// <summary> /// <summary>
/// The judgement text is provided by the <see cref="DrawableSlider"/>. /// The judgement text is provided by the <see cref="DrawableSlider"/>.
@ -25,10 +25,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private SkinnableDrawable circlePiece; private SkinnableDrawable circlePiece;
private Container scaleContainer; private Container scaleContainer;
public DrawableSliderTail()
: base(null)
{
}
public DrawableSliderTail(SliderTailCircle tailCircle) public DrawableSliderTail(SliderTailCircle tailCircle)
: base(tailCircle) : base(tailCircle)
{ {
this.tailCircle = tailCircle;
} }
[BackgroundDependencyLoader] [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() protected override void UpdateInitialTransforms()
@ -92,6 +96,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
public void UpdateSnakingPosition(Vector2 start, Vector2 end) => public void UpdateSnakingPosition(Vector2 start, Vector2 end) =>
Position = tailCircle.RepeatIndex % 2 == 0 ? end : start; Position = HitObject.RepeatIndex % 2 == 0 ? end : start;
} }
} }

View File

@ -24,6 +24,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private SkinnableDrawable scaleContainer; private SkinnableDrawable scaleContainer;
public DrawableSliderTick()
: base(null)
{
}
public DrawableSliderTick(SliderTick sliderTick) public DrawableSliderTick(SliderTick sliderTick)
: base(sliderTick) : base(sliderTick)
{ {
@ -54,7 +59,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Origin = Anchor.Centre, 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) protected override void CheckForResult(bool userTriggered, double timeOffset)

View File

@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void ClearNestedHitObjects() protected override void ClearNestedHitObjects()
{ {
base.ClearNestedHitObjects(); base.ClearNestedHitObjects();
ticks.Clear(); ticks.Clear(false);
} }
protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject)

View File

@ -5,6 +5,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
public class DrawableSpinnerBonusTick : DrawableSpinnerTick public class DrawableSpinnerBonusTick : DrawableSpinnerTick
{ {
public DrawableSpinnerBonusTick()
: base(null)
{
}
public DrawableSpinnerBonusTick(SpinnerBonusTick spinnerTick) public DrawableSpinnerBonusTick(SpinnerBonusTick spinnerTick)
: base(spinnerTick) : base(spinnerTick)
{ {

View File

@ -7,6 +7,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
public override bool DisplayResult => false; public override bool DisplayResult => false;
public DrawableSpinnerTick()
: base(null)
{
}
public DrawableSpinnerTick(SpinnerTick spinnerTick) public DrawableSpinnerTick(SpinnerTick spinnerTick)
: base(spinnerTick) : base(spinnerTick)
{ {

View File

@ -38,8 +38,16 @@ namespace osu.Game.Rulesets.Osu.UI
private void load() private void load()
{ {
registerPool<HitCircle, DrawableHitCircle>(10, 100); registerPool<HitCircle, DrawableHitCircle>(10, 100);
registerPool<Slider, DrawableSlider>(10, 100); registerPool<Slider, DrawableSlider>(10, 100);
registerPool<SliderHeadCircle, DrawableSliderHead>(10, 100);
registerPool<SliderTailCircle, DrawableSliderTail>(10, 100);
registerPool<SliderTick, DrawableSliderTick>(10, 100);
registerPool<SliderRepeat, DrawableSliderRepeat>(5, 50);
registerPool<Spinner, DrawableSpinner>(2, 20); registerPool<Spinner, DrawableSpinner>(2, 20);
registerPool<SpinnerTick, DrawableSpinnerTick>(10, 100);
registerPool<SpinnerBonusTick, DrawableSpinnerBonusTick>(10, 100);
} }
private void registerPool<TObject, TDrawable>(int initialSize, int? maximumSize = null) private void registerPool<TObject, TDrawable>(int initialSize, int? maximumSize = null)