diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs index 49d7d9249c..a452f93676 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs @@ -295,7 +295,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor private void assertControlPointPosition(int index, Vector2 position) => AddAssert($"control point {index} at {position}", () => Precision.AlmostEquals(position, getSlider().Path.ControlPoints[index].Position.Value, 1)); - private Slider getSlider() => HitObjectContainer.Count > 0 ? (Slider)((DrawableSlider)HitObjectContainer[0]).HitObject : null; + private Slider getSlider() => HitObjectContainer.Count > 0 ? ((DrawableSlider)HitObjectContainer[0]).HitObject : null; protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject); protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index c9e112f76d..c400e2f2ea 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -112,10 +112,10 @@ namespace osu.Game.Rulesets.Osu.Tests new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, }); - AddAssert("head samples updated", () => assertSamples(((Slider)slider.HitObject).HeadCircle)); - AddAssert("tick samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertTickSamples)); - AddAssert("repeat samples updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); - AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); + AddAssert("head samples updated", () => assertSamples(slider.HitObject.HeadCircle)); + AddAssert("tick samples not updated", () => slider.HitObject.NestedHitObjects.OfType().All(assertTickSamples)); + AddAssert("repeat samples updated", () => slider.HitObject.NestedHitObjects.OfType().All(assertSamples)); + AddAssert("tail has no samples", () => slider.HitObject.TailCircle.Samples.Count == 0); static bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests slider = (DrawableSlider)createSlider(repeats: 1); for (int i = 0; i < 2; i++) - ((Slider)slider.HitObject).NodeSamples.Add(new List { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } }); + slider.HitObject.NodeSamples.Add(new List { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } }); Add(slider); }); @@ -147,10 +147,10 @@ namespace osu.Game.Rulesets.Osu.Tests new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, }); - AddAssert("head samples not updated", () => assertSamples(((Slider)slider.HitObject).HeadCircle)); - AddAssert("tick samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertTickSamples)); - AddAssert("repeat samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); - AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); + AddAssert("head samples not updated", () => assertSamples(slider.HitObject.HeadCircle)); + AddAssert("tick samples not updated", () => slider.HitObject.NestedHitObjects.OfType().All(assertTickSamples)); + AddAssert("repeat samples not updated", () => slider.HitObject.NestedHitObjects.OfType().All(assertSamples)); + AddAssert("tail has no samples", () => slider.HitObject.TailCircle.Samples.Count == 0); static bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index d3fb5defae..f851c7bfc9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override void OnSelected() { - AddInternal(ControlPointVisualiser = new PathControlPointVisualiser((Slider)slider.HitObject, true) + AddInternal(ControlPointVisualiser = new PathControlPointVisualiser(slider.HitObject, true) { RemoveControlPointsRequested = removeControlPoints }); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index b5ac26c824..0c26e2b52f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -21,28 +20,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - public ApproachCircle ApproachCircle { get; } - - private readonly IBindable positionBindable = new Bindable(); - private readonly IBindable stackHeightBindable = new Bindable(); - private readonly IBindable scaleBindable = new BindableFloat(); - public OsuAction? HitAction => HitArea.HitAction; - - public readonly HitReceptor HitArea; - public readonly SkinnableDrawable CirclePiece; - private readonly Container scaleContainer; - protected virtual OsuSkinComponents CirclePieceComponent => OsuSkinComponents.HitCircle; + public ApproachCircle ApproachCircle { get; private set; } + public HitReceptor HitArea { get; private set; } + public SkinnableDrawable CirclePiece { get; private set; } + + private Container scaleContainer; private InputManager inputManager; public DrawableHitCircle(HitCircle h) : base(h) { - Origin = Anchor.Centre; + } - Position = HitObject.StackedPosition; + [BackgroundDependencyLoader] + private void load() + { + Origin = Anchor.Centre; InternalChildren = new Drawable[] { @@ -75,19 +71,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; Size = HitArea.DrawSize; - } - - [BackgroundDependencyLoader] - private void load() - { - positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); - - positionBindable.BindTo(HitObject.PositionBindable); - stackHeightBindable.BindTo(HitObject.StackHeightBindable); - scaleBindable.BindTo(HitObject.ScaleBindable); + PositionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition, true); + StackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition, true); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); AccentColour.BindValueChanged(accent => ApproachCircle.Colour = accent.NewValue, true); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 45c664ba3b..c83bdf17d5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -2,18 +2,24 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Osu.UI; +using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - private readonly ShakeContainer shakeContainer; + public readonly IBindable PositionBindable = new Bindable(); + public readonly IBindable StackHeightBindable = new Bindable(); + public readonly IBindable ScaleBindable = new BindableFloat(); + public readonly IBindable IndexInCurrentComboBindable = new Bindable(); // Must be set to update IsHovered as it's used in relax mdo to detect osu hit objects. public override bool HandlePositionalInput => true; @@ -26,16 +32,28 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// public Func CheckHittable; + private ShakeContainer shakeContainer; + protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { + } + + [BackgroundDependencyLoader] + private void load() + { + Alpha = 0; + base.AddInternal(shakeContainer = new ShakeContainer { ShakeDuration = 30, RelativeSizeAxes = Axes.Both }); - Alpha = 0; + IndexInCurrentComboBindable.BindTo(HitObject.IndexInCurrentComboBindable); + PositionBindable.BindTo(HitObject.PositionBindable); + StackHeightBindable.BindTo(HitObject.StackHeightBindable); + ScaleBindable.BindTo(HitObject.ScaleBindable); } // Forward all internal management to shakeContainer. diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index b00d12983d..b743d2e4d0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -20,62 +20,50 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { + public new Slider HitObject => (Slider)base.HitObject; + public DrawableSliderHead HeadCircle => headContainer.Child; public DrawableSliderTail TailCircle => tailContainer.Child; - public readonly SliderBall Ball; - public readonly SkinnableDrawable Body; + public SliderBall Ball { get; private set; } + public SkinnableDrawable Body { get; private set; } public override bool DisplayResult => false; private PlaySliderBody sliderBody => Body.Drawable as PlaySliderBody; - private readonly Container headContainer; - private readonly Container tailContainer; - private readonly Container tickContainer; - private readonly Container repeatContainer; - - private readonly Slider slider; - - private readonly IBindable positionBindable = new Bindable(); - private readonly IBindable stackHeightBindable = new Bindable(); - private readonly IBindable scaleBindable = new BindableFloat(); + private Container headContainer; + private Container tailContainer; + private Container tickContainer; + private Container repeatContainer; public DrawableSlider(Slider s) : base(s) { - slider = s; - - Position = s.StackedPosition; + } + [BackgroundDependencyLoader] + private void load() + { InternalChildren = new Drawable[] { Body = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new DefaultSliderBody(), confineMode: ConfineMode.NoScaling), tailContainer = new Container { RelativeSizeAxes = Axes.Both }, tickContainer = new Container { RelativeSizeAxes = Axes.Both }, repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, - Ball = new SliderBall(s, this) + Ball = new SliderBall(HitObject, this) { GetInitialHitAction = () => HeadCircle.HitAction, BypassAutoSizeAxes = Axes.Both, - Scale = new Vector2(s.Scale), AlwaysPresent = true, Alpha = 0 }, headContainer = new Container { RelativeSizeAxes = Axes.Both }, }; - } - [BackgroundDependencyLoader] - private void load() - { - positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(scale => Ball.Scale = new Vector2(scale.NewValue)); - - positionBindable.BindTo(HitObject.PositionBindable); - stackHeightBindable.BindTo(HitObject.StackHeightBindable); - scaleBindable.BindTo(HitObject.ScaleBindable); + PositionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition, true); + StackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition, true); + ScaleBindable.BindValueChanged(scale => Ball.Scale = new Vector2(scale.NewValue), true); AccentColour.BindValueChanged(colour => { @@ -162,20 +150,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (hitObject) { case SliderTailCircle tail: - return new DrawableSliderTail(slider, tail); + return new DrawableSliderTail(tail); case SliderHeadCircle head: - return new DrawableSliderHead(slider, head) + return new DrawableSliderHead(HitObject, head) { OnShake = Shake, CheckHittable = (d, t) => CheckHittable?.Invoke(d, t) ?? true }; case SliderTick tick: - return new DrawableSliderTick(tick) { Position = tick.Position - slider.Position }; + return new DrawableSliderTick(tick) { Position = tick.Position - HitObject.Position }; case SliderRepeat repeat: - return new DrawableSliderRepeat(repeat, this) { Position = repeat.Position - slider.Position }; + return new DrawableSliderRepeat(repeat, this) { Position = repeat.Position - HitObject.Position }; } return base.CreateNestedHitObject(hitObject); @@ -200,14 +188,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // keep the sliding sample playing at the current tracking position slidingSample.Balance.Value = CalculateSamplePlaybackBalance(Ball.X / OsuPlayfield.BASE_SIZE.X); - double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - HitObject.StartTime) / HitObject.Duration, 0, 1); Ball.UpdateProgress(completionProgress); sliderBody?.UpdateProgress(completionProgress); foreach (DrawableHitObject hitObject in NestedHitObjects) { - if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(sliderBody?.SnakedStart ?? 0), slider.Path.PositionAt(sliderBody?.SnakedEnd ?? 0)); + if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(HitObject.Path.PositionAt(sliderBody?.SnakedStart ?? 0), HitObject.Path.PositionAt(sliderBody?.SnakedEnd ?? 0)); if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking; } @@ -239,7 +227,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { - if (userTriggered || Time.Current < slider.EndTime) + if (userTriggered || Time.Current < HitObject.EndTime) return; ApplyResult(r => r.Type = r.Judgement.MaxResult); @@ -260,7 +248,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Ball.FadeIn(); Ball.ScaleTo(HitObject.Scale); - using (BeginDelayedSequence(slider.Duration, true)) + using (BeginDelayedSequence(HitObject.Duration, true)) { const float fade_out_time = 450; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 04f563eeec..49ed9f12e3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -5,13 +5,11 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderHead : DrawableHitCircle { - private readonly IBindable positionBindable = new Bindable(); private readonly IBindable pathVersion = new Bindable(); protected override OsuSkinComponents CirclePieceComponent => OsuSkinComponents.SliderHeadHitCircle; @@ -27,10 +25,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables [BackgroundDependencyLoader] private void load() { - positionBindable.BindTo(HitObject.PositionBindable); pathVersion.BindTo(slider.Path.Version); - positionBindable.BindValueChanged(_ => updatePosition()); + PositionBindable.BindValueChanged(_ => updatePosition()); pathVersion.BindValueChanged(_ => updatePosition(), true); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 2a88f11f69..b57bb8dbbf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -22,9 +21,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private double animDuration; - private readonly Drawable scaleContainer; - - public readonly Drawable CirclePiece; + public Drawable CirclePiece { get; private set; } + private Drawable scaleContainer; + private ReverseArrowPiece arrow; public override bool DisplayResult => false; @@ -33,10 +32,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { this.sliderRepeat = sliderRepeat; this.drawableSlider = drawableSlider; + } - Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); - + [BackgroundDependencyLoader] + private void load() + { Origin = Anchor.Centre; + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); InternalChild = scaleContainer = new Container { @@ -50,15 +52,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables arrow = new ReverseArrowPiece(), } }; - } - private readonly IBindable scaleBindable = new BindableFloat(); - - [BackgroundDependencyLoader] - private void load() - { - scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); - scaleBindable.BindTo(HitObject.ScaleBindable); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); } protected override void CheckForResult(bool userTriggered, double timeOffset) @@ -100,8 +95,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private bool hasRotation; - private readonly ReverseArrowPiece arrow; - public void UpdateSnakingPosition(Vector2 start, Vector2 end) { // When the repeat is hit, the arrow should fade out on spot rather than following the slider diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index f5bcecccdf..7e30f4e132 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; @@ -23,18 +22,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool Tracking { get; set; } - private readonly IBindable scaleBindable = new BindableFloat(); + private SkinnableDrawable circlePiece; + private Container scaleContainer; - private readonly SkinnableDrawable circlePiece; - - private readonly Container scaleContainer; - - public DrawableSliderTail(Slider slider, SliderTailCircle tailCircle) + public DrawableSliderTail(SliderTailCircle tailCircle) : base(tailCircle) { this.tailCircle = tailCircle; - Origin = Anchor.Centre; + } + [BackgroundDependencyLoader] + private void load() + { + Origin = Anchor.Centre; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); InternalChildren = new Drawable[] @@ -51,13 +51,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } }, }; - } - [BackgroundDependencyLoader] - private void load() - { - scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); - scaleBindable.BindTo(HitObject.ScaleBindable); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 9b68b446a4..81d12f3432 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osuTK; @@ -23,10 +22,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool DisplayResult => false; - private readonly SkinnableDrawable scaleContainer; + private SkinnableDrawable scaleContainer; public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) + { + } + + [BackgroundDependencyLoader] + private void load() { Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Origin = Anchor.Centre; @@ -49,15 +53,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre, }; - } - private readonly IBindable scaleBindable = new BindableFloat(); - - [BackgroundDependencyLoader] - private void load() - { - scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); - scaleBindable.BindTo(HitObject.ScaleBindable); + ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); } 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 936bfaeb86..50ea45c378 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -16,34 +16,33 @@ using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Skinning; -using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSpinner : DrawableOsuHitObject { - protected readonly Spinner Spinner; + public new Spinner HitObject => (Spinner)base.HitObject; - private readonly Container ticks; + public SpinnerRotationTracker RotationTracker { get; private set; } + public SpinnerSpmCounter SpmCounter { get; private set; } - public readonly SpinnerRotationTracker RotationTracker; - public readonly SpinnerSpmCounter SpmCounter; - private readonly SpinnerBonusDisplay bonusDisplay; - - private readonly IBindable positionBindable = new Bindable(); + private Container ticks; + private SpinnerBonusDisplay bonusDisplay; + private Bindable isSpinning; private bool spinnerFrequencyModulate; public DrawableSpinner(Spinner s) : base(s) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) { Origin = Anchor.Centre; - Position = s.Position; - RelativeSizeAxes = Axes.Both; - Spinner = s; - InternalChildren = new Drawable[] { ticks = new Container(), @@ -55,7 +54,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Children = new Drawable[] { new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SpinnerBody), _ => new DefaultSpinnerDisc()), - RotationTracker = new SpinnerRotationTracker(Spinner) + RotationTracker = new SpinnerRotationTracker(HitObject) } }, SpmCounter = new SpinnerSpmCounter @@ -72,9 +71,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Y = -120, } }; - } - private Bindable isSpinning; + PositionBindable.BindValueChanged(pos => Position = pos.NewValue, true); + } protected override void LoadComplete() { @@ -146,7 +145,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateStateTransforms(state); - using (BeginDelayedSequence(Spinner.Duration, true)) + using (BeginDelayedSequence(HitObject.Duration, true)) this.FadeOut(160); // skin change does a rewind of transforms, which will stop the spinning sound from playing if it's currently in playback. @@ -173,13 +172,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return base.CreateNestedHitObject(hitObject); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - positionBindable.BindValueChanged(pos => Position = pos.NewValue); - positionBindable.BindTo(HitObject.PositionBindable); - } - protected override void ApplySkin(ISkinSource skin, bool allowFallback) { base.ApplySkin(skin, allowFallback); @@ -193,12 +185,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { get { - if (Spinner.SpinsRequired == 0) + if (HitObject.SpinsRequired == 0) // some spinners are so short they can't require an integer spin count. // these become implicitly hit. return 1; - return Math.Clamp(RotationTracker.RateAdjustedRotation / 360 / Spinner.SpinsRequired, 0, 1); + return Math.Clamp(RotationTracker.RateAdjustedRotation / 360 / HitObject.SpinsRequired, 0, 1); } } @@ -208,7 +200,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables RotationTracker.Complete.Value = Progress >= 1; - if (userTriggered || Time.Current < Spinner.EndTime) + if (userTriggered || Time.Current < HitObject.EndTime) return; // Trigger a miss result for remaining ticks to avoid infinite gameplay. @@ -223,7 +215,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables r.Type = HitResult.Ok; else if (Progress > .75) r.Type = HitResult.Meh; - else if (Time.Current >= Spinner.EndTime) + else if (Time.Current >= HitObject.EndTime) r.Type = r.Judgement.MinResult; }); } @@ -275,7 +267,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { tick.TriggerResult(true); if (tick is DrawableSpinnerBonusTick) - bonusDisplay.SetBonusCount(spins - Spinner.SpinsRequired); + bonusDisplay.SetBonusCount(spins - HitObject.SpinsRequired); } wholeSpins++; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs index e855317544..17a734f0f4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private void load(OsuColour colours, DrawableHitObject drawableHitObject) { drawableSpinner = (DrawableSpinner)drawableHitObject; - spinner = (Spinner)drawableSpinner.HitObject; + spinner = drawableSpinner.HitObject; normalColour = colours.BlueDark; completeColour = colours.YellowLight; diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs index 56b5571ce1..018dc78ddb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Utils; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK; @@ -79,7 +78,7 @@ namespace osu.Game.Rulesets.Osu.Skinning if (!(drawableHitObject is DrawableSpinner)) return; - var spinner = (Spinner)drawableSpinner.HitObject; + var spinner = drawableSpinner.HitObject; using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimePreempt, true)) this.FadeOut(); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1ef6c8c207..cd31e468af 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -125,14 +125,14 @@ namespace osu.Game.Rulesets.Objects.Drawables Result = CreateResult(judgement); if (Result == null) throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); - - LoadSamples(); } protected override void LoadAsyncComplete() { base.LoadAsyncComplete(); + LoadSamples(); + HitObject.DefaultsApplied += onDefaultsApplied; startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy();