From 0a3f05c52b7be65c8c559914ef84e122ce63d110 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 May 2025 17:05:27 +0900 Subject: [PATCH 1/7] Allow accessing song select v2 by holding control while entering song select --- .../TestSceneSongSelectNavigation.cs | 100 ------------------ osu.Game/Screens/Menu/MainMenu.cs | 9 +- 2 files changed, 8 insertions(+), 101 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Navigation/TestSceneSongSelectNavigation.cs diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneSongSelectNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneSongSelectNavigation.cs deleted file mode 100644 index 5c6138596a..0000000000 --- a/osu.Game.Tests/Visual/Navigation/TestSceneSongSelectNavigation.cs +++ /dev/null @@ -1,100 +0,0 @@ -// 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 NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Screens; -using osu.Game.Database; -using osu.Game.Overlays; -using osu.Game.Overlays.Toolbar; -using osu.Game.Screens; -using osu.Game.Screens.Footer; -using osu.Game.Screens.Menu; -using osu.Game.Screens.SelectV2; - -namespace osu.Game.Tests.Visual.Navigation -{ - [Explicit] - public partial class TestSceneSongSelectNavigation : ScreenTestScene - { - [Cached] - private readonly ScreenFooter screenFooter; - - [Cached] - private readonly OsuLogo logo; - - [Cached(typeof(INotificationOverlay))] - private readonly INotificationOverlay notificationOverlay = new NotificationOverlay(); - - protected override bool UseOnlineAPI => true; - - public TestSceneSongSelectNavigation() - { - Children = new Drawable[] - { - new PopoverContainer - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Toolbar - { - State = { Value = Visibility.Visible }, - }, - screenFooter = new ScreenFooter - { - OnBack = () => Stack.CurrentScreen.Exit(), - }, - logo = new OsuLogo - { - Alpha = 0f, - }, - }, - }, - }; - - Stack.Padding = new MarginPadding { Top = Toolbar.HEIGHT }; - } - - [BackgroundDependencyLoader] - private void load() - { - RealmDetachedBeatmapStore beatmapStore; - Dependencies.CacheAs(beatmapStore = new RealmDetachedBeatmapStore()); - Add(beatmapStore); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Stack.ScreenPushed += updateFooter; - Stack.ScreenExited += updateFooter; - } - - public override void SetUpSteps() - { - base.SetUpSteps(); - AddStep("load screen", () => Stack.Push(new SoloSongSelect())); - AddUntilStep("wait for load", () => Stack.CurrentScreen is SoloSongSelect songSelect && songSelect.IsLoaded); - } - - private void updateFooter(IScreen? _, IScreen? newScreen) - { - if (newScreen is IOsuScreen osuScreen && osuScreen.ShowFooter) - { - screenFooter.Show(); - screenFooter.SetButtons(osuScreen.CreateFooterButtons()); - } - else - { - screenFooter.Hide(); - screenFooter.SetButtons(Array.Empty()); - } - } - } -} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c7d57f2993..fba321d128 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -43,6 +43,7 @@ using osu.Game.Seasonal; using osuTK; using osuTK.Graphics; using osu.Game.Localisation; +using osu.Game.Screens.SelectV2; namespace osu.Game.Screens.Menu { @@ -239,7 +240,13 @@ namespace osu.Game.Screens.Menu public void ReturnToOsuLogo() => Buttons.State = ButtonSystemState.Initial; - private void loadSoloSongSelect() => this.Push(new PlaySongSelect()); + private void loadSoloSongSelect() + { + if (GetContainingInputManager()!.CurrentState.Keyboard.ControlPressed) + this.Push(new SoloSongSelect()); + else + this.Push(new PlaySongSelect()); + } public override void OnEntering(ScreenTransitionEvent e) { From a8d8d2d84c29d07181a0fa167a54ee7a9f5b8e67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 May 2025 17:32:44 +0900 Subject: [PATCH 2/7] Fix new (beatmap) carousel not correctly accounting for user scroll overrides The new carousel implementation was lacking some scroll related behaviours. This makes sure that post-filter, the selection is re-centered *unless* the user has scrolled away manually. This matches the old carousel's behaviour. See https://github.com/ppy/osu/pull/16647 for original implementation. Closes https://github.com/ppy/osu/issues/33052. --- .../TestSceneBeatmapCarouselScrolling.cs | 79 +++++++++++++++++-- osu.Game/Graphics/Carousel/Carousel.cs | 8 ++ 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs index f5574d2789..1959a2fa49 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs @@ -5,7 +5,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Primitives; using osu.Framework.Testing; -using osu.Game.Screens.Select.Filter; using osu.Game.Screens.SelectV2; namespace osu.Game.Tests.Visual.SongSelectV2 @@ -19,19 +18,16 @@ namespace osu.Game.Tests.Visual.SongSelectV2 RemoveAllBeatmaps(); CreateCarousel(); - SortBy(SortMode.Artist); - AddBeatmaps(10); WaitForDrawablePanels(); } [Test] - public void TestScrollPositionMaintainedOnAddSecondSelected() + public void TestScrollPositionMaintainedOnAdd_SecondSelected() { Quad positionBefore = default; AddStep("select middle beatmap", () => Carousel.CurrentSelection = BeatmapSets.ElementAt(BeatmapSets.Count - 2).Beatmaps.First()); - AddStep("scroll to selected item", () => Scroll.ScrollTo(Scroll.ChildrenOfType().Single(p => p.Selected.Value))); WaitForScrolling(); @@ -45,11 +41,35 @@ namespace osu.Game.Tests.Visual.SongSelectV2 } [Test] - public void TestScrollPositionMaintainedOnAddLastSelected() + public void TestScrollPositionMaintainedOnAdd_SecondSelected_WithUserScroll() { Quad positionBefore = default; - AddStep("scroll to last item", () => Scroll.ScrollToEnd(false)); + AddStep("select middle beatmap", () => Carousel.CurrentSelection = BeatmapSets.ElementAt(BeatmapSets.Count - 2).Beatmaps.First()); + WaitForScrolling(); + + AddStep("override scroll with user scroll", () => + { + InputManager.MoveMouseTo(Scroll.ScreenSpaceDrawQuad.Centre); + InputManager.ScrollVerticalBy(-1); + }); + WaitForScrolling(); + + AddStep("save selected screen position", () => positionBefore = Carousel.ChildrenOfType().FirstOrDefault(p => p.Selected.Value)!.ScreenSpaceDrawQuad); + + RemoveFirstBeatmap(); + WaitForFiltering(); + + AddAssert("select screen position unchanged", () => Carousel.ChildrenOfType().Single(p => p.Selected.Value).ScreenSpaceDrawQuad, + () => Is.EqualTo(positionBefore)); + } + + [Test] + public void TestScrollPositionMaintainedOnAdd_LastSelected() + { + Quad positionBefore = default; + + AddStep("scroll to end", () => Scroll.ScrollToEnd(false)); AddStep("select last beatmap", () => Carousel.CurrentSelection = BeatmapSets.Last().Beatmaps.Last()); @@ -62,5 +82,50 @@ namespace osu.Game.Tests.Visual.SongSelectV2 AddAssert("select screen position unchanged", () => Carousel.ChildrenOfType().Single(p => p.Selected.Value).ScreenSpaceDrawQuad, () => Is.EqualTo(positionBefore)); } + + [Test] + public void TestScrollToSelectionAfterFilter() + { + Quad positionBefore = default; + + AddStep("select first beatmap", () => Carousel.CurrentSelection = BeatmapSets.First().Beatmaps.First()); + + WaitForScrolling(); + + AddStep("save selected screen position", () => positionBefore = Carousel.ChildrenOfType().FirstOrDefault(p => p.Selected.Value)!.ScreenSpaceDrawQuad); + + AddStep("scroll to end", () => Scroll.ScrollToEnd()); + WaitForScrolling(); + + ApplyToFilter("search", f => f.SearchText = "Some"); + WaitForFiltering(); + + AddUntilStep("select screen position returned to selection", () => Carousel.ChildrenOfType().Single(p => p.Selected.Value).ScreenSpaceDrawQuad, + () => Is.EqualTo(positionBefore)); + } + + [Test] + public void TestScrollToSelectionAfterFilter_WithUserScroll() + { + Quad positionBefore = default; + + AddStep("select first beatmap", () => Carousel.CurrentSelection = BeatmapSets.First().Beatmaps.First()); + WaitForScrolling(); + + AddStep("override scroll with user scroll", () => + { + InputManager.MoveMouseTo(Scroll.ScreenSpaceDrawQuad.Centre); + InputManager.ScrollVerticalBy(-1); + }); + WaitForScrolling(); + + AddStep("save selected screen position", () => positionBefore = Carousel.ChildrenOfType().FirstOrDefault(p => p.Selected.Value)!.ScreenSpaceDrawQuad); + + ApplyToFilter("search", f => f.SearchText = "Some"); + WaitForFiltering(); + + AddUntilStep("select screen position returned to selection", () => Carousel.ChildrenOfType().Single(p => p.Selected.Value).ScreenSpaceDrawQuad, + () => Is.EqualTo(positionBefore)); + } } } diff --git a/osu.Game/Graphics/Carousel/Carousel.cs b/osu.Game/Graphics/Carousel/Carousel.cs index 4bcfadf090..170ad4b8d1 100644 --- a/osu.Game/Graphics/Carousel/Carousel.cs +++ b/osu.Game/Graphics/Carousel/Carousel.cs @@ -315,6 +315,8 @@ namespace osu.Game.Graphics.Carousel HandleItemSelected(currentSelection.Model); refreshAfterSelection(); + if (!Scroll.UserScrolling) + scrollToSelection(); NewItemsPresented?.Invoke(); }); @@ -469,6 +471,9 @@ namespace osu.Game.Graphics.Carousel #region Selection handling + /// + /// Becomes invalid when the current selection has changed and needs to be updated visually. + /// private readonly Cached selectionValid = new Cached(); private Selection currentKeyboardSelection = new Selection(); @@ -569,7 +574,10 @@ namespace osu.Game.Graphics.Carousel if (!selectionValid.IsValid) { refreshAfterSelection(); + + // Always scroll to selection in this case (regardless of `UserScrolling` state), centering the selection. scrollToSelection(); + selectionValid.Validate(); } From 168c3cf018c7b85e96ab8ab684df96b2813cda63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 May 2025 11:25:14 +0200 Subject: [PATCH 3/7] Add baseline test coverage of replay recording in all rulesets Nothing fancy, just basics to ensure the subsequent commit doesn't break anything. --- .../TestSceneReplayRecording.cs | 75 +++++++++++++++++ .../TestSceneReplayRecording.cs | 59 ++++++++++++++ .../TestSceneReplayRecording.cs | 81 +++++++++++++++++++ .../TestSceneReplayRecording.cs | 65 +++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneReplayRecording.cs create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneReplayRecording.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneReplayRecording.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs new file mode 100644 index 0000000000..4432a6801e --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Storyboards; +using osu.Game.Tests.Visual; +using osuTK.Input; + +namespace osu.Game.Rulesets.Catch.Tests +{ + public partial class TestSceneReplayRecording : PlayerTestScene + { + protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); + + [Resolved] + private AudioManager audioManager { get; set; } = null!; + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap + { + HitObjects = + { + new Fruit { StartTime = 0, }, + new Fruit { StartTime = 5000, }, + new Fruit { StartTime = 10000, }, + new Fruit { StartTime = 15000, } + } + }; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + + [Test] + public void TestRecording() + { + seekTo(0); + AddStep("start moving left", () => InputManager.PressKey(Key.Left)); + seekTo(5000); + AddStep("end moving left", () => InputManager.ReleaseKey(Key.Left)); + AddAssert("catcher max left", () => this.ChildrenOfType().Single().X, () => Is.EqualTo(0)); + AddAssert("movement to left recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([CatchAction.MoveLeft]))); + AddAssert("replay reached left edge", () => Player.Score.Replay.Frames.OfType().Any(f => Precision.AlmostEquals(f.Position, 0))); + + AddStep("start dashing right", () => + { + InputManager.PressKey(Key.LShift); + InputManager.PressKey(Key.Right); + }); + seekTo(10000); + AddStep("end dashing right", () => + { + InputManager.ReleaseKey(Key.LShift); + InputManager.ReleaseKey(Key.Right); + }); + AddAssert("catcher max right", () => this.ChildrenOfType().Single().X, () => Is.EqualTo(0)); + AddAssert("dash to right recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([CatchAction.Dash, CatchAction.MoveRight]))); + AddAssert("replay reached right edge", () => Player.Score.Replay.Frames.OfType().Any(f => Precision.AlmostEquals(f.Position, CatchPlayfield.WIDTH))); + } + + private void seekTo(double time) + { + AddStep($"seek to {time}ms", () => Player.GameplayClockContainer.Seek(time)); + AddUntilStep("wait for seek to finish", () => Player.DrawableRuleset.FrameStableClock.CurrentTime, () => Is.EqualTo(time).Within(500)); + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRecording.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRecording.cs new file mode 100644 index 0000000000..43c648a6dd --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRecording.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Storyboards; +using osu.Game.Tests.Visual; +using osuTK.Input; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public partial class TestSceneReplayRecording : PlayerTestScene + { + protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); + + [Resolved] + private AudioManager audioManager { get; set; } = null!; + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new ManiaBeatmap(new StageDefinition(1)) + { + HitObjects = + { + new Note { StartTime = 0, }, + new Note { StartTime = 5000, }, + new Note { StartTime = 10000, }, + new Note { StartTime = 15000, } + }, + Difficulty = { CircleSize = 1 }, + BeatmapInfo = + { + Ruleset = ruleset, + } + }; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + + [Test] + public void TestRecording() + { + seekTo(0); + AddStep("press space", () => InputManager.Key(Key.Space)); + AddAssert("button press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([ManiaAction.Key1]))); + } + + private void seekTo(double time) + { + AddStep($"seek to {time}ms", () => Player.GameplayClockContainer.Seek(time)); + AddUntilStep("wait for seek to finish", () => Player.DrawableRuleset.FrameStableClock.CurrentTime, () => Is.EqualTo(time).Within(500)); + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneReplayRecording.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneReplayRecording.cs new file mode 100644 index 0000000000..d163e8a1b4 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneReplayRecording.cs @@ -0,0 +1,81 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Storyboards; +using osu.Game.Tests.Visual; +using osuTK.Input; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public partial class TestSceneReplayRecording : PlayerTestScene + { + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + [Resolved] + private AudioManager audioManager { get; set; } = null!; + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap + { + HitObjects = + { + new HitCircle + { + Position = OsuPlayfield.BASE_SIZE / 2, + StartTime = 0, + }, + new HitCircle + { + Position = OsuPlayfield.BASE_SIZE / 2, + StartTime = 5000, + }, + new HitCircle + { + Position = OsuPlayfield.BASE_SIZE / 2, + StartTime = 10000, + }, + new HitCircle + { + Position = OsuPlayfield.BASE_SIZE / 2, + StartTime = 15000, + } + } + }; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + + [Test] + public void TestRecording() + { + seekTo(0); + AddStep("move cursor to circle", () => InputManager.MoveMouseTo(Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.Single())); + AddStep("press X", () => InputManager.Key(Key.X)); + AddAssert("right button press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([OsuAction.RightButton]))); + + seekTo(5000); + AddStep("move cursor to circle", () => InputManager.MoveMouseTo(Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.Single())); + AddStep("press Z", () => InputManager.Key(Key.Z)); + AddAssert("left button press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([OsuAction.LeftButton]))); + + seekTo(10000); + AddStep("move cursor to circle", () => InputManager.MoveMouseTo(Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.Single())); + AddStep("press C", () => InputManager.Key(Key.C)); + AddAssert("smoke button press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([OsuAction.Smoke]))); + } + + private void seekTo(double time) + { + AddStep($"seek to {time}ms", () => Player.GameplayClockContainer.Seek(time)); + AddUntilStep("wait for seek to finish", () => Player.DrawableRuleset.FrameStableClock.CurrentTime, () => Is.EqualTo(time).Within(500)); + } + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneReplayRecording.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneReplayRecording.cs new file mode 100644 index 0000000000..14a1fbfa99 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneReplayRecording.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Storyboards; +using osu.Game.Tests.Visual; +using osuTK.Input; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public partial class TestSceneReplayRecording : PlayerTestScene + { + protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); + + [Resolved] + private AudioManager audioManager { get; set; } = null!; + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap + { + HitObjects = + { + new Hit { StartTime = 0, }, + new Hit { StartTime = 5000, }, + new Hit { StartTime = 10000, }, + new Hit { StartTime = 15000, } + } + }; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + + [Test] + public void TestRecording() + { + seekTo(0); + AddStep("press D", () => InputManager.Key(Key.D)); + AddAssert("left rim press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([TaikoAction.LeftRim]))); + + seekTo(5000); + AddStep("press F", () => InputManager.Key(Key.F)); + AddAssert("left centre press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([TaikoAction.LeftCentre]))); + + seekTo(10000); + AddStep("press J", () => InputManager.Key(Key.J)); + AddAssert("right centre press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([TaikoAction.RightCentre]))); + + seekTo(10000); + AddStep("press K", () => InputManager.Key(Key.K)); + AddAssert("right rim press recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([TaikoAction.RightRim]))); + } + + private void seekTo(double time) + { + AddStep($"seek to {time}ms", () => Player.GameplayClockContainer.Seek(time)); + AddUntilStep("wait for seek to finish", () => Player.DrawableRuleset.FrameStableClock.CurrentTime, () => Is.EqualTo(time).Within(500)); + } + } +} From acebf3e95effb40583858ec34c5927ddc226bb2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 May 2025 11:25:31 +0200 Subject: [PATCH 4/7] Remove unnecessary replay recorder depth hack Addresses https://github.com/ppy/osu/pull/33102#discussion_r2087963889. --- osu.Game/Rulesets/UI/ReplayRecorder.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/ReplayRecorder.cs b/osu.Game/Rulesets/UI/ReplayRecorder.cs index 1f91e2c5f0..d723c31434 100644 --- a/osu.Game/Rulesets/UI/ReplayRecorder.cs +++ b/osu.Game/Rulesets/UI/ReplayRecorder.cs @@ -40,8 +40,6 @@ namespace osu.Game.Rulesets.UI this.target = target; RelativeSizeAxes = Axes.Both; - - Depth = float.MinValue; } protected override void LoadComplete() From 35e2094ed440f3d11d75f790a41217c6c1ae1870 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 May 2025 19:30:45 +0900 Subject: [PATCH 5/7] Fix test naming --- .../Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs index 1959a2fa49..fa8ca20d9e 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 } [Test] - public void TestScrollPositionMaintainedOnAdd_SecondSelected() + public void TestScrollPositionMaintainedOnRemove_SecondSelected() { Quad positionBefore = default; @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 } [Test] - public void TestScrollPositionMaintainedOnAdd_SecondSelected_WithUserScroll() + public void TestScrollPositionMaintainedOnRemove_SecondSelected_WithUserScroll() { Quad positionBefore = default; From 81689f7c69699cc8eb9e0d16dd5d68e8680aec88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 May 2025 12:36:26 +0200 Subject: [PATCH 6/7] Rename one more test --- .../Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs index fa8ca20d9e..383ec47a69 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapCarouselScrolling.cs @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 } [Test] - public void TestScrollPositionMaintainedOnAdd_LastSelected() + public void TestScrollPositionMaintainedOnRemove_LastSelected() { Quad positionBefore = default; From 81e6d6a2de2c8ad29591b1031b47e8d0389b6e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 May 2025 14:25:38 +0200 Subject: [PATCH 7/7] Fix some botched assertions --- osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs index 4432a6801e..57ee49d70d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneReplayRecording.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("start moving left", () => InputManager.PressKey(Key.Left)); seekTo(5000); AddStep("end moving left", () => InputManager.ReleaseKey(Key.Left)); - AddAssert("catcher max left", () => this.ChildrenOfType().Single().X, () => Is.EqualTo(0)); + AddAssert("catcher max left", () => this.ChildrenOfType().Single().X, () => Is.EqualTo(0)); AddAssert("movement to left recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([CatchAction.MoveLeft]))); AddAssert("replay reached left edge", () => Player.Score.Replay.Frames.OfType().Any(f => Precision.AlmostEquals(f.Position, 0))); @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Catch.Tests InputManager.ReleaseKey(Key.LShift); InputManager.ReleaseKey(Key.Right); }); - AddAssert("catcher max right", () => this.ChildrenOfType().Single().X, () => Is.EqualTo(0)); + AddAssert("catcher max right", () => this.ChildrenOfType().Single().X, () => Is.EqualTo(CatchPlayfield.WIDTH)); AddAssert("dash to right recorded to replay", () => Player.Score.Replay.Frames.OfType().Any(f => f.Actions.SequenceEqual([CatchAction.Dash, CatchAction.MoveRight]))); AddAssert("replay reached right edge", () => Player.Score.Replay.Frames.OfType().Any(f => Precision.AlmostEquals(f.Position, CatchPlayfield.WIDTH))); }