From befe57e12ef017b9cffdf9bb2a4239b0ae9ecdf1 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 17 Nov 2018 15:23:52 +0300 Subject: [PATCH 01/54] Stop PreviewTrack on Completed event --- osu.Game/Audio/PreviewTrack.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 3c9122b941..9fe1c3d2eb 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -28,6 +28,7 @@ namespace osu.Game.Audio private void load() { track = GetTrack(); + track.Completed += Stop; } /// @@ -50,15 +51,6 @@ namespace osu.Game.Audio /// public bool IsRunning => track?.IsRunning ?? false; - protected override void Update() - { - base.Update(); - - // Todo: Track currently doesn't signal its completion, so we have to handle it manually - if (hasStarted && track.HasCompleted) - Stop(); - } - private ScheduledDelegate startDelegate; /// From c4fc87b69a6acfaf94afecad4d0f45d3cf0d190c Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 17 Nov 2018 15:39:40 +0300 Subject: [PATCH 02/54] Move to next track on Completed event --- osu.Game/Overlays/MusicController.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index f282b757cd..790aab16d0 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -253,9 +253,6 @@ namespace osu.Game.Overlays progressBar.CurrentTime = track.CurrentTime; playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; - - if (track.HasCompleted && !track.Looping && !beatmap.Disabled && beatmapSets.Any()) - next(); } else { @@ -333,9 +330,13 @@ namespace osu.Game.Overlays direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } + + current.Track.Completed -= currentTrackCompleted; } current = beatmap; + if (current != null) + current.Track.Completed += currentTrackCompleted; progressBar.CurrentTime = 0; @@ -344,6 +345,12 @@ namespace osu.Game.Overlays queuedDirection = null; } + private void currentTrackCompleted() + { + if (!beatmap.Disabled && beatmapSets.Any()) + next(); + } + private ScheduledDelegate pendingBeatmapSwitch; private void updateDisplay(WorkingBeatmap beatmap, TransformDirection direction) From d3721707fb7bebb3c9d1c0b0f8ab9dc5e2a4645b Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 8 Feb 2019 19:48:56 +0300 Subject: [PATCH 03/54] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 596190fcf7..e87b43ac93 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + From a62f1509627952a84a0c15bbbdb381bd587dc401 Mon Sep 17 00:00:00 2001 From: Ignacio Conde Date: Fri, 22 Feb 2019 02:28:38 -0300 Subject: [PATCH 04/54] Fixed Issue #4159 --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 57728dd134..ba87fe6ed9 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -330,12 +330,12 @@ namespace osu.Game.Rulesets.Mania for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++) bindings.Add(new KeyBinding(LeftKeys[i], currentNormalAction++)); - for (int i = 0; i < columns / 2; i++) - bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); - if (columns % 2 == 1) bindings.Add(new KeyBinding(SpecialKey, SpecialAction)); + for (int i = 0; i < columns / 2; i++) + bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); + nextNormalAction = currentNormalAction; return bindings; } From 7566fcf536df736934fbe258abd433106a660af7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Jan 2019 10:57:14 +0900 Subject: [PATCH 05/54] Slider press fix --- .../Objects/Drawables/DrawableHitCircle.cs | 4 +++ .../Objects/Drawables/DrawableSlider.cs | 1 + .../Objects/Drawables/Pieces/CirclePiece.cs | 10 +++++- .../Objects/Drawables/Pieces/SliderBall.cs | 31 +++++++++++++++---- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 18c28deb9d..e909216508 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); + public OsuAction? HitAction => circle.HitAction; + private readonly Container explodeContainer; private readonly Container scaleContainer; @@ -150,6 +152,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); + circle.HitAction = null; + // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); break; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 89521736c7..b55ec10d1d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -53,6 +53,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) { + GetInitialHitAction = () => HeadCircle.HitAction, BypassAutoSizeAxes = Axes.Both, Scale = new Vector2(s.Scale), AlwaysPresent = true, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index b7e2748ca9..786cac7198 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public Func Hit; + public OsuAction? HitAction; + public CirclePiece() { Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2); @@ -35,7 +37,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { case OsuAction.LeftButton: case OsuAction.RightButton: - return IsHovered && (Hit?.Invoke() ?? false); + if (IsHovered && (Hit?.Invoke() ?? false)) + { + HitAction = action; + return true; + } + + break; } return false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index db9fee242a..93c655797a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.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.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private Color4 accentColour = Color4.Black; + public Func GetInitialHitAction; + /// /// The colour that is used for the slider ball. /// @@ -145,19 +148,35 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime; + private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime && lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value); + + /// + /// The point in time up to which we need to include the key which was used to press the head circle in tracking conditions. + /// + private double? initialHitConditionDismissed; protected override void Update() { base.Update(); - if (Time.Current < slider.EndTime) + var initialHitAction = GetInitialHitAction(); + + if (initialHitAction == null) + initialHitConditionDismissed = null; + + if (canCurrentlyTrack) { + var pressed = drawableSlider?.OsuActionInputManager?.PressedActions; + + if (initialHitConditionDismissed == null && !pressed.Contains(initialHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton)) + initialHitConditionDismissed = Time.Current; + // Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position. - Tracking = canCurrentlyTrack - && lastScreenSpaceMousePosition.HasValue - && ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) - && (drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); + Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => !initialHitConditionDismissed.HasValue || initialHitConditionDismissed.Value < Time.Current ? x == OsuAction.LeftButton || x == OsuAction.RightButton : x == initialHitAction) ?? false; + } + else + { + Tracking = false; } } From 94d3814ae342290ac1af5da1c95dbc1a405ae0e2 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 21 Jan 2019 14:40:28 +0900 Subject: [PATCH 06/54] Add tests for slider input behavior --- .../TestCaseSliderInput.cs | 406 ++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs new file mode 100644 index 0000000000..ebfc11a961 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -0,0 +1,406 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Replays; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestCaseSliderInput : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Slider), + typeof(SliderBall), + typeof(SliderBody), + typeof(SliderTick), + typeof(DrawableSlider), + typeof(DrawableSliderTick), + typeof(DrawableRepeatPoint), + typeof(DrawableOsuHitObject) + }; + + [SetUp] + public void Setup() + { + Schedule(() => { allJudgedFired = false; }); + judgementResults = new List(); + } + + private readonly Container content; + protected override Container Content => content; + + private List judgementResults; + private bool allJudgedFired; + + public TestCaseSliderInput() + { + base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); + } + + /// + /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the latter pressed key + /// should result in tracking to end. + /// At 250ms intervals: + /// Frame 1 (prior to slider): Left Click + /// Frame 2 (within slider hit window): Left & Right Click + /// Frame 3 (while tracking): Left Click + /// A passing test case will have the cursor lose tracking on frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRight() + { + AddStep("Invalid key transfer test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 2500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 1"); + AddAssert("Tracking lost", assertMehJudge); + } + + /// + /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the original key used to hit + /// the slider should reslt in continued tracking. + /// At 250ms intervals: + /// Frame 1: Left Click + /// Frame 2: Left & Right Click + /// Frame 3: Right Click + /// A passing test case will have the cursor continue to track after frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() + { + AddStep("Left to both to right test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = 3500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 2"); + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the new key should result + /// in continue tracking, + /// At 250ms intervals: + /// Frame 1: Left Click + /// Frame 2: Left & Right Click + /// Frame 3: Left Click + /// A passing test case will have the cursor continue to track after frame 3. + /// + [Test] + public void TestTrackingRetentionLeftRightLeft() + { + AddStep("Tracking retention test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = 2500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 3"); + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the former pressed key + /// should result in continued tracking. + /// At 250ms intervals: + /// Frame 1 (prior to slider): Left Click + /// Frame 2 (on slider head): Left & Right Click + /// Frame 3 (tracking slider body): Right Click + /// A passing test case will have the cursor continue to track after frame 3. + /// + [Test] + public void TestTrackingLeftBeforeSliderToRight() + { + AddStep("Tracking retention test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = 2500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 4"); + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Pressing a key before a slider and holding the slider throughout the body should result in tracking, but a miss on the slider head. + /// Only one frame is required: + /// Frame 1: Left Click + /// In a successful test case: + /// The head of the slider should be judged as a miss. + /// The slider end should be judged as a meh. + /// + [Test] + public void TestTrackingPreclicked() + { + AddStep("Tracking retention test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 5"); + AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailMeh); + } + + /// + /// Hitting a slider head, leaving the slider, then coming back into the slider with the same button to track it should re-start tracking. + /// Only one frame is required: + /// Frame 1: Left Click + /// In a successful test case: + /// The last tick of the slider should be judged as a great. + /// + [Test] + public void TestTrackingReturnMidSlider() + { + AddStep("Mid-sldier tracking re-acquisition", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = 2000}, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3000}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 6"); + AddAssert("Tracking re-acquired", assertMidSliderJudgements); + } + + /// + /// Pressing a key before a slider, hitting a slider head, leaving the slider, then coming back into the slider to track it should NOT start retracking + /// This is current stable behavior. + /// + [Test] + public void TestTrackingReturnMidSliderKeyDownBefore() + { + AddStep("Key held down before slider, mid-slider tracking re-acquisition", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 2000}, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3000}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 7"); + AddAssert("Tracking lost", assertMidSliderJudgementFail); + } + + /// + /// Halfway into a slider outside of the slider, then starting to hover the slider afterwards should result in tracking + /// + [Test] + public void TestTrackingMidSlider() + { + AddStep("Mid-slider new tracking acquisition", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = 2000}, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3000}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 8"); + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + /// + /// Pressing a key before a slider, clicking another key after the slider, holding both of them and + /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking + /// + [Test] + public void TestTrackingPressBeforeSliderClickingOtherKeyLeavingSliderReleaseThenTrackOriginal() + { + AddStep("Mid-slider new tracking acquisition", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = 1750}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 9"); + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + /// + /// Pressing a key before a slider, clicking another key after the slider, holding both of them and + /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking + /// + [Test] + public void TestClickingBeforeLeavingSliderReleasingClickingAgainThenTracking() + { + AddStep("Mid-slider new tracking acquisition", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 1500}, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = 2750}, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = 3000}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + }; + + performStaticInputTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 10"); + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + private bool assertMehJudge() + { + return judgementResults.Last().Type == HitResult.Meh; + } + + private bool assertGreatJudge() + { + return judgementResults.Last().Type == HitResult.Great; + } + + private bool assertHeadMissTailMeh() + { + return judgementResults.Last().Type == HitResult.Meh && judgementResults.First().Type == HitResult.Miss; + } + + private bool assertMidSliderJudgements() + { + return judgementResults[judgementResults.Count - 2].Type == HitResult.Great; + } + + private bool assertMidSliderJudgementFail() + { + return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; + } + + private void performStaticInputTest(List frames) + { + var slider = new Slider + { + StartTime = 1500, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + }; + + // Empty frame to be added as a workaround for first frame behavior. + // If an input exists on the first frame, the input would apply to the entire intro lead-in + // Likely requires some discussion regarding how first frame inputs should be handled. + frames.Insert(0, new OsuReplayFrame { Position = slider.Position, Time = 0, Actions = new List() }); + + Beatmap.Value = new TestWorkingBeatmap(new Beatmap + { + HitObjects = { slider }, + ControlPointInfo = + { + DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, + Ruleset = new OsuRuleset().RulesetInfo + }, + }); + + var player = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false + }; + + Child = player; + + player.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); + + player.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; + } + + private class ScoreAccessibleReplayPlayer : ReplayPlayer + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public ScoreAccessibleReplayPlayer(Score score) + : base(score) + { + } + } + } +} From 1c75ee4e824515c66213478bf68548feb96c4a9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Jan 2019 14:47:27 +0900 Subject: [PATCH 07/54] Add fixes --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 93c655797a..20a713c2d1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -168,11 +168,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { var pressed = drawableSlider?.OsuActionInputManager?.PressedActions; - if (initialHitConditionDismissed == null && !pressed.Contains(initialHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton)) + if (initialHitAction != null && !pressed.Contains(initialHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton)) initialHitConditionDismissed = Time.Current; // Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position. - Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => !initialHitConditionDismissed.HasValue || initialHitConditionDismissed.Value < Time.Current ? x == OsuAction.LeftButton || x == OsuAction.RightButton : x == initialHitAction) ?? false; + Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => !initialHitAction.HasValue || (initialHitConditionDismissed.HasValue && initialHitConditionDismissed.Value < Time.Current) ? x == OsuAction.LeftButton || x == OsuAction.RightButton : x == initialHitAction) ?? false; } else { From 8e52e2330e2f278efb468a0c90d2de1b97be7674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Jan 2019 15:46:49 +0900 Subject: [PATCH 08/54] Add extensive commenting --- .../Objects/Drawables/Pieces/SliderBall.cs | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 20a713c2d1..bff225eae7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -151,28 +151,50 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime && lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value); /// - /// The point in time up to which we need to include the key which was used to press the head circle in tracking conditions. + /// If the cursor moves out of the ball's radius we still need to be able to receive positional updates to stop tracking. /// - private double? initialHitConditionDismissed; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + /// + /// The point in time after which we can accept any key for tracking. Before this time, we may need to restrict tracking to the key used to hit the head circle. + /// This is a requirement to stop the case where a player holds down one key (from before the slider) and taps the second key while maintaining full scoring (tracking) of sliders. + /// + /// Visually, if time is increasing from left to right: + /// + /// Z Z+X Z + /// o========o + /// + /// Without this logic, tracking would continue through the entire slider even though no key hold is directly attributing to it. + /// + /// + private double? timeToAcceptAnyKeyAfter; protected override void Update() { base.Update(); - var initialHitAction = GetInitialHitAction(); + // from the point at which the head circle is hit, this will be non-null. + // it may be null if the head circle was missed. + var headCircleHitAction = GetInitialHitAction(); - if (initialHitAction == null) - initialHitConditionDismissed = null; + if (headCircleHitAction == null) + timeToAcceptAnyKeyAfter = null; if (canCurrentlyTrack) { var pressed = drawableSlider?.OsuActionInputManager?.PressedActions; - if (initialHitAction != null && !pressed.Contains(initialHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton)) - initialHitConditionDismissed = Time.Current; + // if the head circle was hit with a specific key, tracking should only occur while that key is pressed. + if (headCircleHitAction != null && timeToAcceptAnyKeyAfter == null) + { + var otherKey = headCircleHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton; - // Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position. - Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => !initialHitAction.HasValue || (initialHitConditionDismissed.HasValue && initialHitConditionDismissed.Value < Time.Current) ? x == OsuAction.LeftButton || x == OsuAction.RightButton : x == initialHitAction) ?? false; + // we can return to accepting all keys if the initial head circle key is the *only* key pressed, or all keys have been released. + if (!pressed.Contains(otherKey)) + timeToAcceptAnyKeyAfter = Time.Current; + } + + Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(isValidTrackingAction) ?? false; } else { @@ -180,6 +202,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + /// + /// Check whether a given user input is a valid tracking action. + /// + private bool isValidTrackingAction(OsuAction action) + { + bool headCircleHit = GetInitialHitAction().HasValue; + + // if the head circle was hit, we may not yet be allowed to accept any key, so we must use the initial hit action. + if (headCircleHit && (!timeToAcceptAnyKeyAfter.HasValue || Time.Current <= timeToAcceptAnyKeyAfter.Value)) + return action == GetInitialHitAction(); + + return action == OsuAction.LeftButton || action == OsuAction.RightButton; + } + public void UpdateProgress(double completionProgress) { Position = slider.CurvePositionAt(completionProgress); From 44501d7d4bf969adff2d398a58facf64880b1338 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 21 Jan 2019 16:25:22 +0900 Subject: [PATCH 09/54] Update test documentation --- .../TestCaseSliderInput.cs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index ebfc11a961..747ed24a69 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -62,7 +62,6 @@ namespace osu.Game.Rulesets.Osu.Tests /// /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the latter pressed key /// should result in tracking to end. - /// At 250ms intervals: /// Frame 1 (prior to slider): Left Click /// Frame 2 (within slider hit window): Left & Right Click /// Frame 3 (while tracking): Left Click @@ -90,7 +89,6 @@ namespace osu.Game.Rulesets.Osu.Tests /// /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the original key used to hit /// the slider should reslt in continued tracking. - /// At 250ms intervals: /// Frame 1: Left Click /// Frame 2: Left & Right Click /// Frame 3: Right Click @@ -118,7 +116,6 @@ namespace osu.Game.Rulesets.Osu.Tests /// /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the new key should result /// in continue tracking, - /// At 250ms intervals: /// Frame 1: Left Click /// Frame 2: Left & Right Click /// Frame 3: Left Click @@ -146,7 +143,6 @@ namespace osu.Game.Rulesets.Osu.Tests /// /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the former pressed key /// should result in continued tracking. - /// At 250ms intervals: /// Frame 1 (prior to slider): Left Click /// Frame 2 (on slider head): Left & Right Click /// Frame 3 (tracking slider body): Right Click @@ -225,8 +221,10 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, hitting a slider head, leaving the slider, then coming back into the slider to track it should NOT start retracking - /// This is current stable behavior. + /// Pressing a key before a slider, hitting a slider head, leaving the slider, then coming back into the slider to track it should NOT start retracking + /// This is current stable behavior. + /// In a successful test case: + /// The last tick of the slider should be judged as a miss. /// [Test] public void TestTrackingReturnMidSliderKeyDownBefore() @@ -251,7 +249,9 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Halfway into a slider outside of the slider, then starting to hover the slider afterwards should result in tracking + /// Halfway into a slider outside of the slider, then starting to hover the slider afterwards should result in tracking + /// In a successful test case: + /// The last tick of the slider should be judged as a great. /// [Test] public void TestTrackingMidSlider() @@ -274,8 +274,10 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, clicking another key after the slider, holding both of them and - /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking + /// Pressing a key before a slider, clicking another key after the slider, holding both of them and + /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking + /// In a successful test case: + /// The last tick of the slider should be judged as a great. /// [Test] public void TestTrackingPressBeforeSliderClickingOtherKeyLeavingSliderReleaseThenTrackOriginal() @@ -298,8 +300,10 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, clicking another key after the slider, holding both of them and - /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking + /// Pressing a key before a slider, clicking another key after the slider, holding both of them and + /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking + /// In a successful test case: + /// The last tick of the slider should be judged as a great. /// [Test] public void TestClickingBeforeLeavingSliderReleasingClickingAgainThenTracking() From 3a57ff40cd03d2dfa72539ccdbad94d5f7e073f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Jan 2019 16:26:44 +0900 Subject: [PATCH 10/54] Add comment about other cases, rewind handling --- .../Objects/Drawables/Pieces/SliderBall.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index bff225eae7..2efc0678c7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -157,15 +157,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces /// /// The point in time after which we can accept any key for tracking. Before this time, we may need to restrict tracking to the key used to hit the head circle. - /// This is a requirement to stop the case where a player holds down one key (from before the slider) and taps the second key while maintaining full scoring (tracking) of sliders. /// - /// Visually, if time is increasing from left to right: + /// This is a requirement to stop the case where a player holds down one key (from before the slider) and taps the second key while maintaining full scoring (tracking) of sliders. + /// Visually, this special case can be seen below (time increasing from left to right): /// /// Z Z+X Z /// o========o /// - /// Without this logic, tracking would continue through the entire slider even though no key hold is directly attributing to it. + /// Without this logic, tracking would continue through the entire slider even though no key hold action is directly attributing to it. /// + /// In all other cases, no special handling is required (either key being pressed is allowable as valid tracking). + /// + /// The reason for storing this as a time value (rather than a bool) is to correct handle rewind scenarios. /// private double? timeToAcceptAnyKeyAfter; From dfa34776a53895a6ca284389a5798f420a9e17e3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 21 Jan 2019 16:27:44 +0900 Subject: [PATCH 11/54] Change ampersands in xmldoc --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 747ed24a69..c0fd63f548 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the latter pressed key /// should result in tracking to end. /// Frame 1 (prior to slider): Left Click - /// Frame 2 (within slider hit window): Left & Right Click + /// Frame 2 (within slider hit window): Left & Right Click /// Frame 3 (while tracking): Left Click /// A passing test case will have the cursor lose tracking on frame 3. /// @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the original key used to hit /// the slider should reslt in continued tracking. /// Frame 1: Left Click - /// Frame 2: Left & Right Click + /// Frame 2: Left & Right Click /// Frame 3: Right Click /// A passing test case will have the cursor continue to track after frame 3. /// @@ -117,7 +117,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the new key should result /// in continue tracking, /// Frame 1: Left Click - /// Frame 2: Left & Right Click + /// Frame 2: Left & Right Click /// Frame 3: Left Click /// A passing test case will have the cursor continue to track after frame 3. /// @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the former pressed key /// should result in continued tracking. /// Frame 1 (prior to slider): Left Click - /// Frame 2 (on slider head): Left & Right Click + /// Frame 2 (on slider head): Left & Right Click /// Frame 3 (tracking slider body): Right Click /// A passing test case will have the cursor continue to track after frame 3. /// From 5fdd7f9bff37298266aac572aa874f63ce494e76 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 21 Jan 2019 16:43:23 +0900 Subject: [PATCH 12/54] Fix typo in comment Co-Authored-By: peppy --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 2efc0678c7..a8ee4c42fd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -168,7 +168,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces /// /// In all other cases, no special handling is required (either key being pressed is allowable as valid tracking). /// - /// The reason for storing this as a time value (rather than a bool) is to correct handle rewind scenarios. + /// The reason for storing this as a time value (rather than a bool) is to correctly handle rewind scenarios. /// private double? timeToAcceptAnyKeyAfter; From cacefd5c6536831aaf0c382f9215b7c036231065 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 22 Jan 2019 00:54:22 +0900 Subject: [PATCH 13/54] Reword slider test xmldocs. --- .../TestCaseSliderInput.cs | 119 ++++++++++-------- 1 file changed, 67 insertions(+), 52 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index c0fd63f548..c3df821e1c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -60,12 +60,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the latter pressed key - /// should result in tracking to end. - /// Frame 1 (prior to slider): Left Click - /// Frame 2 (within slider hit window): Left & Right Click - /// Frame 3 (while tracking): Left Click - /// A passing test case will have the cursor lose tracking on frame 3. + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the latter pressed key + /// Expected Result: + /// A passing test case will have the cursor lose tracking on frame 3. /// [Test] public void TestLeftBeforeSliderThenRight() @@ -87,12 +87,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the original key used to hit - /// the slider should reslt in continued tracking. - /// Frame 1: Left Click - /// Frame 2: Left & Right Click - /// Frame 3: Right Click - /// A passing test case will have the cursor continue to track after frame 3. + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the original key used to hit the slider + /// Expected Result: + /// A passing test case will have the cursor continue tracking on frame 3. /// [Test] public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() @@ -114,12 +114,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Hitting a slider head, pressing a new key after the initial hit, then letting go of the new key should result - /// in continue tracking, - /// Frame 1: Left Click - /// Frame 2: Left & Right Click - /// Frame 3: Left Click - /// A passing test case will have the cursor continue to track after frame 3. + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the new key that was pressed second + /// Expected Result: + /// A passing test case will have the cursor continue tracking on frame 3. /// [Test] public void TestTrackingRetentionLeftRightLeft() @@ -141,12 +141,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, pressing the other key on the slider head, then releasing the former pressed key - /// should result in continued tracking. - /// Frame 1 (prior to slider): Left Click - /// Frame 2 (on slider head): Left & Right Click - /// Frame 3 (tracking slider body): Right Click - /// A passing test case will have the cursor continue to track after frame 3. + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the key that was held down before the slider started. + /// Expected Result: + /// A passing test case will have the cursor continue tracking on frame 3 /// [Test] public void TestTrackingLeftBeforeSliderToRight() @@ -168,12 +168,11 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider and holding the slider throughout the body should result in tracking, but a miss on the slider head. - /// Only one frame is required: - /// Frame 1: Left Click - /// In a successful test case: - /// The head of the slider should be judged as a miss. - /// The slider end should be judged as a meh. + /// Scenario: + /// - Press a key before a slider starts + /// - Hold the key down throughout the slider without pressing any other buttons. + /// Expected Result: + /// A passing test case will have the cursor track the slider, but miss the slider head. /// [Test] public void TestTrackingPreclicked() @@ -193,11 +192,13 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Hitting a slider head, leaving the slider, then coming back into the slider with the same button to track it should re-start tracking. - /// Only one frame is required: - /// Frame 1: Left Click - /// In a successful test case: - /// The last tick of the slider should be judged as a great. + /// Scenario: + /// - Press a key before a slider starts + /// - Hold the key down after the slider starts + /// - Move the cursor away from the slider body + /// - Move the cursor back onto the body + /// Expected Result: + /// A passing test case will have the cursor track the slider, miss the head, miss the ticks where its outside of the body, and resume tracking when the cursor returns. /// [Test] public void TestTrackingReturnMidSlider() @@ -221,10 +222,14 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, hitting a slider head, leaving the slider, then coming back into the slider to track it should NOT start retracking - /// This is current stable behavior. - /// In a successful test case: - /// The last tick of the slider should be judged as a miss. + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the key used to hit the slider head + /// - While holding the first key, move the cursor away from the slider body + /// - Still holding the first key, move the cursor back to the slider body + /// Expected Result: + /// A passing test case will have the slider not track despite having the cursor return to the slider body. /// [Test] public void TestTrackingReturnMidSliderKeyDownBefore() @@ -249,9 +254,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Halfway into a slider outside of the slider, then starting to hover the slider afterwards should result in tracking - /// In a successful test case: - /// The last tick of the slider should be judged as a great. + /// Scenario: + /// - Wait for the slider to reach a mid-point + /// - Press a key away from the slider body + /// - While holding down the key, move into the slider body + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. /// [Test] public void TestTrackingMidSlider() @@ -274,13 +282,16 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, clicking another key after the slider, holding both of them and - /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking - /// In a successful test case: - /// The last tick of the slider should be judged as a great. + /// Scenario: + /// - Press a key before the slider starts + /// - Press another key on the slider head while holding the original key + /// - Move out of the slider body while releasing the two pressed keys + /// - Move back into the slider body while pressing any key. + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. /// [Test] - public void TestTrackingPressBeforeSliderClickingOtherKeyLeavingSliderReleaseThenTrackOriginal() + public void TestTrackingReleasedKeys() { AddStep("Mid-slider new tracking acquisition", () => { @@ -300,13 +311,17 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Pressing a key before a slider, clicking another key after the slider, holding both of them and - /// leaving tracking, then releasing both keys, then pressing the originally pressed key should start tracking - /// In a successful test case: - /// The last tick of the slider should be judged as a great. + /// Scenario: + /// - Press a key on the slider head + /// - While holding the key, move outside of the slider body with the cursor + /// - Release the key while outside of the slider body + /// - Press the key again while outside of the slider body + /// - Move back into the slider body while holding the pressed key + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. /// [Test] - public void TestClickingBeforeLeavingSliderReleasingClickingAgainThenTracking() + public void TestTrackingReleasedValidKey() { AddStep("Mid-slider new tracking acquisition", () => { From a2613e6279437f0d40a09c24cba8bd39d1d641d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Jan 2019 10:47:11 +0900 Subject: [PATCH 14/54] Formatting and constants --- .../TestCaseSliderInput.cs | 114 +++++++++--------- 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index c3df821e1c..a591d260a6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -59,13 +59,20 @@ namespace osu.Game.Rulesets.Osu.Tests base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); } + private const double time_before_slider = 250; + private const double time_slider_start = 1500; + private const double time_during_slide_1 = 2500; + private const double time_during_slide_2 = 3000; + private const double time_during_slide_3 = 3500; + private const double time_during_slide_4 = 4000; + /// /// Scenario: /// - Press a key before a slider starts /// - Press the other key on the slider head timed correctly while holding the original key /// - Release the latter pressed key /// Expected Result: - /// A passing test case will have the cursor lose tracking on frame 3. + /// A passing test case will have the cursor lose tracking on replay frame 3. /// [Test] public void TestLeftBeforeSliderThenRight() @@ -74,12 +81,12 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 1"); @@ -92,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// - Press the other key in the middle of the slider while holding the original key /// - Release the original key used to hit the slider /// Expected Result: - /// A passing test case will have the cursor continue tracking on frame 3. + /// A passing test case will have the cursor continue tracking on replay frame 3. /// [Test] public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() @@ -101,12 +108,12 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 2500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = 3500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 2"); @@ -119,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// - Press the other key in the middle of the slider while holding the original key /// - Release the new key that was pressed second /// Expected Result: - /// A passing test case will have the cursor continue tracking on frame 3. + /// A passing test case will have the cursor continue tracking on replay frame 3. /// [Test] public void TestTrackingRetentionLeftRightLeft() @@ -128,12 +135,12 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 3"); @@ -146,7 +153,7 @@ namespace osu.Game.Rulesets.Osu.Tests /// - Press the other key on the slider head timed correctly while holding the original key /// - Release the key that was held down before the slider started. /// Expected Result: - /// A passing test case will have the cursor continue tracking on frame 3 + /// A passing test case will have the cursor continue tracking on replay frame 3 /// [Test] public void TestTrackingLeftBeforeSliderToRight() @@ -155,12 +162,12 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = 2500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 4"); @@ -181,10 +188,10 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 5"); @@ -207,14 +214,14 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = 2000}, - new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = 2500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3000}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 6"); @@ -238,15 +245,15 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 2000}, - new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = 2500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3000}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 7"); @@ -268,13 +275,13 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = 2000}, - new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = 2500}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3000}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 8"); @@ -297,13 +304,13 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 250}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(100, 100), Time = 1750}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 9"); @@ -327,14 +334,14 @@ namespace osu.Game.Rulesets.Osu.Tests { var frames = new List { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 1500}, - new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = 2500}, - new OsuReplayFrame { Position = new Vector2(100, 100), Time = 2750}, - new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = 3000}, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = 3500}, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }; - performStaticInputTest(frames); + performTest(frames); }); AddUntilStep(() => allJudgedFired, "Wait for test 10"); @@ -366,11 +373,11 @@ namespace osu.Game.Rulesets.Osu.Tests return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; } - private void performStaticInputTest(List frames) + private void performTest(List frames) { var slider = new Slider { - StartTime = 1500, + StartTime = time_slider_start, Position = new Vector2(0, 0), Path = new SliderPath(PathType.PerfectCurve, new[] { @@ -408,7 +415,6 @@ namespace osu.Game.Rulesets.Osu.Tests Child = player; player.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); - player.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; } From 927b0375fd068a8b64966a94e9a94c7cfd4ecf81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Jan 2019 10:49:25 +0900 Subject: [PATCH 15/54] Use schedule for *all* setup --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index a591d260a6..0048d08d1e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -42,11 +42,10 @@ namespace osu.Game.Rulesets.Osu.Tests }; [SetUp] - public void Setup() + public void Setup() => Schedule(() => { - Schedule(() => { allJudgedFired = false; }); + allJudgedFired = false; judgementResults = new List(); - } private readonly Container content; protected override Container Content => content; From f79ce6a7f194b7a11b6fa4fbb89b03914b09d897 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Jan 2019 10:49:54 +0900 Subject: [PATCH 16/54] Remove unnecessary content override --- .../TestCaseSliderInput.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 0048d08d1e..67b1f634cb 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Replays; @@ -46,18 +44,11 @@ namespace osu.Game.Rulesets.Osu.Tests { allJudgedFired = false; judgementResults = new List(); - - private readonly Container content; - protected override Container Content => content; + }); private List judgementResults; private bool allJudgedFired; - public TestCaseSliderInput() - { - base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); - } - private const double time_before_slider = 250; private const double time_slider_start = 1500; private const double time_during_slide_1 = 2500; @@ -411,7 +402,10 @@ namespace osu.Game.Rulesets.Osu.Tests AllowResults = false }; - Child = player; + Child = new OsuInputManager(new RulesetInfo { ID = 0 }) + { + Child = player + }; player.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); player.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; From 147a9c244038c649168d417c3ff6235ef7edbd9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Jan 2019 10:56:04 +0900 Subject: [PATCH 17/54] Fix dynamic compilation failing --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 67b1f634cb..5232fbfa7f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -30,13 +30,18 @@ namespace osu.Game.Rulesets.Osu.Tests public override IReadOnlyList RequiredTypes => new[] { typeof(Slider), + typeof(SliderCircle), typeof(SliderBall), typeof(SliderBody), typeof(SliderTick), + typeof(SliderTailCircle), typeof(DrawableSlider), + typeof(SnakingSliderBody), typeof(DrawableSliderTick), typeof(DrawableRepeatPoint), - typeof(DrawableOsuHitObject) + typeof(DrawableOsuHitObject), + typeof(DrawableSliderHead), + typeof(DrawableSliderTail) }; [SetUp] From 8e09c66cbb6fd21758079c9948e431e0f12c058b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 14:42:09 +0900 Subject: [PATCH 18/54] Split out testcase player for use in slider input tests --- .../TestCaseSliderInput.cs | 2 +- osu.Game/Tests/Visual/TestCasePlayer.cs | 10 +--------- osu.Game/Tests/Visual/TestCasePlayerBase.cs | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Tests/Visual/TestCasePlayerBase.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 5232fbfa7f..cc97947dc3 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -25,7 +25,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSliderInput : OsuTestCase + public class TestCaseSliderInput : TestCasePlayerBase { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 60b630513a..34f0bfab8c 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public abstract class TestCasePlayer : ScreenTestCase + public abstract class TestCasePlayer : TestCasePlayerBase { private readonly Ruleset ruleset; @@ -121,14 +121,6 @@ namespace osu.Game.Tests.Visual return player; } - protected override void Update() - { - base.Update(); - - // note that this will override any mod rate application - Beatmap.Value.Track.Rate = Clock.Rate; - } - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player { AllowPause = false, diff --git a/osu.Game/Tests/Visual/TestCasePlayerBase.cs b/osu.Game/Tests/Visual/TestCasePlayerBase.cs new file mode 100644 index 0000000000..cf5f733d20 --- /dev/null +++ b/osu.Game/Tests/Visual/TestCasePlayerBase.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2019 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tests.Visual +{ + public class TestCasePlayerBase : ScreenTestCase + { + protected override void Update() + { + base.Update(); + + // note that this will override any mod rate application + Beatmap.Value.Track.Rate = Clock.Rate; + } + } +} From 1fdb8ca37acc5c5567244279154b81efc6ec785d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 14:46:36 +0900 Subject: [PATCH 19/54] Fix auto-generated lisence header --- osu.Game/Tests/Visual/TestCasePlayerBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/TestCasePlayerBase.cs b/osu.Game/Tests/Visual/TestCasePlayerBase.cs index cf5f733d20..99489b2933 100644 --- a/osu.Game/Tests/Visual/TestCasePlayerBase.cs +++ b/osu.Game/Tests/Visual/TestCasePlayerBase.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2019 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Tests.Visual From 8b7cc2eaa28993ce8da17de284e3a25cc7b7ebac Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 15:01:45 +0900 Subject: [PATCH 20/54] Re-order tests --- .../TestCaseSliderInput.cs | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index cc97947dc3..a7fc705b30 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -61,33 +61,6 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_during_slide_3 = 3500; private const double time_during_slide_4 = 4000; - /// - /// Scenario: - /// - Press a key before a slider starts - /// - Press the other key on the slider head timed correctly while holding the original key - /// - Release the latter pressed key - /// Expected Result: - /// A passing test case will have the cursor lose tracking on replay frame 3. - /// - [Test] - public void TestLeftBeforeSliderThenRight() - { - AddStep("Invalid key transfer test", () => - { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - }; - - performTest(frames); - }); - - AddUntilStep(() => allJudgedFired, "Wait for test 1"); - AddAssert("Tracking lost", assertMehJudge); - } - /// /// Scenario: /// - Press a key on the slider head timed correctly @@ -111,10 +84,37 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 2"); + AddUntilStep(() => allJudgedFired, "Wait for test 1"); AddAssert("Tracking retained", assertGreatJudge); } + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the latter pressed key + /// Expected Result: + /// A passing test case will have the cursor lose tracking on replay frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRight() + { + AddStep("Invalid key transfer test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + }; + + performTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 2"); + AddAssert("Tracking lost", assertMehJudge); + } + /// /// Scenario: /// - Press a key on the slider head timed correctly From 837b4f4f6cd50222a367216f931173ef2b12f2ca Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 15:52:20 +0900 Subject: [PATCH 21/54] Fix input tests not using async loads --- .../TestCaseSliderInput.cs | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index a7fc705b30..9ce1599fb4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -61,33 +61,6 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_during_slide_3 = 3500; private const double time_during_slide_4 = 4000; - /// - /// Scenario: - /// - Press a key on the slider head timed correctly - /// - Press the other key in the middle of the slider while holding the original key - /// - Release the original key used to hit the slider - /// Expected Result: - /// A passing test case will have the cursor continue tracking on replay frame 3. - /// - [Test] - public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() - { - AddStep("Left to both to right test", () => - { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, - }; - - performTest(frames); - }); - - AddUntilStep(() => allJudgedFired, "Wait for test 1"); - AddAssert("Tracking retained", assertGreatJudge); - } - /// /// Scenario: /// - Press a key before a slider starts @@ -115,6 +88,33 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("Tracking lost", assertMehJudge); } + /// + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the original key used to hit the slider + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() + { + AddStep("Left to both to right test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }; + + performTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 1"); + AddAssert("Tracking retained", assertGreatJudge); + } + /// /// Scenario: /// - Press a key on the slider head timed correctly @@ -407,13 +407,13 @@ namespace osu.Game.Rulesets.Osu.Tests AllowResults = false }; - Child = new OsuInputManager(new RulesetInfo { ID = 0 }) + LoadComponentAsync(player, p => { - Child = player - }; + Child = p; - player.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); - player.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; + p.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); + p.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; + }); } private class ScoreAccessibleReplayPlayer : ReplayPlayer From d413d1ef1b4022d2d5fda1f6ce52ecce0b6294b9 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 16:07:40 +0900 Subject: [PATCH 22/54] re-order tests again --- .../TestCaseSliderInput.cs | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 9ce1599fb4..6e5afe4774 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -61,33 +61,6 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_during_slide_3 = 3500; private const double time_during_slide_4 = 4000; - /// - /// Scenario: - /// - Press a key before a slider starts - /// - Press the other key on the slider head timed correctly while holding the original key - /// - Release the latter pressed key - /// Expected Result: - /// A passing test case will have the cursor lose tracking on replay frame 3. - /// - [Test] - public void TestLeftBeforeSliderThenRight() - { - AddStep("Invalid key transfer test", () => - { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - }; - - performTest(frames); - }); - - AddUntilStep(() => allJudgedFired, "Wait for test 2"); - AddAssert("Tracking lost", assertMehJudge); - } - /// /// Scenario: /// - Press a key on the slider head timed correctly @@ -115,6 +88,33 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("Tracking retained", assertGreatJudge); } + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the latter pressed key + /// Expected Result: + /// A passing test case will have the cursor lose tracking on replay frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRight() + { + AddStep("Invalid key transfer test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + }; + + performTest(frames); + }); + + AddUntilStep(() => allJudgedFired, "Wait for test 2"); + AddAssert("Tracking lost", assertMehJudge); + } + /// /// Scenario: /// - Press a key on the slider head timed correctly @@ -410,7 +410,6 @@ namespace osu.Game.Rulesets.Osu.Tests LoadComponentAsync(player, p => { Child = p; - p.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); p.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; }); From 1f93fde2460cd9a53c402dfb1a836e735bafeb1a Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 16:56:42 +0900 Subject: [PATCH 23/54] Check for beatmap load state before performing test --- .../TestCaseSliderInput.cs | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 6e5afe4774..48b563f45f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Osu.Tests { allJudgedFired = false; judgementResults = new List(); + loadBeatmap(); }); private List judgementResults; @@ -72,6 +73,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Left to both to right test", () => { var frames = new List @@ -99,6 +101,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestLeftBeforeSliderThenRight() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Invalid key transfer test", () => { var frames = new List @@ -126,6 +129,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingRetentionLeftRightLeft() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Tracking retention test", () => { var frames = new List @@ -153,6 +157,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingLeftBeforeSliderToRight() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Tracking retention test", () => { var frames = new List @@ -179,6 +184,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingPreclicked() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Tracking retention test", () => { var frames = new List @@ -205,6 +211,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReturnMidSlider() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-sldier tracking re-acquisition", () => { var frames = new List @@ -236,6 +243,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReturnMidSliderKeyDownBefore() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Key held down before slider, mid-slider tracking re-acquisition", () => { var frames = new List @@ -266,6 +274,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingMidSlider() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-slider new tracking acquisition", () => { var frames = new List @@ -295,6 +304,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReleasedKeys() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-slider new tracking acquisition", () => { var frames = new List @@ -325,6 +335,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReleasedValidKey() { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-slider new tracking acquisition", () => { var frames = new List @@ -368,7 +379,7 @@ namespace osu.Game.Rulesets.Osu.Tests return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; } - private void performTest(List frames) + private void loadBeatmap() { var slider = new Slider { @@ -381,11 +392,6 @@ namespace osu.Game.Rulesets.Osu.Tests }, 25), }; - // Empty frame to be added as a workaround for first frame behavior. - // If an input exists on the first frame, the input would apply to the entire intro lead-in - // Likely requires some discussion regarding how first frame inputs should be handled. - frames.Insert(0, new OsuReplayFrame { Position = slider.Position, Time = 0, Actions = new List() }); - Beatmap.Value = new TestWorkingBeatmap(new Beatmap { HitObjects = { slider }, @@ -399,6 +405,14 @@ namespace osu.Game.Rulesets.Osu.Tests Ruleset = new OsuRuleset().RulesetInfo }, }); + } + + private void performTest(List frames) + { + // Empty frame to be added as a workaround for first frame behavior. + // If an input exists on the first frame, the input would apply to the entire intro lead-in + // Likely requires some discussion regarding how first frame inputs should be handled. + frames.Insert(0, new OsuReplayFrame { Position = new Vector2(0, 0), Time = 0, Actions = new List() }); var player = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) { From 4353002fde5ea34498b685d2b8f03cfdc24ef8a7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 18:24:13 +0900 Subject: [PATCH 24/54] Fix dynamic compilation, use slidertick judgements --- .../TestCaseSliderInput.cs | 87 +++++++++---------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 48b563f45f..f1f7b076fd 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -29,19 +29,13 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => new[] { - typeof(Slider), - typeof(SliderCircle), typeof(SliderBall), - typeof(SliderBody), - typeof(SliderTick), - typeof(SliderTailCircle), typeof(DrawableSlider), - typeof(SnakingSliderBody), typeof(DrawableSliderTick), typeof(DrawableRepeatPoint), typeof(DrawableOsuHitObject), typeof(DrawableSliderHead), - typeof(DrawableSliderTail) + typeof(DrawableSliderTail), }; [SetUp] @@ -49,9 +43,14 @@ namespace osu.Game.Rulesets.Osu.Tests { allJudgedFired = false; judgementResults = new List(); - loadBeatmap(); }); + public TestCaseSliderInput() + { + loadBeatmap(); + } + + private List judgementResults; private bool allJudgedFired; @@ -62,34 +61,6 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_during_slide_3 = 3500; private const double time_during_slide_4 = 4000; - /// - /// Scenario: - /// - Press a key on the slider head timed correctly - /// - Press the other key in the middle of the slider while holding the original key - /// - Release the original key used to hit the slider - /// Expected Result: - /// A passing test case will have the cursor continue tracking on replay frame 3. - /// - [Test] - public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() - { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); - AddStep("Left to both to right test", () => - { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, - }; - - performTest(frames); - }); - - AddUntilStep(() => allJudgedFired, "Wait for test 1"); - AddAssert("Tracking retained", assertGreatJudge); - } - /// /// Scenario: /// - Press a key before a slider starts @@ -114,8 +85,36 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); + AddUntilStep(() => allJudgedFired, "Wait for test 1"); + AddAssert("Tracking lost", assertMidSliderJudgementFail); + } + + /// + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the original key used to hit the slider + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() + { + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); + AddStep("Left to both to right test", () => + { + var frames = new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }; + + performTest(frames); + }); + AddUntilStep(() => allJudgedFired, "Wait for test 2"); - AddAssert("Tracking lost", assertMehJudge); + AddAssert("Tracking retained", assertGreatJudge); } /// @@ -196,7 +195,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); AddUntilStep(() => allJudgedFired, "Wait for test 5"); - AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailMeh); + AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailTracked); } /// @@ -292,6 +291,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("Tracking acquired", assertMidSliderJudgements); } + /// /// Scenario: /// - Press a key before the slider starts @@ -354,19 +354,14 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("Tracking acquired", assertMidSliderJudgements); } - private bool assertMehJudge() - { - return judgementResults.Last().Type == HitResult.Meh; - } - private bool assertGreatJudge() { return judgementResults.Last().Type == HitResult.Great; } - private bool assertHeadMissTailMeh() + private bool assertHeadMissTailTracked() { - return judgementResults.Last().Type == HitResult.Meh && judgementResults.First().Type == HitResult.Miss; + return judgementResults[judgementResults.Count - 2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; } private bool assertMidSliderJudgements() @@ -379,6 +374,7 @@ namespace osu.Game.Rulesets.Osu.Tests return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; } + private void loadBeatmap() { var slider = new Slider @@ -392,6 +388,7 @@ namespace osu.Game.Rulesets.Osu.Tests }, 25), }; + Beatmap.Value = new TestWorkingBeatmap(new Beatmap { HitObjects = { slider }, From ebcc041ac835096dc8a51ba4405a1597bf03ad36 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 18:27:16 +0900 Subject: [PATCH 25/54] Nuke whitespace --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index f1f7b076fd..c1bb1c4cb8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -49,11 +49,9 @@ namespace osu.Game.Rulesets.Osu.Tests { loadBeatmap(); } - - private List judgementResults; private bool allJudgedFired; - + private const double time_before_slider = 250; private const double time_slider_start = 1500; private const double time_during_slide_1 = 2500; @@ -374,7 +372,6 @@ namespace osu.Game.Rulesets.Osu.Tests return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; } - private void loadBeatmap() { var slider = new Slider @@ -388,7 +385,6 @@ namespace osu.Game.Rulesets.Osu.Tests }, 25), }; - Beatmap.Value = new TestWorkingBeatmap(new Beatmap { HitObjects = { slider }, From 01c4671fc8d9eb84709db464480821b5e314f578 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 18:45:43 +0900 Subject: [PATCH 26/54] phantom whitespace --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index c1bb1c4cb8..c1309fb6c6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -49,9 +49,7 @@ namespace osu.Game.Rulesets.Osu.Tests { loadBeatmap(); } - private List judgementResults; - private bool allJudgedFired; - + private const double time_before_slider = 250; private const double time_slider_start = 1500; private const double time_during_slide_1 = 2500; @@ -59,6 +57,9 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_during_slide_3 = 3500; private const double time_during_slide_4 = 4000; + private List judgementResults; + private bool allJudgedFired; + /// /// Scenario: /// - Press a key before a slider starts From da922c603da63e742e4841bf9c6d43e4347d55c6 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 18:51:48 +0900 Subject: [PATCH 27/54] Nuke whitespace again --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index c1309fb6c6..db10a1b069 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -59,7 +59,6 @@ namespace osu.Game.Rulesets.Osu.Tests private List judgementResults; private bool allJudgedFired; - /// /// Scenario: /// - Press a key before a slider starts From f5aaf13363f7797ae190c43c128168c8a5f3c113 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 20:07:22 +0900 Subject: [PATCH 28/54] Move all beatmap initialization logic into constructor --- .../TestCaseSliderInput.cs | 53 +++++++++---------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index db10a1b069..073f327f9f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -47,7 +47,30 @@ namespace osu.Game.Rulesets.Osu.Tests public TestCaseSliderInput() { - loadBeatmap(); + var slider = new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + }; + + Beatmap.Value = new TestWorkingBeatmap(new Beatmap + { + HitObjects = { slider }, + ControlPointInfo = + { + DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, + Ruleset = new OsuRuleset().RulesetInfo + }, + }); } private const double time_before_slider = 250; @@ -372,34 +395,6 @@ namespace osu.Game.Rulesets.Osu.Tests return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; } - private void loadBeatmap() - { - var slider = new Slider - { - StartTime = time_slider_start, - Position = new Vector2(0, 0), - Path = new SliderPath(PathType.PerfectCurve, new[] - { - Vector2.Zero, - new Vector2(25, 0), - }, 25), - }; - - Beatmap.Value = new TestWorkingBeatmap(new Beatmap - { - HitObjects = { slider }, - ControlPointInfo = - { - DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } - }, - BeatmapInfo = - { - BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, - Ruleset = new OsuRuleset().RulesetInfo - }, - }); - } - private void performTest(List frames) { // Empty frame to be added as a workaround for first frame behavior. From d80424b1d61f2eb536da5415cc2e1acf3a41203a Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 24 Jan 2019 20:11:28 +0900 Subject: [PATCH 29/54] Remove load checks and place one in the constructor --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 073f327f9f..43d4648e96 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -71,6 +71,8 @@ namespace osu.Game.Rulesets.Osu.Tests Ruleset = new OsuRuleset().RulesetInfo }, }); + + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); } private const double time_before_slider = 250; @@ -93,7 +95,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestLeftBeforeSliderThenRight() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Invalid key transfer test", () => { var frames = new List @@ -121,7 +122,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Left to both to right test", () => { var frames = new List @@ -149,7 +149,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingRetentionLeftRightLeft() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Tracking retention test", () => { var frames = new List @@ -177,7 +176,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingLeftBeforeSliderToRight() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Tracking retention test", () => { var frames = new List @@ -204,7 +202,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingPreclicked() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Tracking retention test", () => { var frames = new List @@ -231,7 +228,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReturnMidSlider() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-sldier tracking re-acquisition", () => { var frames = new List @@ -263,7 +259,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReturnMidSliderKeyDownBefore() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Key held down before slider, mid-slider tracking re-acquisition", () => { var frames = new List @@ -294,7 +289,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingMidSlider() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-slider new tracking acquisition", () => { var frames = new List @@ -325,7 +319,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReleasedKeys() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-slider new tracking acquisition", () => { var frames = new List @@ -356,7 +349,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReleasedValidKey() { - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); AddStep("Mid-slider new tracking acquisition", () => { var frames = new List From d59ba8cfe9865267b9dc351dfc5d91ba7fadea34 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 25 Jan 2019 00:07:33 +0900 Subject: [PATCH 30/54] Rename base player test class to RateAdjustedBeatmap, refactor input tests --- .../TestCaseSliderInput.cs | 46 +++++++++---------- osu.Game/Tests/Visual/TestCasePlayer.cs | 2 +- ...Base.cs => TestCaseRateAdjustedBeatmap.cs} | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) rename osu.Game/Tests/Visual/{TestCasePlayerBase.cs => TestCaseRateAdjustedBeatmap.cs} (86%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 43d4648e96..aa83e324ca 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -25,7 +25,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSliderInput : TestCasePlayerBase + public class TestCaseSliderInput : TestCaseRateAdjustedBeatmap { public override IReadOnlyList RequiredTypes => new[] { @@ -47,20 +47,18 @@ namespace osu.Game.Rulesets.Osu.Tests public TestCaseSliderInput() { - var slider = new Slider - { - StartTime = time_slider_start, - Position = new Vector2(0, 0), - Path = new SliderPath(PathType.PerfectCurve, new[] - { - Vector2.Zero, - new Vector2(25, 0), - }, 25), - }; - Beatmap.Value = new TestWorkingBeatmap(new Beatmap { - HitObjects = { slider }, + HitObjects = { new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + }}, ControlPointInfo = { DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } @@ -107,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 1"); + waitForJudged(); AddAssert("Tracking lost", assertMidSliderJudgementFail); } @@ -134,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 2"); + waitForJudged(); AddAssert("Tracking retained", assertGreatJudge); } @@ -161,7 +159,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 3"); + waitForJudged(); AddAssert("Tracking retained", assertGreatJudge); } @@ -188,7 +186,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 4"); + waitForJudged(); AddAssert("Tracking retained", assertGreatJudge); } @@ -212,7 +210,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 5"); + waitForJudged(); AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailTracked); } @@ -242,7 +240,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 6"); + waitForJudged(); AddAssert("Tracking re-acquired", assertMidSliderJudgements); } @@ -274,7 +272,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 7"); + waitForJudged(); AddAssert("Tracking lost", assertMidSliderJudgementFail); } @@ -302,7 +300,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 8"); + waitForJudged(); AddAssert("Tracking acquired", assertMidSliderJudgements); } @@ -332,7 +330,7 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 9"); + waitForJudged(); AddAssert("Tracking acquired", assertMidSliderJudgements); } @@ -363,10 +361,12 @@ namespace osu.Game.Rulesets.Osu.Tests performTest(frames); }); - AddUntilStep(() => allJudgedFired, "Wait for test 10"); + waitForJudged(); AddAssert("Tracking acquired", assertMidSliderJudgements); } + private void waitForJudged() => AddUntilStep(() => allJudgedFired, "Wait for all judged"); + private bool assertGreatJudge() { return judgementResults.Last().Type == HitResult.Great; diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 34f0bfab8c..196f501c6f 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public abstract class TestCasePlayer : TestCasePlayerBase + public abstract class TestCasePlayer : TestCaseRateAdjustedBeatmap { private readonly Ruleset ruleset; diff --git a/osu.Game/Tests/Visual/TestCasePlayerBase.cs b/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs similarity index 86% rename from osu.Game/Tests/Visual/TestCasePlayerBase.cs rename to osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs index 99489b2933..affb5f6778 100644 --- a/osu.Game/Tests/Visual/TestCasePlayerBase.cs +++ b/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs @@ -3,7 +3,7 @@ namespace osu.Game.Tests.Visual { - public class TestCasePlayerBase : ScreenTestCase + public class TestCaseRateAdjustedBeatmap : ScreenTestCase { protected override void Update() { From 3495aa645f44b67d4a5b7b95d49b957e050bdb6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Jan 2019 11:11:04 +0900 Subject: [PATCH 31/54] Update headers --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 4 ++-- osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index aa83e324ca..bd81c65caf 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// 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; diff --git a/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs b/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs index affb5f6778..a7fd2885bd 100644 --- a/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs +++ b/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Tests.Visual { From 490fb86f9eca5f43625e816172049c87ced4aa96 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Jan 2019 11:11:40 +0900 Subject: [PATCH 32/54] Make base class abstract and add documentation --- osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs b/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs index a7fd2885bd..4a9dfe2dfa 100644 --- a/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs +++ b/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs @@ -3,7 +3,10 @@ namespace osu.Game.Tests.Visual { - public class TestCaseRateAdjustedBeatmap : ScreenTestCase + /// + /// Test case which adjusts the beatmap's rate to match any speed adjustments in visual tests. + /// + public abstract class TestCaseRateAdjustedBeatmap : ScreenTestCase { protected override void Update() { From 2a544f66eae6e44ecc58aea4a8fe80aca94592e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Jan 2019 11:13:37 +0900 Subject: [PATCH 33/54] Formatting, ordering and simplification --- .../TestCaseSliderInput.cs | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index bd81c65caf..a69c7ed66f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -38,27 +38,33 @@ namespace osu.Game.Rulesets.Osu.Tests typeof(DrawableSliderTail), }; - [SetUp] - public void Setup() => Schedule(() => - { - allJudgedFired = false; - judgementResults = new List(); - }); + private const double time_before_slider = 250; + private const double time_slider_start = 1500; + private const double time_during_slide_1 = 2500; + private const double time_during_slide_2 = 3000; + private const double time_during_slide_3 = 3500; + private const double time_during_slide_4 = 4000; + + private List judgementResults; + private bool allJudgedFired; public TestCaseSliderInput() { Beatmap.Value = new TestWorkingBeatmap(new Beatmap { - HitObjects = { new Slider + HitObjects = { - StartTime = time_slider_start, - Position = new Vector2(0, 0), - Path = new SliderPath(PathType.PerfectCurve, new[] + new Slider { - Vector2.Zero, - new Vector2(25, 0), - }, 25), - }}, + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + } + }, ControlPointInfo = { DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } @@ -73,15 +79,13 @@ namespace osu.Game.Rulesets.Osu.Tests AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); } - private const double time_before_slider = 250; - private const double time_slider_start = 1500; - private const double time_during_slide_1 = 2500; - private const double time_during_slide_2 = 3000; - private const double time_during_slide_3 = 3500; - private const double time_during_slide_4 = 4000; + [SetUp] + public void Setup() => Schedule(() => + { + allJudgedFired = false; + judgementResults = new List(); + }); - private List judgementResults; - private bool allJudgedFired; /// /// Scenario: /// - Press a key before a slider starts @@ -392,16 +396,14 @@ namespace osu.Game.Rulesets.Osu.Tests // Empty frame to be added as a workaround for first frame behavior. // If an input exists on the first frame, the input would apply to the entire intro lead-in // Likely requires some discussion regarding how first frame inputs should be handled. - frames.Insert(0, new OsuReplayFrame { Position = new Vector2(0, 0), Time = 0, Actions = new List() }); + frames.Insert(0, new OsuReplayFrame()); - var player = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) + LoadComponentAsync(new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) { AllowPause = false, AllowLeadIn = false, AllowResults = false - }; - - LoadComponentAsync(player, p => + }, p => { Child = p; p.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); From e9a22a5c5ddad80d74d9e5c755d2b2e7c268bafc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Jan 2019 11:15:31 +0900 Subject: [PATCH 34/54] Not sure what a bm is --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index a69c7ed66f..79fd732013 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Tests }, }); - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait for bm load"); + AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait until beatmap is loaded"); } [SetUp] From 2bd75fd8aebb07236bf19c21a90de3d78eb4e76f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Feb 2019 10:39:39 +0900 Subject: [PATCH 35/54] Fix some huge oversights --- .../TestCaseSliderInput.cs | 205 ++++++------------ 1 file changed, 66 insertions(+), 139 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 79fd732013..71c667f114 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -75,17 +75,8 @@ namespace osu.Game.Rulesets.Osu.Tests Ruleset = new OsuRuleset().RulesetInfo }, }); - - AddUntilStep(() => Beatmap.Value.BeatmapLoaded, "Wait until beatmap is loaded"); } - [SetUp] - public void Setup() => Schedule(() => - { - allJudgedFired = false; - judgementResults = new List(); - }); - /// /// Scenario: /// - Press a key before a slider starts @@ -95,21 +86,15 @@ namespace osu.Game.Rulesets.Osu.Tests /// A passing test case will have the cursor lose tracking on replay frame 3. /// [Test] - public void TestLeftBeforeSliderThenRight() + public void TestInvalidKeyTransfer() { - AddStep("Invalid key transfer test", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, }); - waitForJudged(); AddAssert("Tracking lost", assertMidSliderJudgementFail); } @@ -124,19 +109,13 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() { - AddStep("Left to both to right test", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, }); - waitForJudged(); AddAssert("Tracking retained", assertGreatJudge); } @@ -151,19 +130,13 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingRetentionLeftRightLeft() { - AddStep("Tracking retention test", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, }); - waitForJudged(); AddAssert("Tracking retained", assertGreatJudge); } @@ -178,19 +151,13 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingLeftBeforeSliderToRight() { - AddStep("Tracking retention test", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, }); - waitForJudged(); AddAssert("Tracking retained", assertGreatJudge); } @@ -204,17 +171,11 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingPreclicked() { - AddStep("Tracking retention test", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, }); - waitForJudged(); AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailTracked); } @@ -230,21 +191,15 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReturnMidSlider() { - AddStep("Mid-sldier tracking re-acquisition", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }); - waitForJudged(); AddAssert("Tracking re-acquired", assertMidSliderJudgements); } @@ -261,22 +216,16 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReturnMidSliderKeyDownBefore() { - AddStep("Key held down before slider, mid-slider tracking re-acquisition", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }); - waitForJudged(); AddAssert("Tracking lost", assertMidSliderJudgementFail); } @@ -291,20 +240,14 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingMidSlider() { - AddStep("Mid-slider new tracking acquisition", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }); - waitForJudged(); AddAssert("Tracking acquired", assertMidSliderJudgements); } @@ -319,22 +262,16 @@ namespace osu.Game.Rulesets.Osu.Tests /// A passing test case will have the slider track the cursor after the cursor enters the slider body. /// [Test] - public void TestTrackingReleasedKeys() + public void TestMidSliderTrackingAcquired() { - AddStep("Mid-slider new tracking acquisition", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, }); - waitForJudged(); AddAssert("Tracking acquired", assertMidSliderJudgements); } @@ -351,45 +288,25 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestTrackingReleasedValidKey() { - AddStep("Mid-slider new tracking acquisition", () => + performTest(new List { - var frames = new List - { - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, - new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, - new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_2 }, - new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, - new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, - }; - - performTest(frames); + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, }); - waitForJudged(); AddAssert("Tracking acquired", assertMidSliderJudgements); } - private void waitForJudged() => AddUntilStep(() => allJudgedFired, "Wait for all judged"); + private bool assertGreatJudge() => judgementResults.Last().Type == HitResult.Great; - private bool assertGreatJudge() - { - return judgementResults.Last().Type == HitResult.Great; - } + private bool assertHeadMissTailTracked() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; - private bool assertHeadMissTailTracked() - { - return judgementResults[judgementResults.Count - 2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; - } + private bool assertMidSliderJudgements() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great; - private bool assertMidSliderJudgements() - { - return judgementResults[judgementResults.Count - 2].Type == HitResult.Great; - } - - private bool assertMidSliderJudgementFail() - { - return judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; - } + private bool assertMidSliderJudgementFail() => judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; private void performTest(List frames) { @@ -398,17 +315,27 @@ namespace osu.Game.Rulesets.Osu.Tests // Likely requires some discussion regarding how first frame inputs should be handled. frames.Insert(0, new OsuReplayFrame()); - LoadComponentAsync(new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) { AllowPause = false, AllowLeadIn = false, AllowResults = false - }, p => + }; + + p.OnLoadComplete += _ => { - Child = p; p.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); p.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; + }; + + AddStep("load player", () => LoadScreen(p)); + AddUntilStep(() => p.IsLoaded, "Wait until player is loaded"); + AddStep("reset counts", () => + { + allJudgedFired = false; + judgementResults = new List(); }); + AddUntilStep(() => allJudgedFired, "Wait for all judged"); } private class ScoreAccessibleReplayPlayer : ReplayPlayer From 6b81315009f0de4de47add098efa982cf7b8e4f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Feb 2019 12:06:49 +0900 Subject: [PATCH 36/54] Avoid test frame being the precise time of slider end --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 71c667f114..8217fe7750 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_during_slide_1 = 2500; private const double time_during_slide_2 = 3000; private const double time_during_slide_3 = 3500; - private const double time_during_slide_4 = 4000; + private const double time_during_slide_4 = 3800; private List judgementResults; private bool allJudgedFired; From 39b203375f9b59a957309d4c7c6ad29a05d52a6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Feb 2019 13:58:05 +0900 Subject: [PATCH 37/54] Ensure variable isolation over multiple test runs --- .../TestCaseSliderInput.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 8217fe7750..39dc914406 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -308,6 +308,8 @@ namespace osu.Game.Rulesets.Osu.Tests private bool assertMidSliderJudgementFail() => judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; + private ScoreAccessibleReplayPlayer currentPlayer; + private void performTest(List frames) { // Empty frame to be added as a workaround for first frame behavior. @@ -324,17 +326,23 @@ namespace osu.Game.Rulesets.Osu.Tests p.OnLoadComplete += _ => { - p.ScoreProcessor.NewJudgement += result => judgementResults.Add(result); - p.ScoreProcessor.AllJudged += () => { allJudgedFired = true; }; + p.ScoreProcessor.NewJudgement += result => + { + if (currentPlayer == p) judgementResults.Add(result); + }; + p.ScoreProcessor.AllJudged += () => + { + if (currentPlayer == p) allJudgedFired = true; + }; }; - AddStep("load player", () => LoadScreen(p)); - AddUntilStep(() => p.IsLoaded, "Wait until player is loaded"); - AddStep("reset counts", () => + AddStep("load player", () => { + LoadScreen(currentPlayer = p); allJudgedFired = false; judgementResults = new List(); }); + AddUntilStep(() => p.IsLoaded, "Wait until player is loaded"); AddUntilStep(() => allJudgedFired, "Wait for all judged"); } From 5f792fbacc945f6a5e6e0c7e71aca3896bd1f8e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Feb 2019 14:28:53 +0900 Subject: [PATCH 38/54] Fix tests not running more than once --- .../TestCaseSliderInput.cs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 39dc914406..1e469b7d12 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -317,32 +317,32 @@ namespace osu.Game.Rulesets.Osu.Tests // Likely requires some discussion regarding how first frame inputs should be handled. frames.Insert(0, new OsuReplayFrame()); - var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) - { - AllowPause = false, - AllowLeadIn = false, - AllowResults = false - }; - - p.OnLoadComplete += _ => - { - p.ScoreProcessor.NewJudgement += result => - { - if (currentPlayer == p) judgementResults.Add(result); - }; - p.ScoreProcessor.AllJudged += () => - { - if (currentPlayer == p) allJudgedFired = true; - }; - }; - AddStep("load player", () => { + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false + }; + + p.OnLoadComplete += _ => + { + p.ScoreProcessor.NewJudgement += result => + { + if (currentPlayer == p) judgementResults.Add(result); + }; + p.ScoreProcessor.AllJudged += () => + { + if (currentPlayer == p) allJudgedFired = true; + }; + }; + LoadScreen(currentPlayer = p); allJudgedFired = false; judgementResults = new List(); }); - AddUntilStep(() => p.IsLoaded, "Wait until player is loaded"); + AddUntilStep(() => currentPlayer.IsLoaded, "Wait until player is loaded"); AddUntilStep(() => allJudgedFired, "Wait for all judged"); } From c8778014415eb26f94a4e0720f487364727af79d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Feb 2019 11:30:30 +0900 Subject: [PATCH 39/54] Use game clock as reference --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 1e469b7d12..0f0bc4b134 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -48,8 +48,9 @@ namespace osu.Game.Rulesets.Osu.Tests private List judgementResults; private bool allJudgedFired; - public TestCaseSliderInput() + protected override void LoadComplete() { + base.LoadComplete(); Beatmap.Value = new TestWorkingBeatmap(new Beatmap { HitObjects = @@ -74,7 +75,7 @@ namespace osu.Game.Rulesets.Osu.Tests BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, Ruleset = new OsuRuleset().RulesetInfo }, - }); + }, Clock); } /// From 0c218eb0d5559093e706dcd446412ecf294775df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Feb 2019 21:24:02 +0900 Subject: [PATCH 40/54] Apply new RulesetInputManager logic Run UpdateSubTree twice to ensure correctness --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 37 ++++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 96775ab9c1..3e201e2c0d 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -121,6 +121,8 @@ namespace osu.Game.Rulesets.UI private const int max_catch_up_updates_per_frame = 50; + private const double sixty_frame_time = 1000.0 / 60; + public override bool UpdateSubTree() { requireMoreUpdateLoops = true; @@ -130,25 +132,28 @@ namespace osu.Game.Rulesets.UI while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) { - if (!base.UpdateSubTree()) - return false; + updateClock(); - UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); - - if (isAttached) + //if (Clock.ElapsedFrameTime > sixty_frame_time) { - // When handling replay input, we need to consider the possibility of fast-forwarding, which may cause the clock to be updated - // to a point very far into the future, then playing a frame at that time. In such a case, lifetime MUST be updated before - // input is handled. This is why base.Update is not called from the derived Update when handling replay input, and is instead - // called manually at the correct time here. - base.Update(); + base.UpdateSubTree(); + UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); } + + // When handling replay input, we need to consider the possibility of fast-forwarding, which may cause the clock to be updated + // to a point very far into the future, then playing a frame at that time. In such a case, lifetime MUST be updated before + // input is handled. This is why base.Update is not called from the derived Update when handling replay input, and is instead + // called manually at the correct time here. + base.Update(); + + base.UpdateSubTree(); + UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); } return true; } - protected override void Update() + private void updateClock() { if (parentClock == null) return; @@ -178,12 +183,11 @@ namespace osu.Game.Rulesets.UI // The manual clock time has changed in the above code. The framed clock now needs to be updated // to ensure that the its time is valid for our children before input is processed Clock.ProcessFrame(); + } - if (!isAttached) - { - // For non-replay input handling, this provides equivalent input ordering as if Update was not overridden - base.Update(); - } + protected override void Update() + { + // block update from base.UpdateSubTree() } #endregion @@ -211,6 +215,7 @@ namespace osu.Game.Rulesets.UI return false; break; } + return base.Handle(e); } From acc160042bbfe697fadbd6da5cfb659753750f18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Feb 2019 21:27:41 +0900 Subject: [PATCH 41/54] Move beatmap construction to step --- .../TestCaseSliderInput.cs | 76 +++++++++++-------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 0f0bc4b134..4b1714bc57 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Replays; @@ -17,6 +18,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; @@ -48,36 +50,6 @@ namespace osu.Game.Rulesets.Osu.Tests private List judgementResults; private bool allJudgedFired; - protected override void LoadComplete() - { - base.LoadComplete(); - Beatmap.Value = new TestWorkingBeatmap(new Beatmap - { - HitObjects = - { - new Slider - { - StartTime = time_slider_start, - Position = new Vector2(0, 0), - Path = new SliderPath(PathType.PerfectCurve, new[] - { - Vector2.Zero, - new Vector2(25, 0), - }, 25), - } - }, - ControlPointInfo = - { - DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } - }, - BeatmapInfo = - { - BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, - Ruleset = new OsuRuleset().RulesetInfo - }, - }, Clock); - } - /// /// Scenario: /// - Press a key before a slider starts @@ -276,6 +248,20 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("Tracking acquired", assertMidSliderJudgements); } + [Test] + public void TestMidSliderTrackingAcquiredWithMouseDownOutsideSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + /// /// Scenario: /// - Press a key on the slider head @@ -320,6 +306,32 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("load player", () => { + Beatmap.Value = new TestWorkingBeatmap(new Beatmap + { + HitObjects = + { + new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + } + }, + ControlPointInfo = + { + DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, + Ruleset = new OsuRuleset().RulesetInfo + }, + }, Clock); + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) { AllowPause = false, @@ -343,7 +355,9 @@ namespace osu.Game.Rulesets.Osu.Tests allJudgedFired = false; judgementResults = new List(); }); - AddUntilStep(() => currentPlayer.IsLoaded, "Wait until player is loaded"); + + AddUntilStep(() => Beatmap.Value.Track.CurrentTime == 0, "Beatmap at 0"); + AddUntilStep(() => currentPlayer.IsCurrentScreen(), "Wait until player is loaded"); AddUntilStep(() => allJudgedFired, "Wait for all judged"); } From 7f5780c615155e2788457bba349d78cdfc47ea53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Feb 2019 21:30:47 +0900 Subject: [PATCH 42/54] Simplify SliderBall and fix incorrect key up handling Was not processing timeToAcceptAnyKeyAfter when cursor was outside valid tracking area, but should have been. --- .../Objects/Drawables/Pieces/SliderBall.cs | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index a8ee4c42fd..609236311b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -125,6 +125,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return base.OnMouseMove(e); } + public bool OnReleased(OsuAction action) => false; + public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { // Consider the case of rewinding - children's transforms are handled internally, so propagating down @@ -148,8 +150,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime && lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value); - /// /// If the cursor moves out of the ball's radius we still need to be able to receive positional updates to stop tracking. /// @@ -183,26 +183,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces if (headCircleHitAction == null) timeToAcceptAnyKeyAfter = null; - if (canCurrentlyTrack) + var actions = drawableSlider?.OsuActionInputManager?.PressedActions; + + // if the head circle was hit with a specific key, tracking should only occur while that key is pressed. + if (headCircleHitAction != null && timeToAcceptAnyKeyAfter == null) { - var pressed = drawableSlider?.OsuActionInputManager?.PressedActions; + var otherKey = headCircleHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton; - // if the head circle was hit with a specific key, tracking should only occur while that key is pressed. - if (headCircleHitAction != null && timeToAcceptAnyKeyAfter == null) - { - var otherKey = headCircleHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton; - - // we can return to accepting all keys if the initial head circle key is the *only* key pressed, or all keys have been released. - if (!pressed.Contains(otherKey)) - timeToAcceptAnyKeyAfter = Time.Current; - } - - Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(isValidTrackingAction) ?? false; - } - else - { - Tracking = false; + // we can return to accepting all keys if the initial head circle key is the *only* key pressed, or all keys have been released. + if (actions?.Contains(otherKey) != true) + timeToAcceptAnyKeyAfter = Time.Current; } + + Tracking = + // in valid time range + Time.Current >= slider.StartTime && Time.Current < slider.EndTime && + // in valid position range + lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && + // valid action + (actions?.Any(isValidTrackingAction) ?? false); } /// From 97d324ab116de2448c219d43d0b8999fa9f16b4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Feb 2019 21:42:15 +0900 Subject: [PATCH 43/54] Remove unnecessary using --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 4b1714bc57..f0dfd3b6e9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; From 6d3c0e31919df45454700e40879555b2b65b87bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Feb 2019 20:57:08 +0900 Subject: [PATCH 44/54] Holy sheet --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 54 ++++++++++++++------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 3e201e2c0d..a7afcbe0e0 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.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.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -160,29 +161,46 @@ namespace osu.Game.Rulesets.UI clock.Rate = parentClock.Rate; clock.IsRunning = parentClock.IsRunning; - if (!isAttached) - { - clock.CurrentTime = parentClock.CurrentTime; - } - else - { - double? newTime = replayInputHandler.SetFrameFromTime(parentClock.CurrentTime); + var newProposedTime = parentClock.CurrentTime; - if (newTime == null) + try + { + if (Math.Abs(clock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) { - // we shouldn't execute for this time value. probably waiting on more replay data. - validState = false; - return; + newProposedTime = clock.Rate > 0 + ? Math.Min(newProposedTime, clock.CurrentTime + sixty_frame_time) + : Math.Max(newProposedTime, clock.CurrentTime - sixty_frame_time); } - clock.CurrentTime = newTime.Value; + if (!isAttached) + { + clock.CurrentTime = newProposedTime; + } + else + { + double? newTime = replayInputHandler.SetFrameFromTime(newProposedTime); + + if (newTime == null) + { + // we shouldn't execute for this time value. probably waiting on more replay data. + validState = false; + + requireMoreUpdateLoops = true; + clock.CurrentTime = newProposedTime; + return; + } + + clock.CurrentTime = newTime.Value; + } + + requireMoreUpdateLoops = clock.CurrentTime != parentClock.CurrentTime; + } + finally + { + // The manual clock time has changed in the above code. The framed clock now needs to be updated + // to ensure that the its time is valid for our children before input is processed + Clock.ProcessFrame(); } - - requireMoreUpdateLoops = clock.CurrentTime != parentClock.CurrentTime; - - // The manual clock time has changed in the above code. The framed clock now needs to be updated - // to ensure that the its time is valid for our children before input is processed - Clock.ProcessFrame(); } protected override void Update() From 90cae0a69c0f0b595b6e8d500abe00bf2c11ad13 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Feb 2019 15:48:34 +0900 Subject: [PATCH 45/54] Simplify RulesetInputManager further --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index a7afcbe0e0..0065f195fc 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -135,20 +135,11 @@ namespace osu.Game.Rulesets.UI { updateClock(); - //if (Clock.ElapsedFrameTime > sixty_frame_time) + if (validState) { base.UpdateSubTree(); UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); } - - // When handling replay input, we need to consider the possibility of fast-forwarding, which may cause the clock to be updated - // to a point very far into the future, then playing a frame at that time. In such a case, lifetime MUST be updated before - // input is handled. This is why base.Update is not called from the derived Update when handling replay input, and is instead - // called manually at the correct time here. - base.Update(); - - base.UpdateSubTree(); - UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); } return true; @@ -203,11 +194,6 @@ namespace osu.Game.Rulesets.UI } } - protected override void Update() - { - // block update from base.UpdateSubTree() - } - #endregion #region Setting application (disables etc.) From 69b9de5acde6b45a75d0633cd4947121437afe86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Feb 2019 21:13:53 +0900 Subject: [PATCH 46/54] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5e670c7391..f464dafd3f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 600cd271aa..bf38335e0c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 287870f1e14246f787648eabf3508afac14124e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Feb 2019 23:35:18 +0900 Subject: [PATCH 47/54] Remove limitation stopping search updates when no query present in direct Closes #4310. --- osu.Game/Overlays/DirectOverlay.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index ef1daf7e99..d3881b6ef8 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -273,9 +273,6 @@ namespace osu.Game.Overlays if (api == null) return; - if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery.Value == string.Empty)) - return; - previewTrackManager.StopAnyPlaying(this); getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty, From d06f38b3f3c9fb1a949dcc502e1b186776d0d2be Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 Feb 2019 15:57:07 +0900 Subject: [PATCH 48/54] Cleanup --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 1 - osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index f0dfd3b6e9..e1d6f67263 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -223,7 +223,6 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("Tracking acquired", assertMidSliderJudgements); } - /// /// Scenario: /// - Press a key before the slider starts diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 609236311b..afa7f22140 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -125,8 +125,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return base.OnMouseMove(e); } - public bool OnReleased(OsuAction action) => false; - public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { // Consider the case of rewinding - children's transforms are handled internally, so propagating down From 7fde21b51af4229b12ecff5c5e06b2e310a6c699 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 Feb 2019 16:09:09 +0900 Subject: [PATCH 49/54] Rename testcase --- osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs | 2 +- ...aseRateAdjustedBeatmap.cs => RateAdjustedBeatmapTestCase.cs} | 2 +- osu.Game/Tests/Visual/TestCasePlayer.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Tests/Visual/{TestCaseRateAdjustedBeatmap.cs => RateAdjustedBeatmapTestCase.cs} (89%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index e1d6f67263..57effe01f1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -26,7 +26,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSliderInput : TestCaseRateAdjustedBeatmap + public class TestCaseSliderInput : RateAdjustedBeatmapTestCase { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs similarity index 89% rename from osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs rename to osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs index 4a9dfe2dfa..14b4af1e7d 100644 --- a/osu.Game/Tests/Visual/TestCaseRateAdjustedBeatmap.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs @@ -6,7 +6,7 @@ namespace osu.Game.Tests.Visual /// /// Test case which adjusts the beatmap's rate to match any speed adjustments in visual tests. /// - public abstract class TestCaseRateAdjustedBeatmap : ScreenTestCase + public abstract class RateAdjustedBeatmapTestCase : ScreenTestCase { protected override void Update() { diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 196f501c6f..5ff798c40d 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public abstract class TestCasePlayer : TestCaseRateAdjustedBeatmap + public abstract class TestCasePlayer : RateAdjustedBeatmapTestCase { private readonly Ruleset ruleset; From ad1bce35856d29a74b3a382457e91df5552ee694 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 25 Feb 2019 18:40:19 +0900 Subject: [PATCH 50/54] Fix song select backround not being exited in time --- osu.Game/Screens/Select/SongSelect.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3be4dd8c0b..fd58b1db5b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -285,7 +285,7 @@ namespace osu.Game.Screens.Select public void Edit(BeatmapInfo beatmap = null) { - Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap ?? beatmapNoDebounce); + Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap ?? beatmapNoDebounce); this.Push(new Editor()); } @@ -510,14 +510,17 @@ namespace osu.Game.Screens.Select public override bool OnExiting(IScreen next) { + if (base.OnExiting(next)) + return true; + + Logger.Log("Exiting song select!"); + if (ModSelect.State == Visibility.Visible) { ModSelect.Hide(); return true; } - FinaliseSelection(performStartAction: false); - beatmapInfoWedge.State = Visibility.Hidden; this.FadeOut(100); @@ -530,7 +533,7 @@ namespace osu.Game.Screens.Select SelectedMods.UnbindAll(); Beatmap.Value.Mods.Value = new Mod[] { }; - return base.OnExiting(next); + return false; } protected override void Dispose(bool isDisposing) From 59ad470eed8eff14a47e75d314cc7fd1d60f701e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 25 Feb 2019 18:41:13 +0900 Subject: [PATCH 51/54] Clean up test code --- osu.Game/Screens/Select/SongSelect.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index fd58b1db5b..68ca89a012 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -513,8 +513,6 @@ namespace osu.Game.Screens.Select if (base.OnExiting(next)) return true; - Logger.Log("Exiting song select!"); - if (ModSelect.State == Visibility.Visible) { ModSelect.Hide(); From a4e119786f270593b3d47e953d7464fa3e2bb650 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Feb 2019 19:19:28 +0900 Subject: [PATCH 52/54] Fix some weird formatting --- osu.Game/Screens/Menu/MainMenu.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index d6e3d378e0..6e1afb6b68 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -54,10 +54,10 @@ namespace osu.Game.Screens.Menu buttons = new ButtonSystem { OnChart = delegate { this.Push(new ChartListing()); }, - OnDirect = delegate {this.Push(new OnlineListing()); }, - OnEdit = delegate {this.Push(new Editor()); }, + OnDirect = delegate { this.Push(new OnlineListing()); }, + OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, - OnMulti = delegate {this.Push(new Multiplayer()); }, + OnMulti = delegate { this.Push(new Multiplayer()); }, OnExit = this.Exit, } } @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Menu public void LoadToSolo() => Schedule(onSolo); - private void onSolo() =>this.Push(consumeSongSelect()); + private void onSolo() => this.Push(consumeSongSelect()); private Screen consumeSongSelect() { @@ -184,7 +184,7 @@ namespace osu.Game.Screens.Menu { base.OnResuming(last); - ((BackgroundScreenDefault)Background).Next(); + (Background as BackgroundScreenDefault)?.Next(); //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); @@ -201,7 +201,7 @@ namespace osu.Game.Screens.Menu { if (!e.Repeat && e.ControlPressed && e.ShiftPressed && e.Key == Key.D) { - this.Push(new Drawings()); + this.Push(new Drawings()); return true; } From ed10024b22ce82bb928db4b265518ee91769b973 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Feb 2019 19:29:09 +0900 Subject: [PATCH 53/54] Fix some formatting / variable naming --- osu.Game/Overlays/MusicController.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c1dd06c36a..7c62ecf27e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -312,13 +312,13 @@ namespace osu.Game.Overlays private WorkingBeatmap current; private TransformDirection? queuedDirection; - private void beatmapChanged(ValueChangedEvent e) + private void beatmapChanged(ValueChangedEvent beatmap) { TransformDirection direction = TransformDirection.None; if (current != null) { - bool audioEquals = e.NewValue?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; + bool audioEquals = beatmap.NewValue?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; if (audioEquals) direction = TransformDirection.None; @@ -331,7 +331,7 @@ namespace osu.Game.Overlays { //figure out the best direction based on order in playlist. var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != e.NewValue.BeatmapSetInfo?.ID).Count(); + var next = this.beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } @@ -339,7 +339,8 @@ namespace osu.Game.Overlays current.Track.Completed -= currentTrackCompleted; } - current = e.NewValue; + current = beatmap.NewValue; + if (current != null) current.Track.Completed += currentTrackCompleted; From 2fbb0b4e6f69b4d05365dd26725e7a1665b32753 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Feb 2019 19:34:03 +0900 Subject: [PATCH 54/54] Don't use `this` --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 7c62ecf27e..6a71e91de9 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -331,7 +331,7 @@ namespace osu.Game.Overlays { //figure out the best direction based on order in playlist. var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = this.beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); + var next = beatmap.NewValue == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); direction = last > next ? TransformDirection.Prev : TransformDirection.Next; }