diff --git a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowTest.cs b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowTest.cs new file mode 100644 index 0000000000..aed2a5c122 --- /dev/null +++ b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowTest.cs @@ -0,0 +1,123 @@ +// 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.Diagnostics.CodeAnalysis; +using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; + +namespace osu.Game.Tests.NonVisual +{ + public class FirstAvailableHitWindowsTest + { + private TestDrawableRuleset testDrawableRuleset; + + [SetUp] + public void Setup() + { + testDrawableRuleset = new TestDrawableRuleset(); + } + + [Test] + public void TestResultIfOnlyParentHitWindowIsEmpty() + { + var testObject = new TestHitObject(HitWindows.Empty); + HitObject nested = new TestHitObject(new HitWindows()); + testObject.AddNested(nested); + testDrawableRuleset.HitObjects = new List { testObject }; + + Assert.AreSame(testDrawableRuleset.FirstAvailableHitWindows, nested.HitWindows); + } + + [Test] + public void TestResultIfParentHitWindowsIsNotEmpty() + { + var testObject = new TestHitObject(new HitWindows()); + HitObject nested = new TestHitObject(new HitWindows()); + testObject.AddNested(nested); + testDrawableRuleset.HitObjects = new List { testObject }; + + Assert.AreSame(testDrawableRuleset.FirstAvailableHitWindows, testObject.HitWindows); + } + + [Test] + public void TestResultIfParentAndChildHitWindowsAreEmpty() + { + var firstObject = new TestHitObject(HitWindows.Empty); + HitObject nested = new TestHitObject(HitWindows.Empty); + firstObject.AddNested(nested); + + var secondObject = new TestHitObject(new HitWindows()); + testDrawableRuleset.HitObjects = new List { firstObject, secondObject }; + + Assert.AreSame(testDrawableRuleset.FirstAvailableHitWindows, secondObject.HitWindows); + } + + [Test] + public void TestResultIfAllHitWindowsAreEmpty() + { + var firstObject = new TestHitObject(HitWindows.Empty); + HitObject nested = new TestHitObject(HitWindows.Empty); + firstObject.AddNested(nested); + + testDrawableRuleset.HitObjects = new List { firstObject }; + + Assert.IsNull(testDrawableRuleset.FirstAvailableHitWindows); + } + + [SuppressMessage("ReSharper", "UnassignedGetOnlyAutoProperty")] + private class TestDrawableRuleset : DrawableRuleset + { + public List HitObjects; + public override IEnumerable Objects => HitObjects; + + public override event Action NewResult; + public override event Action RevertResult; + + public override Playfield Playfield { get; } + public override Container Overlays { get; } + public override Container FrameStableComponents { get; } + public override IFrameStableClock FrameStableClock { get; } + internal override bool FrameStablePlayback { get; set; } + public override IReadOnlyList Mods { get; } + + public override double GameplayStartTime { get; } + public override GameplayCursorContainer Cursor { get; } + + public TestDrawableRuleset() + : base(new OsuRuleset()) + { + // won't compile without this. + NewResult?.Invoke(null); + RevertResult?.Invoke(null); + } + + public override void SetReplayScore(Score replayScore) => throw new NotImplementedException(); + + public override void SetRecordTarget(Score score) => throw new NotImplementedException(); + + public override void RequestResume(Action continueResume) => throw new NotImplementedException(); + + public override void CancelResume() => throw new NotImplementedException(); + } + } + + public class TestHitObject : HitObject + { + public TestHitObject(HitWindows hitWindows) + { + HitWindows = hitWindows; + HitWindows.SetDifficulty(0.5f); + } + + public new void AddNested(HitObject nested) => base.AddNested(nested); + } +} diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 8dcc1ca164..daf46dcdcc 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -489,15 +489,15 @@ namespace osu.Game.Rulesets.UI { get { - foreach (var h in Objects) + foreach (var hitObject in Objects) { - if (h.HitWindows.WindowFor(HitResult.Miss) > 0) - return h.HitWindows; + if (hitObject.HitWindows.WindowFor(HitResult.Miss) > 0) + return hitObject.HitWindows; - foreach (var n in h.NestedHitObjects) + foreach (var nested in hitObject.NestedHitObjects) { - if (h.HitWindows.WindowFor(HitResult.Miss) > 0) - return n.HitWindows; + if (nested.HitWindows.WindowFor(HitResult.Miss) > 0) + return nested.HitWindows; } }