From a25cd910f83fe6ed012fdf63e1f2a20245ac625d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 22:20:35 +0100 Subject: [PATCH 01/11] Prepare base DHO for HO application --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index cf3aa69b6f..6041eccb51 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; +using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private readonly Container nonProxiedContent; - protected DrawableTaikoHitObject(TaikoHitObject hitObject) + protected DrawableTaikoHitObject([CanBeNull] TaikoHitObject hitObject) : base(hitObject) { AddRangeInternal(new[] @@ -113,25 +113,23 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); - public new TObject HitObject; + public new TObject HitObject => (TObject)base.HitObject; protected Vector2 BaseSize; protected SkinnableDrawable MainPiece; - protected DrawableTaikoHitObject(TObject hitObject) + protected DrawableTaikoHitObject([CanBeNull] TObject hitObject) : base(hitObject) { - HitObject = hitObject; - Anchor = Anchor.CentreLeft; Origin = Anchor.Custom; RelativeSizeAxes = Axes.Both; } - [BackgroundDependencyLoader] - private void load() + protected override void OnApply() { + base.OnApply(); RecreatePieces(); } From 7b350fc8e5f61644d63700c236fe2c447eb39efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 22:27:45 +0100 Subject: [PATCH 02/11] Prepare strongable DHO for HO application --- .../DrawableTaikoStrongableHitObject.cs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs index af3e94d9c6..62f338ca91 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Allocation; +using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Audio; @@ -16,28 +16,38 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables where TObject : TaikoStrongableHitObject where TStrongNestedObject : StrongNestedHitObject { - private readonly Bindable isStrong; + private readonly Bindable isStrong = new BindableBool(); private readonly Container strongHitContainer; - protected DrawableTaikoStrongableHitObject(TObject hitObject) + protected DrawableTaikoStrongableHitObject([CanBeNull] TObject hitObject) : base(hitObject) { - isStrong = HitObject.IsStrongBindable.GetBoundCopy(); - AddInternal(strongHitContainer = new Container()); } - [BackgroundDependencyLoader] - private void load() + protected override void OnApply() { + isStrong.BindTo(HitObject.IsStrongBindable); isStrong.BindValueChanged(_ => { - // will overwrite samples, should only be called on change. + // will overwrite samples, should only be called on subsequent changes + // after the initial application. updateSamplesFromStrong(); RecreatePieces(); }); + + base.OnApply(); + } + + protected override void OnFree() + { + base.OnFree(); + + isStrong.UnbindFrom(HitObject.IsStrongBindable); + // ensure the next application does not accidentally overwrite samples. + isStrong.UnbindEvents(); } private HitSampleInfo[] getStrongSamples() => HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_FINISH).ToArray(); From a31e8d137f3c0bf2926e603a9ef294eb0f8f47c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 22:53:00 +0100 Subject: [PATCH 03/11] Add guard when clearing samples --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 644c67ea59..da6da0ea97 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -303,7 +303,8 @@ namespace osu.Game.Rulesets.Objects.Drawables samplesBindable.CollectionChanged -= onSamplesChanged; // Release the samples for other hitobjects to use. - Samples.Samples = null; + if (Samples != null) + Samples.Samples = null; if (nestedHitObjects.IsValueCreated) { From 232c0205b4d7927c3b84dac00a719ec2fa4be7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 22:51:35 +0100 Subject: [PATCH 04/11] Refactor hit object application scene to work reliably --- .../HitObjectApplicationTestScene.cs | 14 ++++++++++---- .../TestSceneBarLineApplication.cs | 7 ++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs index 07c7b4d1db..a1d000386f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs @@ -25,16 +25,22 @@ namespace osu.Game.Rulesets.Taiko.Tests private ScrollingHitObjectContainer hitObjectContainer; - [SetUpSteps] - public void SetUp() - => AddStep("create SHOC", () => Child = hitObjectContainer = new ScrollingHitObjectContainer + [BackgroundDependencyLoader] + private void load() + { + Child = hitObjectContainer = new ScrollingHitObjectContainer { RelativeSizeAxes = Axes.X, Height = 200, Anchor = Anchor.Centre, Origin = Anchor.Centre, Clock = new FramedClock(new StopwatchClock()) - }); + }; + } + + [SetUpSteps] + public void SetUp() + => AddStep("clear SHOC", () => hitObjectContainer.Clear(false)); protected void AddHitObject(DrawableHitObject hitObject) => AddStep("add to SHOC", () => hitObjectContainer.Add(hitObject)); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs index 65230a07bc..a970965141 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs @@ -12,12 +12,13 @@ namespace osu.Game.Rulesets.Taiko.Tests [Test] public void TestApplyNewBarLine() { - DrawableBarLine barLine = new DrawableBarLine(PrepareObject(new BarLine + DrawableBarLine barLine = new DrawableBarLine(); + + AddStep("apply new bar line", () => barLine.Apply(PrepareObject(new BarLine { StartTime = 400, Major = true - })); - + }), null)); AddHitObject(barLine); RemoveHitObject(barLine); From e32b1c34cac0436c39a5087896f386af30239d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 22:53:46 +0100 Subject: [PATCH 05/11] Implement hit application --- .../TestSceneHitApplication.cs | 37 ++++++++++++++++ .../Objects/Drawables/DrawableHit.cs | 44 ++++++++++++++----- 2 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs new file mode 100644 index 0000000000..52fd440857 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects.Drawables; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneHitApplication : HitObjectApplicationTestScene + { + [Test] + public void TestApplyNewHit() + { + var hit = new DrawableHit(); + + AddStep("apply new hit", () => hit.Apply(PrepareObject(new Hit + { + Type = HitType.Rim, + IsStrong = false, + StartTime = 300 + }), null)); + + AddHitObject(hit); + RemoveHitObject(hit); + + AddStep("apply new hit", () => hit.Apply(PrepareObject(new Hit + { + Type = HitType.Centre, + IsStrong = true, + StartTime = 500 + }), null)); + + AddHitObject(hit); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 431f2980ec..5a479e1f53 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Allocation; +using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Audio; @@ -36,29 +36,51 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private bool pressHandledThisFrame; - private readonly Bindable type; + private readonly Bindable type = new Bindable(); - public DrawableHit(Hit hit) - : base(hit) + public DrawableHit() + : this(null) { - type = HitObject.TypeBindable.GetBoundCopy(); - FillMode = FillMode.Fit; - - updateActionsFromType(); } - [BackgroundDependencyLoader] - private void load() + public DrawableHit([CanBeNull] Hit hit) + : base(hit) { + FillMode = FillMode.Fit; + } + + protected override void OnApply() + { + type.BindTo(HitObject.TypeBindable); type.BindValueChanged(_ => { updateActionsFromType(); - // will overwrite samples, should only be called on change. + // will overwrite samples, should only be called on subsequent changes + // after the initial application. updateSamplesFromTypeChange(); RecreatePieces(); }); + + // action update also has to happen immediately on application. + updateActionsFromType(); + + base.OnApply(); + } + + protected override void OnFree() + { + base.OnFree(); + + type.UnbindFrom(HitObject.TypeBindable); + type.UnbindEvents(); + + UnproxyContent(); + + HitActions = null; + HitAction = null; + validActionPressed = pressHandledThisFrame = false; } private HitSampleInfo[] getRimSamples() => HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE).ToArray(); From 8b6bc09b8f0c0dd48879fe05adb5f614aeb4dc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 23:02:33 +0100 Subject: [PATCH 06/11] Implement drum roll application --- .../TestSceneDrumRollApplication.cs | 39 +++++++++++++++++++ .../Objects/Drawables/DrawableDrumRoll.cs | 34 ++++++++++------ 2 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs new file mode 100644 index 0000000000..54450e27db --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs @@ -0,0 +1,39 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects.Drawables; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneDrumRollApplication : HitObjectApplicationTestScene + { + [Test] + public void TestApplyNewDrumRoll() + { + var drumRoll = new DrawableDrumRoll(); + + AddStep("apply new drum roll", () => drumRoll.Apply(PrepareObject(new DrumRoll + { + StartTime = 300, + Duration = 500, + IsStrong = false, + TickRate = 2 + }), null)); + + AddHitObject(drumRoll); + RemoveHitObject(drumRoll); + + AddStep("apply new drum roll", () => drumRoll.Apply(PrepareObject(new DrumRoll + { + StartTime = 150, + Duration = 400, + IsStrong = true, + TickRate = 16 + }), null)); + + AddHitObject(drumRoll); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 4925b6fdfc..ede7453804 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Utils; using osu.Game.Graphics; @@ -31,15 +32,26 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private int rollingHits; - private Container tickContainer; + private readonly Container tickContainer; private Color4 colourIdle; private Color4 colourEngaged; - public DrawableDrumRoll(DrumRoll drumRoll) + public DrawableDrumRoll() + : this(null) + { + } + + public DrawableDrumRoll([CanBeNull] DrumRoll drumRoll) : base(drumRoll) { RelativeSizeAxes = Axes.Y; + + Content.Add(tickContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Depth = float.MinValue + }); } [BackgroundDependencyLoader] @@ -47,12 +59,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { colourIdle = colours.YellowDark; colourEngaged = colours.YellowDarker; - - Content.Add(tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Depth = float.MinValue - }); } protected override void LoadComplete() @@ -68,6 +74,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables updateColour(); } + protected override void OnFree() + { + base.OnFree(); + rollingHits = 0; + } + protected override void AddNestedHitObject(DrawableHitObject hitObject) { base.AddNestedHitObject(hitObject); @@ -114,7 +126,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); - updateColour(); + updateColour(100); } protected override void CheckForResult(bool userTriggered, double timeOffset) @@ -156,10 +168,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRoll.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); - private void updateColour() + private void updateColour(double fadeDuration = 0) { Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); - (MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, 100); + (MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration); } private class StrongNestedHit : DrawableStrongNestedHit From e3b6eaa39059ba8afc2e71a0d034bc3b227fe49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 23:06:22 +0100 Subject: [PATCH 07/11] Implement swell application Also removes a weird sizing application that seems to have no effect (introduced in 27e63eb; compare removals for other taiko DHO types in 9d00e5b and 58bf288). --- .../Objects/Drawables/DrawableSwell.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 229d581d0c..9798a79450 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -35,7 +36,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; - public DrawableSwell(Swell swell) + public DrawableSwell() + : this(null) + { + } + + public DrawableSwell([CanBeNull] Swell swell) : base(swell) { FillMode = FillMode.Fit; @@ -123,12 +129,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Origin = Anchor.Centre, }); - protected override void LoadComplete() + protected override void OnFree() { - base.LoadComplete(); + base.OnFree(); - // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize - Width *= Parent.RelativeChildSize.X; + UnproxyContent(); + + lastWasCentre = null; } protected override void AddNestedHitObject(DrawableHitObject hitObject) From 3bd42795899eda793b9b0d346abdae7902585ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 23:10:19 +0100 Subject: [PATCH 08/11] Implement drum roll tick application --- .../Objects/Drawables/DrawableDrumRollTick.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index c6761de5e3..e7d8ef1e12 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Skinning.Default; @@ -16,7 +17,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public HitType JudgementType; - public DrawableDrumRollTick(DrumRollTick tick) + public DrawableDrumRollTick() + : this(null) + { + } + + public DrawableDrumRollTick([CanBeNull] DrumRollTick tick) : base(tick) { FillMode = FillMode.Fit; From d823c77a63e315207bbe7f282ef07ef3eeb8bf1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 23:11:51 +0100 Subject: [PATCH 09/11] Implement swell tick application --- .../Objects/Drawables/DrawableSwellTick.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 14c86d151f..47fc7e5ab3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; @@ -11,7 +12,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override bool DisplayResult => false; - public DrawableSwellTick(SwellTick hitObject) + public DrawableSwellTick() + : this(null) + { + } + + public DrawableSwellTick([CanBeNull] SwellTick hitObject) : base(hitObject) { } From ae6dedacaf1edb784c9ca7bdfb4a871f6e0821f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Dec 2020 23:21:19 +0100 Subject: [PATCH 10/11] Implement nested strong hit application --- .../Objects/Drawables/DrawableDrumRoll.cs | 17 ++++++++---- .../Objects/Drawables/DrawableDrumRollTick.cs | 17 ++++++++---- .../Objects/Drawables/DrawableHit.cs | 27 +++++++++++-------- .../Drawables/DrawableStrongNestedHit.cs | 7 +++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index ede7453804..01336ea2e4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Content.X = DrawHeight / 2; } - protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRoll.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); + protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRoll.StrongNestedHit hitObject) => new StrongNestedHit(hitObject); private void updateColour(double fadeDuration = 0) { @@ -176,17 +176,24 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private class StrongNestedHit : DrawableStrongNestedHit { - public StrongNestedHit(DrumRoll.StrongNestedHit nestedHit, DrawableDrumRoll drumRoll) - : base(nestedHit, drumRoll) + public new DrawableDrumRoll ParentHitObject => (DrawableDrumRoll)base.ParentHitObject; + + public StrongNestedHit() + : this(null) + { + } + + public StrongNestedHit([CanBeNull] DrumRoll.StrongNestedHit nestedHit) + : base(nestedHit) { } protected override void CheckForResult(bool userTriggered, double timeOffset) { - if (!MainObject.Judged) + if (!ParentHitObject.Judged) return; - ApplyResult(r => r.Type = MainObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); } public override bool OnPressed(TaikoAction action) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index e7d8ef1e12..1e625d91d6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -67,21 +67,28 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return UpdateResult(true); } - protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRollTick.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); + protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRollTick.StrongNestedHit hitObject) => new StrongNestedHit(hitObject); private class StrongNestedHit : DrawableStrongNestedHit { - public StrongNestedHit(DrumRollTick.StrongNestedHit nestedHit, DrawableDrumRollTick tick) - : base(nestedHit, tick) + public new DrawableDrumRollTick ParentHitObject => (DrawableDrumRollTick)base.ParentHitObject; + + public StrongNestedHit() + : this(null) + { + } + + public StrongNestedHit([CanBeNull] DrumRollTick.StrongNestedHit nestedHit) + : base(nestedHit) { } protected override void CheckForResult(bool userTriggered, double timeOffset) { - if (!MainObject.Judged) + if (!ParentHitObject.Judged) return; - ApplyResult(r => r.Type = MainObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); } public override bool OnPressed(TaikoAction action) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 5a479e1f53..73ebd7c117 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -250,32 +250,37 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override DrawableStrongNestedHit CreateStrongNestedHit(Hit.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); + protected override DrawableStrongNestedHit CreateStrongNestedHit(Hit.StrongNestedHit hitObject) => new StrongNestedHit(hitObject); private class StrongNestedHit : DrawableStrongNestedHit { + public new DrawableHit ParentHitObject => (DrawableHit)base.ParentHitObject; + /// /// The lenience for the second key press. /// This does not adjust by map difficulty in ScoreV2 yet. /// private const double second_hit_window = 30; - public new DrawableHit MainObject => (DrawableHit)base.MainObject; + public StrongNestedHit() + : this(null) + { + } - public StrongNestedHit(Hit.StrongNestedHit nestedHit, DrawableHit hit) - : base(nestedHit, hit) + public StrongNestedHit([CanBeNull] Hit.StrongNestedHit nestedHit) + : base(nestedHit) { } protected override void CheckForResult(bool userTriggered, double timeOffset) { - if (!MainObject.Result.HasResult) + if (!ParentHitObject.Result.HasResult) { base.CheckForResult(userTriggered, timeOffset); return; } - if (!MainObject.Result.IsHit) + if (!ParentHitObject.Result.IsHit) { ApplyResult(r => r.Type = r.Judgement.MinResult); return; @@ -283,27 +288,27 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { - if (timeOffset - MainObject.Result.TimeOffset > second_hit_window) + if (timeOffset - ParentHitObject.Result.TimeOffset > second_hit_window) ApplyResult(r => r.Type = r.Judgement.MinResult); return; } - if (Math.Abs(timeOffset - MainObject.Result.TimeOffset) <= second_hit_window) + if (Math.Abs(timeOffset - ParentHitObject.Result.TimeOffset) <= second_hit_window) ApplyResult(r => r.Type = r.Judgement.MaxResult); } public override bool OnPressed(TaikoAction action) { // Don't process actions until the main hitobject is hit - if (!MainObject.IsHit) + if (!ParentHitObject.IsHit) return false; // Don't process actions if the pressed button was released - if (MainObject.HitAction == null) + if (ParentHitObject.HitAction == null) return false; // Don't handle invalid hit action presses - if (!MainObject.HitActions.Contains(action)) + if (!ParentHitObject.HitActions.Contains(action)) return false; return UpdateResult(true); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index d2e8888197..9c22e34387 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Objects.Drawables; +using JetBrains.Annotations; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -11,12 +11,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public abstract class DrawableStrongNestedHit : DrawableTaikoHitObject { - public readonly DrawableHitObject MainObject; + public new DrawableTaikoHitObject ParentHitObject => (DrawableTaikoHitObject)base.ParentHitObject; - protected DrawableStrongNestedHit(StrongNestedHitObject nestedHit, DrawableHitObject mainObject) + protected DrawableStrongNestedHit([CanBeNull] StrongNestedHitObject nestedHit) : base(nestedHit) { - MainObject = mainObject; } } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index d20b190c86..8682495b41 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -248,7 +248,7 @@ namespace osu.Game.Rulesets.Taiko.UI { case TaikoStrongJudgement _: if (result.IsHit) - hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).MainObject)?.VisualiseSecondHit(); + hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).ParentHitObject)?.VisualiseSecondHit(); break; case TaikoDrumRollTickJudgement _: From eb46c9ce9be47341a18e08fedeeb65408ac5847c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Dec 2020 17:11:30 +0900 Subject: [PATCH 11/11] Fix metadata lost in beatmapset deserialisation --- .../Online/API/Requests/Responses/APIBeatmapSet.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 6d0160fbc4..720d6bfff4 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -80,7 +80,7 @@ namespace osu.Game.Online.API.Requests.Responses public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) { - return new BeatmapSetInfo + var beatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = OnlineBeatmapSetID, Metadata = this, @@ -104,8 +104,17 @@ namespace osu.Game.Online.API.Requests.Responses Genre = genre, Language = language }, - Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(), }; + + beatmapSet.Beatmaps = beatmaps?.Select(b => + { + var beatmap = b.ToBeatmap(rulesets); + beatmap.BeatmapSet = beatmapSet; + beatmap.Metadata = beatmapSet.Metadata; + return beatmap; + }).ToList(); + + return beatmapSet; } } }