From f24569694716cbbbd92f2470680c4469f5b326bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Nov 2020 13:24:32 +0100 Subject: [PATCH 01/15] Move {-> Default}KiaiHitExplosion --- .../UI/{KiaiHitExplosion.cs => DefaultKiaiHitExplosion.cs} | 4 ++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game.Rulesets.Taiko/UI/{KiaiHitExplosion.cs => DefaultKiaiHitExplosion.cs} (92%) diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs similarity index 92% rename from osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs rename to osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs index 067d390894..32c9f3ec4f 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs @@ -13,14 +13,14 @@ using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.UI { - public class KiaiHitExplosion : CircularContainer + public class DefaultKiaiHitExplosion : CircularContainer { public override bool RemoveWhenNotAlive => true; public readonly DrawableHitObject JudgedObject; private readonly HitType type; - public KiaiHitExplosion(DrawableHitObject judgedObject, HitType type) + public DefaultKiaiHitExplosion(DrawableHitObject judgedObject, HitType type) { JudgedObject = judgedObject; this.type = type; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 120cf264c3..03895dfd68 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko.UI public const float DEFAULT_HEIGHT = 178; private Container hitExplosionContainer; - private Container kiaiExplosionContainer; + private Container kiaiExplosionContainer; private JudgementContainer judgementContainer; private ScrollingHitObjectContainer drumRollHitContainer; internal Drawable HitTarget; @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Taiko.UI drumRollHitContainer = new DrumRollHitContainer() } }, - kiaiExplosionContainer = new Container + kiaiExplosionContainer = new Container { Name = "Kiai hit explosions", RelativeSizeAxes = Axes.Both, @@ -219,7 +219,7 @@ namespace osu.Game.Rulesets.Taiko.UI { hitExplosionContainer.Add(new HitExplosion(drawableObject, result)); if (drawableObject.HitObject.Kiai) - kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type)); + kiaiExplosionContainer.Add(new DefaultKiaiHitExplosion(drawableObject, type)); } private class ProxyContainer : LifetimeManagementContainer From ed01d37966a9249bb4f81d81f03a2c01746ec374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Nov 2020 13:35:49 +0100 Subject: [PATCH 02/15] Reintroduce KiaiHitExplosion as skinnable --- .../TaikoSkinComponents.cs | 1 + .../UI/DefaultKiaiHitExplosion.cs | 9 +--- .../UI/KiaiHitExplosion.cs | 47 +++++++++++++++++++ osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 6 +-- 4 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs index 132d8f8868..bf48898dd2 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Taiko TaikoExplosionMiss, TaikoExplosionOk, TaikoExplosionGreat, + TaikoExplosionKiai, Scroller, Mascot, } diff --git a/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs index 32c9f3ec4f..7ce8b016d5 100644 --- a/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.UI @@ -17,19 +16,13 @@ namespace osu.Game.Rulesets.Taiko.UI { public override bool RemoveWhenNotAlive => true; - public readonly DrawableHitObject JudgedObject; private readonly HitType type; - public DefaultKiaiHitExplosion(DrawableHitObject judgedObject, HitType type) + public DefaultKiaiHitExplosion(HitType type) { - JudgedObject = judgedObject; this.type = type; - Anchor = Anchor.CentreLeft; - Origin = Anchor.Centre; - RelativeSizeAxes = Axes.Both; - Size = new Vector2(TaikoHitObject.DEFAULT_SIZE, 1); Blending = BlendingParameters.Additive; diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs new file mode 100644 index 0000000000..20900a9352 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -0,0 +1,47 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Rulesets.Taiko.UI +{ + public class KiaiHitExplosion : Container + { + public override bool RemoveWhenNotAlive => true; + + [Cached(typeof(DrawableHitObject))] + public readonly DrawableHitObject JudgedObject; + + private readonly HitType hitType; + + private SkinnableDrawable skinnable; + + public override double LifetimeStart => skinnable.Drawable.LifetimeStart; + + public override double LifetimeEnd => skinnable.Drawable.LifetimeEnd; + + public KiaiHitExplosion(DrawableHitObject judgedObject, HitType hitType) + { + JudgedObject = judgedObject; + this.hitType = hitType; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + + RelativeSizeAxes = Axes.Both; + Size = new Vector2(TaikoHitObject.DEFAULT_SIZE, 1); + } + + [BackgroundDependencyLoader] + private void load() + { + Child = skinnable = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoExplosionKiai), _ => new DefaultKiaiHitExplosion(hitType)); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 03895dfd68..120cf264c3 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko.UI public const float DEFAULT_HEIGHT = 178; private Container hitExplosionContainer; - private Container kiaiExplosionContainer; + private Container kiaiExplosionContainer; private JudgementContainer judgementContainer; private ScrollingHitObjectContainer drumRollHitContainer; internal Drawable HitTarget; @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Taiko.UI drumRollHitContainer = new DrumRollHitContainer() } }, - kiaiExplosionContainer = new Container + kiaiExplosionContainer = new Container { Name = "Kiai hit explosions", RelativeSizeAxes = Axes.Both, @@ -219,7 +219,7 @@ namespace osu.Game.Rulesets.Taiko.UI { hitExplosionContainer.Add(new HitExplosion(drawableObject, result)); if (drawableObject.HitObject.Kiai) - kiaiExplosionContainer.Add(new DefaultKiaiHitExplosion(drawableObject, type)); + kiaiExplosionContainer.Add(new KiaiHitExplosion(drawableObject, type)); } private class ProxyContainer : LifetimeManagementContainer From 35763a74fd75c18897d7236b4f58f2218c80135e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Nov 2020 14:07:39 +0100 Subject: [PATCH 03/15] Add test scene --- .../Skinning/TestSceneKiaiHitExplosion.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs new file mode 100644 index 0000000000..b558709592 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.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.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.UI; + +namespace osu.Game.Rulesets.Taiko.Tests.Skinning +{ + [TestFixture] + public class TestSceneKiaiHitExplosion : TaikoSkinnableTestScene + { + [Test] + public void TestKiaiHits() + { + AddStep("rim hit", () => SetContents(() => getContentFor(createHit(HitType.Rim)))); + AddStep("centre hit", () => SetContents(() => getContentFor(createHit(HitType.Centre)))); + } + + private Drawable getContentFor(DrawableTestHit hit) + { + return new Container + { + RelativeSizeAxes = Axes.Both, + Child = new KiaiHitExplosion(hit, hit.HitObject.Type) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + + private DrawableTestHit createHit(HitType type) => new DrawableTestHit(new Hit { StartTime = Time.Current, Type = type }); + } +} From 0387d994bdc6136259d32c3b2181842a6e91f8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Nov 2020 14:08:27 +0100 Subject: [PATCH 04/15] Do not lookup default kiai explosion if skin has own --- .../Skinning/TaikoLegacySkinTransformer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs index c88480d18f..ddbf20b827 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs @@ -114,6 +114,13 @@ namespace osu.Game.Rulesets.Taiko.Skinning return null; + case TaikoSkinComponents.TaikoExplosionKiai: + // suppress the default kiai explosion if the skin brings its own sprites. + if (hasExplosion.Value) + return Drawable.Empty(); + + return null; + case TaikoSkinComponents.Scroller: if (GetTexture("taiko-slider") != null) return new LegacyTaikoScroller(); From be4735cd2ba8f37e853d9a09796d1248cbddc8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Nov 2020 14:50:19 +0100 Subject: [PATCH 05/15] Explicitly set lifetime to ensure empty drawables are cleaned up --- .../Skinning/TaikoLegacySkinTransformer.cs | 3 ++- osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs index ddbf20b827..880af3fbd8 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs @@ -116,8 +116,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning case TaikoSkinComponents.TaikoExplosionKiai: // suppress the default kiai explosion if the skin brings its own sprites. + // the drawable needs to expire as soon as possible to avoid accumulating empty drawables on the playfield. if (hasExplosion.Value) - return Drawable.Empty(); + return KiaiHitExplosion.EmptyExplosion(); return null; diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index 20900a9352..326cb23897 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -43,5 +43,11 @@ namespace osu.Game.Rulesets.Taiko.UI { Child = skinnable = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoExplosionKiai), _ => new DefaultKiaiHitExplosion(hitType)); } + + /// + /// Helper function to use when an explosion is not desired. + /// Lifetime is set to avoid accumulating empty drawables in the parent container. + /// + public static Drawable EmptyExplosion() => Empty().With(d => d.LifetimeEnd = double.MinValue); } } From 1173ef089099e2468b80cf33eeb8f9bf79bbcc80 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Nov 2020 12:37:00 +0900 Subject: [PATCH 06/15] Fix mania notelock crashing with overlapping hitwindows --- .../TestSceneHoldNoteInput.cs | 2 +- .../TestSceneOutOfOrderHits.cs | 23 +++++++++++++++++++ .../Objects/Drawables/DrawableHoldNote.cs | 2 +- .../UI/OrderedHitPolicy.cs | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 5cb1519196..6c9f184c2c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Mania.Tests assertHeadJudgement(HitResult.Miss); assertTickJudgement(HitResult.LargeTickMiss); assertTailJudgement(HitResult.Miss); - assertNoteJudgement(HitResult.IgnoreHit); + assertNoteJudgement(HitResult.IgnoreMiss); } /// diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index e8c2472c3b..d699921307 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -54,6 +54,29 @@ namespace osu.Game.Rulesets.Mania.Tests } } + [Test] + public void TestMissAfterNextObjectStartTime() + { + var objects = new List + { + new HoldNote + { + StartTime = 1000, + EndTime = 1200, + }, + new HoldNote + { + StartTime = 1220, + EndTime = 1420 + } + }; + + performTest(objects, new List()); + + addJudgementAssert(objects[0], HitResult.IgnoreMiss); + addJudgementAssert(objects[1], HitResult.IgnoreMiss); + } + private void addJudgementAssert(ManiaHitObject hitObject, HitResult result) { AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judgement is {result}", diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index d9d740c145..3b3f72157a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -233,7 +233,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (Tail.AllJudged) { - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(r => r.Type = Tail.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); endHold(); } diff --git a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs index 0f9cd48dd8..9bc577a81e 100644 --- a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.UI /// The that was hit. public void HandleHit(DrawableHitObject hitObject) { - if (!IsHittable(hitObject, hitObject.HitObject.StartTime + hitObject.Result.TimeOffset)) + if (hitObject.IsHit && !IsHittable(hitObject, hitObject.HitObject.StartTime + hitObject.Result.TimeOffset)) throw new InvalidOperationException($"A {hitObject} was hit before it became hittable!"); foreach (var obj in enumerateHitObjectsUpTo(hitObject.HitObject.StartTime)) From 626231d90626790a063f9b93256276e2b4d8135e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Nov 2020 12:53:32 +0900 Subject: [PATCH 07/15] Completely remove check as it can occur for hits too --- .../TestSceneOutOfOrderHits.cs | 51 +++++++++++++++++-- .../UI/OrderedHitPolicy.cs | 4 -- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index d699921307..86a142f2f6 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.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 System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -55,19 +56,19 @@ namespace osu.Game.Rulesets.Mania.Tests } [Test] - public void TestMissAfterNextObjectStartTime() + public void TestHoldNoteMissAfterNextObjectStartTime() { var objects = new List { new HoldNote { StartTime = 1000, - EndTime = 1200, + EndTime = 1010, }, new HoldNote { - StartTime = 1220, - EndTime = 1420 + StartTime = 1020, + EndTime = 1030 } }; @@ -77,12 +78,54 @@ namespace osu.Game.Rulesets.Mania.Tests addJudgementAssert(objects[1], HitResult.IgnoreMiss); } + [Test] + public void TestHoldNoteReleasedHitAfterNextObjectStartTime() + { + var objects = new List + { + new HoldNote + { + StartTime = 1000, + EndTime = 1010, + }, + new HoldNote + { + StartTime = 1020, + EndTime = 1030 + } + }; + + var frames = new List + { + new ManiaReplayFrame(1000, ManiaAction.Key1), + new ManiaReplayFrame(1030), + new ManiaReplayFrame(1040, ManiaAction.Key1), + new ManiaReplayFrame(1050) + }; + + performTest(objects, frames); + + addJudgementAssert(objects[0], HitResult.IgnoreHit); + addJudgementAssert("first head", () => ((HoldNote)objects[0]).Head, HitResult.Perfect); + addJudgementAssert("first tail", () => ((HoldNote)objects[0]).Tail, HitResult.Perfect); + + addJudgementAssert(objects[1], HitResult.IgnoreHit); + addJudgementAssert("second head", () => ((HoldNote)objects[1]).Head, HitResult.Great); + addJudgementAssert("second tail", () => ((HoldNote)objects[1]).Tail, HitResult.Perfect); + } + private void addJudgementAssert(ManiaHitObject hitObject, HitResult result) { AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judgement is {result}", () => judgementResults.Single(r => r.HitObject == hitObject).Type == result); } + private void addJudgementAssert(string name, Func hitObject, HitResult result) + { + AddAssert($"{name} judgement is {result}", + () => judgementResults.Single(r => r.HitObject == hitObject()).Type == result); + } + private void addJudgementOffsetAssert(ManiaHitObject hitObject, double offset) { AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judged at {offset}", diff --git a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs index 9bc577a81e..961858b62b 100644 --- a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -44,9 +43,6 @@ namespace osu.Game.Rulesets.Mania.UI /// The that was hit. public void HandleHit(DrawableHitObject hitObject) { - if (hitObject.IsHit && !IsHittable(hitObject, hitObject.HitObject.StartTime + hitObject.Result.TimeOffset)) - throw new InvalidOperationException($"A {hitObject} was hit before it became hittable!"); - foreach (var obj in enumerateHitObjectsUpTo(hitObject.HitObject.StartTime)) { if (obj.Judged) From 508ae91a978e3d706d654457cbfaff4206aea266 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Nov 2020 12:53:53 +0900 Subject: [PATCH 08/15] Revert unnecessary change --- osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs | 2 +- osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs | 4 ++-- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 6c9f184c2c..5cb1519196 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Mania.Tests assertHeadJudgement(HitResult.Miss); assertTickJudgement(HitResult.LargeTickMiss); assertTailJudgement(HitResult.Miss); - assertNoteJudgement(HitResult.IgnoreMiss); + assertNoteJudgement(HitResult.IgnoreHit); } /// diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index 86a142f2f6..cecac38f70 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -74,8 +74,8 @@ namespace osu.Game.Rulesets.Mania.Tests performTest(objects, new List()); - addJudgementAssert(objects[0], HitResult.IgnoreMiss); - addJudgementAssert(objects[1], HitResult.IgnoreMiss); + addJudgementAssert(objects[0], HitResult.IgnoreHit); + addJudgementAssert(objects[1], HitResult.IgnoreHit); } [Test] diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 3b3f72157a..d9d740c145 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -233,7 +233,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (Tail.AllJudged) { - ApplyResult(r => r.Type = Tail.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(r => r.Type = r.Judgement.MaxResult); endHold(); } From 804450e707300b51abfc13014d354f9a9a1123ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Nov 2020 15:49:45 +0900 Subject: [PATCH 09/15] Remove duplicate instantiation of externalLinkOpener --- osu.Game/OsuGame.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5119f262d5..a4e7214d32 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -662,7 +662,6 @@ namespace osu.Game loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); - loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add); chatOverlay.State.ValueChanged += state => channelManager.HighPollRate.Value = state.NewValue == Visibility.Visible; From 5d55af58182449a73da8aea2c5da743fb86fc589 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Nov 2020 16:35:48 +0900 Subject: [PATCH 10/15] Fix hitobjects sometimes not fading in completely with HD mod --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 10 ++++++++-- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 025e202666..cf7faca9b9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -27,17 +27,23 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var d in drawables) - d.ApplyCustomUpdateState += applyFadeInAdjustment; + { + d.HitObjectApplied += applyFadeInAdjustment; + applyFadeInAdjustment(d); + } base.ApplyToDrawableHitObjects(drawables); } - private void applyFadeInAdjustment(DrawableHitObject hitObject, ArmedState state) + private void applyFadeInAdjustment(DrawableHitObject hitObject) { if (!(hitObject is DrawableOsuHitObject d)) return; d.HitObject.TimeFadeIn = d.HitObject.TimePreempt * fade_in_duration_multiplier; + + foreach (var nested in d.NestedHitObjects) + applyFadeInAdjustment(nested); } private double lastSliderHeadFadeOutStartTime; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7a4e136553..62709b2900 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -26,8 +26,16 @@ namespace osu.Game.Rulesets.Objects.Drawables [Cached(typeof(DrawableHitObject))] public abstract class DrawableHitObject : SkinReloadableDrawable { + /// + /// Invoked after this 's applied has had its defaults applied. + /// public event Action DefaultsApplied; + /// + /// Invoked after a has been applied to this . + /// + public event Action HitObjectApplied; + /// /// The currently represented by this . /// @@ -192,6 +200,7 @@ namespace osu.Game.Rulesets.Objects.Drawables HitObject.DefaultsApplied += onDefaultsApplied; OnApply(hitObject); + HitObjectApplied?.Invoke(this); // If not loaded, the state update happens in LoadComplete(). Otherwise, the update is scheduled to allow for lifetime updates. if (IsLoaded) From 891218ec6b754ef13165c9e95dc88b64d66d9c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 11 Nov 2020 09:11:33 +0100 Subject: [PATCH 11/15] Inline empty explosion in legacy transformer --- .../Skinning/TaikoLegacySkinTransformer.cs | 2 +- osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs index 880af3fbd8..96fb065e79 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning // suppress the default kiai explosion if the skin brings its own sprites. // the drawable needs to expire as soon as possible to avoid accumulating empty drawables on the playfield. if (hasExplosion.Value) - return KiaiHitExplosion.EmptyExplosion(); + return Drawable.Empty().With(d => d.LifetimeEnd = double.MinValue); return null; diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index 326cb23897..20900a9352 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -43,11 +43,5 @@ namespace osu.Game.Rulesets.Taiko.UI { Child = skinnable = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.TaikoExplosionKiai), _ => new DefaultKiaiHitExplosion(hitType)); } - - /// - /// Helper function to use when an explosion is not desired. - /// Lifetime is set to avoid accumulating empty drawables in the parent container. - /// - public static Drawable EmptyExplosion() => Empty().With(d => d.LifetimeEnd = double.MinValue); } } From a08833f3b3cd3b7581be8e95a0b56d03611c8567 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Nov 2020 18:03:04 +0900 Subject: [PATCH 12/15] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index bbe8426316..5078fee1cf 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8f0cc58594..405fb1a6ca 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index f766e0ec03..099ecd8319 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From f753f138c6bb3df154e109d30ee6bbbaaa841257 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Nov 2020 03:11:29 +0300 Subject: [PATCH 13/15] Add counter to most played beatmaps section in user overlay --- .../Historical/PaginatedMostPlayedBeatmapContainer.cs | 4 +++- osu.Game/Users/User.cs | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 8f19cd900c..556f3139dd 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer { public PaginatedMostPlayedBeatmapContainer(Bindable user) - : base(user, "Most Played Beatmaps", "No records. :(") + : base(user, "Most Played Beatmaps", "No records. :(", CounterVisibilityState.AlwaysVisible) { ItemsPerPage = 5; } @@ -27,6 +27,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical ItemsContainer.Direction = FillDirection.Vertical; } + protected override int GetCount(User user) => user.BeatmapPlaycountsCount; + protected override APIRequest> CreateRequest() => new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 2a76a963e1..d7e78d5b35 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -144,6 +144,9 @@ namespace osu.Game.Users [JsonProperty(@"scores_first_count")] public int ScoresFirstCount; + [JsonProperty(@"beatmap_playcounts_count")] + public int BeatmapPlaycountsCount; + [JsonProperty] private string[] playstyle { From 25af091409142d702041f5a5bd15bea093c78897 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Nov 2020 17:03:42 +0900 Subject: [PATCH 14/15] Fix storyboard animations of very old beatmaps playing too slow Closes https://github.com/ppy/osu/issues/10772. --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 -- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 ++ osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 12 +++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 442be6e837..37ab489da5 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -16,8 +16,6 @@ namespace osu.Game.Beatmaps.Formats { public class LegacyBeatmapDecoder : LegacyDecoder { - public const int LATEST_VERSION = 14; - private Beatmap beatmap; private ConvertHitObjectParser parser; diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 7b377e481f..de4dc8cdc8 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -16,6 +16,8 @@ namespace osu.Game.Beatmaps.Formats public abstract class LegacyDecoder : Decoder where T : new() { + public const int LATEST_VERSION = 14; + protected readonly int FormatVersion; protected LegacyDecoder(int version) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 8d8ca523d5..9a244c8bb2 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Beatmaps.Legacy; @@ -23,15 +24,15 @@ namespace osu.Game.Beatmaps.Formats private readonly Dictionary variables = new Dictionary(); - public LegacyStoryboardDecoder() - : base(0) + public LegacyStoryboardDecoder(int version = LATEST_VERSION) + : base(version) { } public static void Register() { // note that this isn't completely correct - AddDecoder(@"osu file format v", m => new LegacyStoryboardDecoder()); + AddDecoder(@"osu file format v", m => new LegacyStoryboardDecoder(Parsing.ParseInt(m.Split('v').Last()))); AddDecoder(@"[Events]", m => new LegacyStoryboardDecoder()); SetFallbackDecoder(() => new LegacyStoryboardDecoder()); } @@ -133,6 +134,11 @@ namespace osu.Game.Beatmaps.Formats var y = Parsing.ParseFloat(split[5], Parsing.MAX_COORDINATE_VALUE); var frameCount = Parsing.ParseInt(split[6]); var frameDelay = Parsing.ParseDouble(split[7]); + + if (FormatVersion < 6) + // this is random as hell but taken straight from osu-stable. + frameDelay = Math.Round(0.015 * frameDelay) * 1.186 * (1000 / 60f); + var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever; storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); storyboard.GetLayer(layer).Add(storyboardSprite); From de31c1ea0cd3df825d65fae00dc6b644d3f16a9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Nov 2020 17:58:39 +0900 Subject: [PATCH 15/15] Fix skinfallback test crashing on repeats --- osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 075bf314bc..856bfd7e80 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -125,6 +125,9 @@ namespace osu.Game.Rulesets.Osu.Tests { if (!enabled) return null; + if (component is OsuSkinComponent osuComponent && osuComponent.Component == OsuSkinComponents.SliderBody) + return null; + return new OsuSpriteText { Text = identifier,