From 4ac2e1c58ee1aab9bbac8cb62dc717a8e03f5d3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 21:41:18 +0900 Subject: [PATCH 01/13] Move load() to below ctor() --- .../Objects/Drawables/DrawableSlider.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 9e8ad9851c..09157d4fdc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -94,13 +94,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void UpdateInitialTransforms() - { - base.UpdateInitialTransforms(); - - Body.FadeInFromZero(HitObject.TimeFadeIn); - } - [BackgroundDependencyLoader] private void load() { @@ -129,6 +122,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } + protected override void UpdateInitialTransforms() + { + base.UpdateInitialTransforms(); + + Body.FadeInFromZero(HitObject.TimeFadeIn); + } + public readonly Bindable Tracking = new Bindable(); protected override void Update() From 8d7453c251b68243ed6a082f815a1d2133e71aa4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 22:10:50 +0900 Subject: [PATCH 02/13] Rework construction of nested hitobjects --- .../Objects/Drawables/DrawableSlider.cs | 124 +++++++++++------- .../Objects/Drawables/DrawableHitObject.cs | 44 +++++-- 2 files changed, 111 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 09157d4fdc..21411259ae 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -5,7 +5,6 @@ using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -21,15 +20,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - private readonly Slider slider; - private readonly List components = new List(); - - public readonly DrawableHitCircle HeadCircle; - public readonly DrawableSliderTail TailCircle; + public DrawableSliderHead HeadCircle { get; private set; } + public DrawableSliderTail TailCircle { get; private set; } public readonly SnakingSliderBody Body; public readonly SliderBall Ball; + 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 scaleBindable = new Bindable(); private readonly IBindable pathBindable = new Bindable(); @@ -44,14 +47,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Position = s.StackedPosition; - Container ticks; - Container repeatPoints; - InternalChildren = new Drawable[] { Body = new SnakingSliderBody(s), - ticks = new Container { RelativeSizeAxes = Axes.Both }, - repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, + repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) { GetInitialHitAction = () => HeadCircle.HitAction, @@ -60,38 +60,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true, Alpha = 0 }, - HeadCircle = new DrawableSliderHead(s, s.HeadCircle) - { - OnShake = Shake - }, - TailCircle = new DrawableSliderTail(s, s.TailCircle) + headContainer = new Container { RelativeSizeAxes = Axes.Both }, + tailContainer = new Container { RelativeSizeAxes = Axes.Both }, }; - - components.Add(Body); - components.Add(Ball); - - AddNested(HeadCircle); - - AddNested(TailCircle); - components.Add(TailCircle); - - foreach (var tick in s.NestedHitObjects.OfType()) - { - var drawableTick = new DrawableSliderTick(tick) { Position = tick.Position - s.Position }; - - ticks.Add(drawableTick); - components.Add(drawableTick); - AddNested(drawableTick); - } - - foreach (var repeatPoint in s.NestedHitObjects.OfType()) - { - var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this) { Position = repeatPoint.Position - s.Position }; - - repeatPoints.Add(drawableRepeatPoint); - components.Add(drawableRepeatPoint); - AddNested(drawableRepeatPoint); - } } [BackgroundDependencyLoader] @@ -122,6 +93,60 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableSliderHead head: + headContainer.Child = HeadCircle = head; + break; + + case DrawableSliderTail tail: + tailContainer.Child = TailCircle = tail; + break; + + case DrawableSliderTick tick: + tickContainer.Add(tick); + break; + + case DrawableRepeatPoint repeat: + repeatContainer.Add(repeat); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + + headContainer.Clear(); + tailContainer.Clear(); + repeatContainer.Clear(); + tickContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case SliderTailCircle tail: + return new DrawableSliderTail(slider, tail); + + case HitCircle head: + return new DrawableSliderHead(slider, head) { OnShake = Shake }; + + case SliderTick tick: + return new DrawableSliderTick(tick) { Position = tick.Position - slider.Position }; + + case RepeatPoint repeat: + return new DrawableRepeatPoint(repeat, this) { Position = repeat.Position - slider.Position }; + } + + return base.CreateNested(hitObject); + } + protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); @@ -139,9 +164,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); - foreach (var c in components.OfType()) c.UpdateProgress(completionProgress); - foreach (var c in components.OfType()) c.UpdateSnakingPosition(slider.Path.PositionAt(Body.SnakedStart ?? 0), slider.Path.PositionAt(Body.SnakedEnd ?? 0)); - foreach (var t in components.OfType()) t.Tracking = Ball.Tracking; + Ball.UpdateProgress(completionProgress); + Body.UpdateProgress(completionProgress); + + foreach (DrawableHitObject hitObject in NestedHitObjects) + { + if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(Body.SnakedStart ?? 0), slider.Path.PositionAt(Body.SnakedEnd ?? 0)); + if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking; + } Size = Body.Size; OriginPosition = Body.PathOffset; @@ -187,7 +217,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApplyResult(r => { - var judgementsCount = NestedHitObjects.Count(); + var judgementsCount = NestedHitObjects.Count; var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; @@ -228,7 +258,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public Drawable ProxiedLayer => HeadCircle.ApproachCircle; + public Drawable ProxiedLayer => new Container(); // Todo: public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Body.ReceivePositionalInputAt(screenSpacePos); } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7f3bfd3b5c..6bc2ccb889 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual IEnumerable GetSamples() => HitObject.Samples; private readonly Lazy> nestedHitObjects = new Lazy>(); - public IEnumerable NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty(); + public IReadOnlyList NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : (IReadOnlyList)Array.Empty(); /// /// Invoked when a has been applied by this or a nested . @@ -125,6 +125,8 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); + Apply(HitObject); + if (HitObject is IHasComboInformation combo) { comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy(); @@ -134,6 +136,37 @@ namespace osu.Game.Rulesets.Objects.Drawables updateState(ArmedState.Idle, true); } + protected void Apply(HitObject hitObject) + { + if (nestedHitObjects.IsValueCreated) + { + nestedHitObjects.Value.Clear(); + ClearNested(); + } + + foreach (var h in hitObject.NestedHitObjects) + { + var drawableNested = CreateNested(h) ?? throw new InvalidOperationException($"{nameof(CreateNested)} returned null for {h.GetType().ReadableName()}."); + + drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); + drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Value.Add(drawableNested); + AddNested(drawableNested); + } + } + + protected virtual void AddNested(DrawableHitObject h) + { + } + + protected virtual void ClearNested() + { + } + + protected virtual DrawableHitObject CreateNested(HitObject hitObject) => null; + #region State / Transform Management /// @@ -356,15 +389,6 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateResult(false); } - protected virtual void AddNested(DrawableHitObject h) - { - h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); - h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); - - nestedHitObjects.Value.Add(h); - } - /// /// Applies the of this , notifying responders such as /// the of the . From d49ef6a36bac0a60364f42a3ff7daab2c72e0fc0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 11:57:00 +0900 Subject: [PATCH 03/13] Make taiko use the new nested hitobject structure --- .../Objects/Drawables/DrawableDrumRoll.cs | 69 ++++++++++++++----- .../Objects/Drawables/DrawableSwell.cs | 56 +++++++++++---- .../Drawables/DrawableTaikoHitObject.cs | 39 ++++++++--- 3 files changed, 124 insertions(+), 40 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 8e16a21199..d98043b1b7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -28,31 +29,18 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private int rollingHits; + private readonly Container tickContainer; + + private Color4 colourIdle; + private Color4 colourEngaged; + public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { RelativeSizeAxes = Axes.Y; - - Container tickContainer; MainPiece.Add(tickContainer = new Container { RelativeSizeAxes = Axes.Both }); - - foreach (var tick in drumRoll.NestedHitObjects.OfType()) - { - var newTick = new DrawableDrumRollTick(tick); - newTick.OnNewResult += onNewTickResult; - - AddNested(newTick); - tickContainer.Add(newTick); - } } - protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); - - public override bool OnPressed(TaikoAction action) => false; - - private Color4 colourIdle; - private Color4 colourEngaged; - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -60,8 +48,51 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables colourEngaged = colours.YellowDarker; } - private void onNewTickResult(DrawableHitObject obj, JudgementResult result) + protected override void LoadComplete() { + base.LoadComplete(); + + OnNewResult += onNewResult; + } + + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableDrumRollTick tick: + tickContainer.Add(tick); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + tickContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case DrumRollTick tick: + return new DrawableDrumRollTick(tick); + } + + return base.CreateNested(hitObject); + } + + protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); + + public override bool OnPressed(TaikoAction action) => false; + + private void onNewResult(DrawableHitObject obj, JudgementResult result) + { + if (!(obj is DrawableDrumRollTick)) + return; + if (result.Type > HitResult.Miss) rollingHits++; else diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 07af7fe7e0..164944f00a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -14,6 +13,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -30,8 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const double ring_appear_offset = 100; - private readonly List ticks = new List(); - + private readonly Container ticks; private readonly Container bodyContainer; private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; @@ -108,16 +107,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } }); + AddInternal(ticks = new Container { RelativeSizeAxes = Axes.Both }); + MainPiece.Add(symbol = new SwellSymbolPiece()); - - foreach (var tick in HitObject.NestedHitObjects.OfType()) - { - var vis = new DrawableSwellTick(tick); - - ticks.Add(vis); - AddInternal(vis); - AddNested(vis); - } } [BackgroundDependencyLoader] @@ -136,11 +128,49 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableSwellTick tick: + ticks.Add(tick); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + ticks.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case SwellTick tick: + return new DrawableSwellTick(tick); + } + + return base.CreateNested(hitObject); + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered) { - var nextTick = ticks.Find(j => !j.IsHit); + DrawableSwellTick nextTick = null; + + foreach (var t in ticks) + { + if (!t.IsHit) + { + nextTick = t; + break; + } + } nextTick?.TriggerResult(HitResult.Great); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 423f65b2d3..b89cd7c09f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -11,6 +11,7 @@ using osu.Game.Audio; using System.Collections.Generic; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -109,11 +110,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); - protected readonly Vector2 BaseSize; + public new TaikoHitType HitObject; + protected readonly Vector2 BaseSize; protected readonly TaikoPiece MainPiece; - public new TaikoHitType HitObject; + private readonly Container strongHitContainer; protected DrawableTaikoHitObject(TaikoHitType hitObject) : base(hitObject) @@ -129,17 +131,38 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Content.Add(MainPiece = CreateMainPiece()); MainPiece.KiaiMode = HitObject.Kiai; - var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); + AddInternal(strongHitContainer = new Container()); + } - if (strongObject != null) + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) { - var strongHit = CreateStrongHit(strongObject); - - AddNested(strongHit); - AddInternal(strongHit); + case DrawableStrongNestedHit strong: + strongHitContainer.Add(strong); + break; } } + protected override void ClearNested() + { + base.ClearNested(); + strongHitContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case StrongHitObject strong: + return CreateStrongHit(strong); + } + + return base.CreateNested(hitObject); + } + // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); From 1a0dfcdd4601ec2eff43eebf4ebee20e14570405 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:37:09 +0900 Subject: [PATCH 04/13] Make catch use the new nested hitobject structure --- .../Objects/Drawable/DrawableBananaShower.cs | 27 +++++++++++++---- .../Objects/Drawable/DrawableJuiceStream.cs | 30 +++++++++++++------ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 42646851d7..57ffd23e85 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -2,35 +2,50 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableBananaShower : DrawableCatchHitObject { + private readonly Func> createDrawableRepresentation; private readonly Container bananaContainer; public DrawableBananaShower(BananaShower s, Func> createDrawableRepresentation = null) : base(s) { + this.createDrawableRepresentation = createDrawableRepresentation; RelativeSizeAxes = Axes.X; Origin = Anchor.BottomLeft; X = 0; AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); - - foreach (var b in s.NestedHitObjects.Cast()) - AddNested(createDrawableRepresentation?.Invoke(b)); } protected override void AddNested(DrawableHitObject h) { - ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; - bananaContainer.Add(h); base.AddNested(h); + bananaContainer.Add(h); + } + + protected override void ClearNested() + { + base.ClearNested(); + bananaContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case Banana banana: + return createDrawableRepresentation?.Invoke(banana)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); + } + + return base.CreateNested(hitObject); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 9e5e9f6a04..1bbb7b08a5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -2,38 +2,50 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableJuiceStream : DrawableCatchHitObject { + private readonly Func> createDrawableRepresentation; private readonly Container dropletContainer; public DrawableJuiceStream(JuiceStream s, Func> createDrawableRepresentation = null) : base(s) { + this.createDrawableRepresentation = createDrawableRepresentation; RelativeSizeAxes = Axes.Both; Origin = Anchor.BottomLeft; X = 0; AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); - - foreach (var o in s.NestedHitObjects.Cast()) - AddNested(createDrawableRepresentation?.Invoke(o)); } protected override void AddNested(DrawableHitObject h) { - var catchObject = (DrawableCatchHitObject)h; - - catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false; - - dropletContainer.Add(h); base.AddNested(h); + dropletContainer.Add(h); + } + + protected override void ClearNested() + { + base.ClearNested(); + dropletContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case CatchHitObject catchObject: + return createDrawableRepresentation?.Invoke(catchObject)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); + } + + return base.CreateNested(hitObject); } } } From 8a284bacba34ed8a4a5759e89a237df19fea4087 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:37:20 +0900 Subject: [PATCH 05/13] Make mania use the new nested hitobject structure --- .../Objects/Drawables/DrawableHoldNote.cs | 106 ++++++++++++------ 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index c5c157608f..78969b7361 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,13 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; -using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -22,8 +21,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { public override bool DisplayResult => false; - public readonly DrawableNote Head; - public readonly DrawableNote Tail; + private readonly Container headContainer; + private readonly Container tailContainer; + private readonly Container tickContainer; + + public DrawableNote Head { get; private set; } + public DrawableNote Tail { get; private set; } private readonly BodyPiece bodyPiece; @@ -40,50 +43,81 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableHoldNote(HoldNote hitObject) : base(hitObject) { - Container tickContainer; RelativeSizeAxes = Axes.X; AddRangeInternal(new Drawable[] { - bodyPiece = new BodyPiece - { - RelativeSizeAxes = Axes.X, - }, - tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - ChildrenEnumerable = HitObject.NestedHitObjects.OfType().Select(tick => new DrawableHoldNoteTick(tick) - { - HoldStartTime = () => holdStartTime - }) - }, - Head = new DrawableHeadNote(this) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, - Tail = new DrawableTailNote(this) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - } + bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, + headContainer = new Container { RelativeSizeAxes = Axes.Both }, + tailContainer = new Container { RelativeSizeAxes = Axes.Both }, }); - foreach (var tick in tickContainer) - AddNested(tick); - - AddNested(Head); - AddNested(Tail); - AccentColour.BindValueChanged(colour => { bodyPiece.AccentColour = colour.NewValue; - Head.AccentColour.Value = colour.NewValue; - Tail.AccentColour.Value = colour.NewValue; - tickContainer.ForEach(t => t.AccentColour.Value = colour.NewValue); }, true); } + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableHeadNote head: + headContainer.Child = head; + break; + + case DrawableTailNote tail: + tailContainer.Child = tail; + break; + + case DrawableHoldNoteTick tick: + tickContainer.Add(tick); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + headContainer.Clear(); + tailContainer.Clear(); + tickContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case TailNote _: + return Tail = new DrawableTailNote(this) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = { BindTarget = AccentColour } + }; + + case Note _: + return Head = new DrawableHeadNote(this) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = { BindTarget = AccentColour } + }; + + case HoldNoteTick tick: + return new DrawableHoldNoteTick(tick) + { + HoldStartTime = () => holdStartTime, + AccentColour = { BindTarget = AccentColour } + }; + } + + return base.CreateNested(hitObject); + } + protected override void OnDirectionChanged(ValueChangedEvent e) { base.OnDirectionChanged(e); From 3a1acf7b0aab924aa9b48ef341ea2518d9ec3b92 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:50:22 +0900 Subject: [PATCH 06/13] Fix slider approach circle proxies --- .../Objects/Drawables/DrawableSlider.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 21411259ae..6ab14cb036 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -258,7 +258,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public Drawable ProxiedLayer => new Container(); // Todo: + public Drawable ProxiedLayer => HeadCircle.ProxiedLayer; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Body.ReceivePositionalInputAt(screenSpacePos); } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index d1757de445..69e53d6eea 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -57,21 +57,15 @@ namespace osu.Game.Rulesets.Osu.UI public override void Add(DrawableHitObject h) { h.OnNewResult += onNewResult; - - if (h is IDrawableHitObjectWithProxiedApproach c) + h.OnLoadComplete += d => { - var original = c.ProxiedLayer; - - // Hitobjects only have lifetimes set on LoadComplete. For nested hitobjects (e.g. SliderHeads), this only happens when the parenting slider becomes visible. - // This delegation is required to make sure that the approach circles for those not-yet-loaded objects aren't added prematurely. - original.OnLoadComplete += addApproachCircleProxy; - } + if (d is IDrawableHitObjectWithProxiedApproach c) + approachCircles.Add(c.ProxiedLayer.CreateProxy()); + }; base.Add(h); } - private void addApproachCircleProxy(Drawable d) => approachCircles.Add(d.CreateProxy()); - public override void PostProcess() { connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); From d8f3678c3cadbdc02adf3db8d79796b39c646b4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:53:54 +0900 Subject: [PATCH 07/13] Rename parameter --- .../Objects/Drawable/DrawableBananaShower.cs | 6 +++--- .../Objects/Drawable/DrawableJuiceStream.cs | 6 +++--- .../Objects/Drawables/DrawableHoldNote.cs | 6 +++--- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 6 +++--- .../Objects/Drawables/DrawableDrumRoll.cs | 6 +++--- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 6 +++--- .../Objects/Drawables/DrawableTaikoHitObject.cs | 6 +++--- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 57ffd23e85..f46abea68f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); - bananaContainer.Add(h); + base.AddNested(hitObject); + bananaContainer.Add(hitObject); } protected override void ClearNested() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 1bbb7b08a5..7af3f49267 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); - dropletContainer.Add(h); + base.AddNested(hitObject); + dropletContainer.Add(hitObject); } protected override void ClearNested() diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 78969b7361..2d4f90876e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -59,11 +59,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableHeadNote head: headContainer.Child = head; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 6ab14cb036..b937fd346f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -93,11 +93,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableSliderHead head: headContainer.Child = HeadCircle = head; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index d98043b1b7..b212c81020 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -55,11 +55,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables OnNewResult += onNewResult; } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableDrumRollTick tick: tickContainer.Add(tick); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 164944f00a..162c8f4810 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -128,11 +128,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableSwellTick tick: ticks.Add(tick); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index b89cd7c09f..ddc29f1de6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -134,11 +134,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddInternal(strongHitContainer = new Container()); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableStrongNestedHit strong: strongHitContainer.Add(strong); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 6bc2ccb889..424776f61b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - protected virtual void AddNested(DrawableHitObject h) + protected virtual void AddNested(DrawableHitObject hitObject) { } From f429a8f7c272b4849898cec0716257ec50c70d2c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 13:52:21 +0900 Subject: [PATCH 08/13] Add back/obsolete old AddNested() method --- .../Objects/Drawable/DrawableBananaShower.cs | 12 ++--- .../Objects/Drawable/DrawableJuiceStream.cs | 12 ++--- .../Objects/Drawables/DrawableHoldNote.cs | 12 ++--- .../Objects/Drawables/DrawableSlider.cs | 12 ++--- .../Objects/Drawables/DrawableDrumRoll.cs | 12 ++--- .../Objects/Drawables/DrawableSwell.cs | 12 ++--- .../Drawables/DrawableTaikoHitObject.cs | 12 ++--- .../Objects/Drawables/DrawableHitObject.cs | 44 ++++++++++++++++--- 8 files changed, 80 insertions(+), 48 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index f46abea68f..ea415e18fa 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -25,19 +25,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); bananaContainer.Add(hitObject); } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); bananaContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable return createDrawableRepresentation?.Invoke(banana)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 7af3f49267..a24821b3ce 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -25,19 +25,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); dropletContainer.Add(hitObject); } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); dropletContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable return createDrawableRepresentation?.Invoke(catchObject)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 2d4f90876e..78d49c217e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -59,9 +59,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -79,15 +79,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); headContainer.Clear(); tailContainer.Clear(); tickContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override void OnDirectionChanged(ValueChangedEvent e) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index b937fd346f..f057c67efe 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -93,9 +93,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -117,9 +117,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); headContainer.Clear(); tailContainer.Clear(); @@ -127,7 +127,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables tickContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return new DrawableRepeatPoint(repeat, this) { Position = repeat.Position - slider.Position }; } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index b212c81020..cc0d6829ba 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -55,9 +55,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables OnNewResult += onNewResult; } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -67,13 +67,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); tickContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return new DrawableDrumRollTick(tick); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 162c8f4810..9c9dfc5f9e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -128,9 +128,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -140,13 +140,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); ticks.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return new DrawableSwellTick(tick); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index ddc29f1de6..0db6498c12 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -134,9 +134,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddInternal(strongHitContainer = new Container()); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -146,13 +146,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); strongHitContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return CreateStrongHit(strong); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } // Normal and clap samples are handled by the drum diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 424776f61b..99b0c07570 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; @@ -138,34 +139,65 @@ namespace osu.Game.Rulesets.Objects.Drawables protected void Apply(HitObject hitObject) { +#pragma warning disable 618 // can be removed 20200417 + if (GetType().GetMethod(nameof(AddNested), BindingFlags.NonPublic | BindingFlags.Instance)?.DeclaringType != typeof(DrawableHitObject)) + return; +#pragma warning restore 618 + if (nestedHitObjects.IsValueCreated) { nestedHitObjects.Value.Clear(); - ClearNested(); + ClearNestedHitObjects(); } foreach (var h in hitObject.NestedHitObjects) { - var drawableNested = CreateNested(h) ?? throw new InvalidOperationException($"{nameof(CreateNested)} returned null for {h.GetType().ReadableName()}."); + var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); nestedHitObjects.Value.Add(drawableNested); - AddNested(drawableNested); + AddNestedHitObject(drawableNested); } } - protected virtual void AddNested(DrawableHitObject hitObject) + /// + /// Invoked by the base to add nested s to the hierarchy. + /// + /// The to be added. + protected virtual void AddNestedHitObject(DrawableHitObject hitObject) { } - protected virtual void ClearNested() + /// + /// Adds a nested . This should not be used except for legacy nested usages. + /// + /// + [Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417 + protected virtual void AddNested(DrawableHitObject h) + { + h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); + h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Value.Add(h); + } + + /// + /// Invoked by the base to remove all previously-added nested s. + /// + protected virtual void ClearNestedHitObjects() { } - protected virtual DrawableHitObject CreateNested(HitObject hitObject) => null; + /// + /// Creates the drawable representation for a nested . + /// + /// The . + /// The drawable representation for . + protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null; #region State / Transform Management From bc41eb176ee6ad63a153d7ba82e1a8a17d13c0c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 14:02:23 +0900 Subject: [PATCH 09/13] Clean up head/tail setting in various DHOs --- .../Objects/Drawables/DrawableHoldNote.cs | 10 +++++----- .../Objects/Drawables/DrawableSlider.cs | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 78d49c217e..87b9633c80 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -21,13 +21,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { public override bool DisplayResult => false; + public DrawableNote Head => headContainer.Child; + public DrawableNote Tail => tailContainer.Child; + private readonly Container headContainer; private readonly Container tailContainer; private readonly Container tickContainer; - public DrawableNote Head { get; private set; } - public DrawableNote Tail { get; private set; } - private readonly BodyPiece bodyPiece; /// @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables switch (hitObject) { case TailNote _: - return Tail = new DrawableTailNote(this) + return new DrawableTailNote(this) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; case Note _: - return Head = new DrawableHeadNote(this) + return new DrawableHeadNote(this) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index f057c67efe..6d45bb9ac4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - public DrawableSliderHead HeadCircle { get; private set; } - public DrawableSliderTail TailCircle { get; private set; } + public DrawableSliderHead HeadCircle => headContainer.Child; + public DrawableSliderTail TailCircle => tailContainer.Child; public readonly SnakingSliderBody Body; public readonly SliderBall Ball; @@ -100,11 +100,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (hitObject) { case DrawableSliderHead head: - headContainer.Child = HeadCircle = head; + headContainer.Child = head; break; case DrawableSliderTail tail: - tailContainer.Child = TailCircle = tail; + tailContainer.Child = tail; break; case DrawableSliderTick tick: From 510ce9345f79b3deee4f6ed1fc72e46ebed0ed0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 16:14:28 +0900 Subject: [PATCH 10/13] Fix potential blueprint nullrefs with the new structure --- .../Blueprints/HoldNoteSelectionBlueprint.cs | 32 +++++++++++-------- .../Compose/Components/BlueprintContainer.cs | 18 ++++++++--- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index d64c5dbc6a..3169a8c036 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -20,30 +20,36 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints private readonly IBindable direction = new Bindable(); - private readonly BodyPiece body; + [Resolved] + private OsuColour colours { get; set; } public HoldNoteSelectionBlueprint(DrawableHoldNote hold) : base(hold) { - InternalChildren = new Drawable[] - { - new HoldNoteNoteSelectionBlueprint(hold.Head), - new HoldNoteNoteSelectionBlueprint(hold.Tail), - body = new BodyPiece - { - AccentColour = Color4.Transparent - }, - }; } [BackgroundDependencyLoader] - private void load(OsuColour colours, IScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - body.BorderColour = colours.Yellow; - direction.BindTo(scrollingInfo.Direction); } + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new Drawable[] + { + new HoldNoteNoteSelectionBlueprint(HitObject.Head), + new HoldNoteNoteSelectionBlueprint(HitObject.Tail), + new BodyPiece + { + AccentColour = Color4.Transparent, + BorderColour = colours.Yellow + }, + }; + } + protected override void Update() { base.Update(); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 2de5ecf633..cb3d3b71fc 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -123,12 +123,20 @@ namespace osu.Game.Screens.Edit.Compose.Components if (blueprint == null) return; - blueprint.Selected += onBlueprintSelected; - blueprint.Deselected += onBlueprintDeselected; - blueprint.SelectionRequested += onSelectionRequested; - blueprint.DragRequested += onDragRequested; + if (hitObject.IsLoaded) + addBlueprint(); + else + hitObject.OnLoadComplete += _ => addBlueprint(); - selectionBlueprints.Add(blueprint); + void addBlueprint() + { + blueprint.Selected += onBlueprintSelected; + blueprint.Deselected += onBlueprintDeselected; + blueprint.SelectionRequested += onSelectionRequested; + blueprint.DragRequested += onDragRequested; + + selectionBlueprints.Add(blueprint); + } } private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject); From 5d3d25d3b69060342deb8ba58dfe192735c809a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 13:24:25 +0900 Subject: [PATCH 11/13] Make method private for now --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 99b0c07570..18d45f3724 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); - Apply(HitObject); + apply(HitObject); if (HitObject is IHasComboInformation combo) { @@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Objects.Drawables updateState(ArmedState.Idle, true); } - protected void Apply(HitObject hitObject) + private void apply(HitObject hitObject) { #pragma warning disable 618 // can be removed 20200417 if (GetType().GetMethod(nameof(AddNested), BindingFlags.NonPublic | BindingFlags.Instance)?.DeclaringType != typeof(DrawableHitObject)) From dc222b5e4d00b3eac3d6e46405731e2b1050642b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 13:52:02 +0900 Subject: [PATCH 12/13] Add common path for duplicated code --- .../Objects/Drawables/DrawableHitObject.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 156d4178e2..b472c880c0 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -154,11 +154,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); - drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); - drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); - - nestedHitObjects.Value.Add(drawableNested); + addNested(drawableNested); AddNestedHitObject(drawableNested); } } @@ -176,14 +172,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// [Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417 - protected virtual void AddNested(DrawableHitObject h) - { - h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); - h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); - - nestedHitObjects.Value.Add(h); - } + protected virtual void AddNested(DrawableHitObject h) => addNested(h); /// /// Invoked by the base to remove all previously-added nested s. @@ -199,6 +188,17 @@ namespace osu.Game.Rulesets.Objects.Drawables /// The drawable representation for . protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null; + private void addNested(DrawableHitObject hitObject) + { + // Todo: Exists for legacy purposes, can be removed 20200417 + + hitObject.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + hitObject.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); + hitObject.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Value.Add(hitObject); + } + #region State / Transform Management /// From 74b6e691d82631c6f2ad8edc73db42d2490c748f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 14:01:52 +0900 Subject: [PATCH 13/13] Remove unnecessary schedule --- .../Compose/Components/BlueprintContainer.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index cb3d3b71fc..2de5ecf633 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -123,20 +123,12 @@ namespace osu.Game.Screens.Edit.Compose.Components if (blueprint == null) return; - if (hitObject.IsLoaded) - addBlueprint(); - else - hitObject.OnLoadComplete += _ => addBlueprint(); + blueprint.Selected += onBlueprintSelected; + blueprint.Deselected += onBlueprintDeselected; + blueprint.SelectionRequested += onSelectionRequested; + blueprint.DragRequested += onDragRequested; - void addBlueprint() - { - blueprint.Selected += onBlueprintSelected; - blueprint.Deselected += onBlueprintDeselected; - blueprint.SelectionRequested += onSelectionRequested; - blueprint.DragRequested += onDragRequested; - - selectionBlueprints.Add(blueprint); - } + selectionBlueprints.Add(blueprint); } private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject);