From 3f8dfc7cb035adc38e849ac1fc895739aec86b6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Jul 2023 18:02:03 +0900 Subject: [PATCH 1/2] Fix fallback for `Judged` to be more correct Without this change, when the `Judged` value is checked on an `HitObjectLifetimeEntry` it would return `true` if a `DrawableHitObject` has not yet been associated with the entry. Which is completely wrong. Of note, the usage in `DrawableHitObject` will have never fallen through to this incorrect value as they always have a result populated: https://github.com/ppy/osu/blob/f26f001e1d01ca6bb53225da7bf06c0ad21153c5/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs#L721-L726 --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++-- osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 08dcf91e52..e4d8eb2335 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -112,12 +112,12 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether this has been judged. /// Note: This does NOT include nested hitobjects. /// - public bool Judged => Entry?.Judged ?? true; + public bool Judged => Entry?.Judged ?? false; /// /// Whether this and all of its nested s have been judged. /// - public bool AllJudged => Entry?.AllJudged ?? true; + public bool AllJudged => Entry?.AllJudged ?? false; /// /// The relative X position of this hit object for sample playback balance adjustment. diff --git a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs index 1d99e7440f..4450f026b4 100644 --- a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs +++ b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Objects /// Whether has been judged. /// Note: This does NOT include nested hitobjects. /// - public bool Judged => Result?.HasResult ?? true; + public bool Judged => Result?.HasResult ?? false; /// /// Whether and all of its nested objects have been judged. From e21dc56fcbc307b517ee51491d06a29cc8f07e9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Jul 2023 18:20:25 +0900 Subject: [PATCH 2/2] Add test coverage of `Judged` state --- .../Gameplay/TestSceneDrawableHitObject.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 04fc4cafbd..10dbede2e0 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; @@ -80,7 +81,9 @@ namespace osu.Game.Tests.Gameplay { TestLifetimeEntry entry = null; AddStep("Create entry", () => entry = new TestLifetimeEntry(new HitObject()) { LifetimeStart = 1 }); + assertJudged(() => entry, false); AddStep("ApplyDefaults", () => entry.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty())); + assertJudged(() => entry, false); AddAssert("Lifetime is updated", () => entry.LifetimeStart == -TestLifetimeEntry.INITIAL_LIFETIME_OFFSET); TestDrawableHitObject dho = null; @@ -91,6 +94,7 @@ namespace osu.Game.Tests.Gameplay }); AddStep("ApplyDefaults", () => entry.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty())); AddAssert("Lifetime is correct", () => dho.LifetimeStart == TestDrawableHitObject.LIFETIME_ON_APPLY && entry.LifetimeStart == TestDrawableHitObject.LIFETIME_ON_APPLY); + assertJudged(() => entry, false); } [Test] @@ -138,6 +142,29 @@ namespace osu.Game.Tests.Gameplay AddAssert("DHO state is correct", () => dho.State.Value == ArmedState.Miss); } + [Test] + public void TestJudgedStateThroughLifetime() + { + TestDrawableHitObject dho = null; + HitObjectLifetimeEntry lifetimeEntry = null; + + AddStep("Create lifetime entry", () => lifetimeEntry = new HitObjectLifetimeEntry(new HitObject { StartTime = Time.Current })); + + assertJudged(() => lifetimeEntry, false); + + AddStep("Create DHO and apply entry", () => + { + Child = dho = new TestDrawableHitObject(); + dho.Apply(lifetimeEntry); + }); + + assertJudged(() => lifetimeEntry, false); + + AddStep("Apply result", () => dho.MissForcefully()); + + assertJudged(() => lifetimeEntry, true); + } + [Test] public void TestResultSetBeforeLoadComplete() { @@ -154,15 +181,20 @@ namespace osu.Game.Tests.Gameplay } }; }); + assertJudged(() => lifetimeEntry, true); AddStep("Create DHO and apply entry", () => { dho = new TestDrawableHitObject(); dho.Apply(lifetimeEntry); Child = dho; }); + assertJudged(() => lifetimeEntry, true); AddAssert("DHO state is correct", () => dho.State.Value, () => Is.EqualTo(ArmedState.Hit)); } + private void assertJudged(Func entry, bool val) => + AddAssert(val ? "Is judged" : "Not judged", () => entry().Judged, () => Is.EqualTo(val)); + private partial class TestDrawableHitObject : DrawableHitObject { public const double INITIAL_LIFETIME_OFFSET = 100;