From 93d2bb8a5e461ede155d5fd7e9e4e29882642f9c Mon Sep 17 00:00:00 2001 From: Salman Alshamrani Date: Fri, 9 May 2025 09:19:16 +0300 Subject: [PATCH] Add delete hotkey functionality to new song select --- .../TestSceneSongSelectFiltering.cs | 33 +++++++++++++++ osu.Game/Screens/SelectV2/FilterControl.cs | 12 ++++++ osu.Game/Screens/SelectV2/SongSelect.cs | 42 +++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs index e88b47a287..1e368dbee3 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs @@ -19,6 +19,7 @@ using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Chat; using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets; using osu.Game.Rulesets.Mania.Mods; @@ -31,9 +32,11 @@ using osu.Game.Screens.Menu; using osu.Game.Screens.Select.Filter; using osu.Game.Screens.SelectV2; using osu.Game.Tests.Resources; +using osuTK.Input; using BeatmapCarousel = osu.Game.Screens.SelectV2.BeatmapCarousel; using FilterControl = osu.Game.Screens.SelectV2.FilterControl; using NoResultsPlaceholder = osu.Game.Screens.SelectV2.NoResultsPlaceholder; +using BeatmapDeleteDialog = osu.Game.Screens.Select.BeatmapDeleteDialog; namespace osu.Game.Tests.Visual.SongSelectV2 { @@ -268,6 +271,36 @@ namespace osu.Game.Tests.Visual.SongSelectV2 AddAssert("filter count is 5", () => filterOperationsCount, () => Is.EqualTo(5)); } + // This test should probably not be in this test class, it has nothing to do with filtering. + // TestSceneSongSelect is a better place, but doesn't have local storage isolation setup (yet). + [Test] + public void TestDeleteHotkey() + { + loadSongSelect(); + + importBeatmapForRuleset(0); + + AddAssert("beatmap imported", () => manager.GetAllUsableBeatmapSets().Any(), () => Is.True); + + // song select should automatically select the beatmap for us but this is not implemented yet. + // todo: remove when that's the case. + AddAssert("no beatmap selected", () => Beatmap.IsDefault); + AddStep("select beatmap", () => Beatmap.Value = manager.GetWorkingBeatmap(manager.GetAllUsableBeatmapSets().Single().Beatmaps.First())); + AddAssert("beatmap selected", () => !Beatmap.IsDefault); + + AddStep("press shift-delete", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.Delete); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + AddUntilStep("delete dialog shown", () => DialogOverlay.CurrentDialog, Is.InstanceOf); + AddStep("confirm deletion", () => DialogOverlay.CurrentDialog!.PerformAction()); + + AddAssert("beatmap set deleted", () => manager.GetAllUsableBeatmapSets().Any(), () => Is.False); + } + [Test] public void TestPlaceholderVisibleAfterDeleteAll() { diff --git a/osu.Game/Screens/SelectV2/FilterControl.cs b/osu.Game/Screens/SelectV2/FilterControl.cs index 69029cd131..5845c36882 100644 --- a/osu.Game/Screens/SelectV2/FilterControl.cs +++ b/osu.Game/Screens/SelectV2/FilterControl.cs @@ -9,6 +9,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -21,6 +23,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; using osuTK; +using osuTK.Input; namespace osu.Game.Screens.SelectV2 { @@ -274,6 +277,15 @@ namespace osu.Game.Screens.SelectV2 private partial class InnerTextBox : InnerFilterTextBox { public override bool HandleLeftRightArrows => false; + + public override bool OnPressed(KeyBindingPressEvent e) + { + // the "cut" platform key binding (shift-delete) conflicts with the beatmap deletion action. + if (e.Action == PlatformAction.Cut && e.ShiftPressed && e.CurrentState.Keyboard.Keys.IsPressed(Key.Delete)) + return false; + + return base.OnPressed(e); + } } } } diff --git a/osu.Game/Screens/SelectV2/SongSelect.cs b/osu.Game/Screens/SelectV2/SongSelect.cs index d0749c8e6f..a647e04c0a 100644 --- a/osu.Game/Screens/SelectV2/SongSelect.cs +++ b/osu.Game/Screens/SelectV2/SongSelect.cs @@ -9,8 +9,10 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Screens; using osu.Framework.Threading; +using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Overlays.Mods; @@ -19,6 +21,7 @@ using osu.Game.Screens.Menu; using osu.Game.Screens.Select; using osuTK; using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Screens.SelectV2 { @@ -57,6 +60,9 @@ namespace osu.Game.Screens.SelectV2 [Resolved] private OsuLogo? logo { get; set; } + [Resolved] + private IDialogOverlay? dialogs { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -316,5 +322,41 @@ namespace osu.Game.Screens.SelectV2 } #endregion + + #region Beatmap management + + /// + /// Opens up with the given beatmap set. + /// + public void RequestDeleteBeatmap(BeatmapSetInfo set) + { + dialogs?.Push(new BeatmapDeleteDialog(set)); + } + + #endregion + + #region Hotkeys + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.Repeat) return false; + + switch (e.Key) + { + case Key.Delete: + if (e.ShiftPressed) + { + if (!Beatmap.IsDefault) + RequestDeleteBeatmap(Beatmap.Value.BeatmapSetInfo); + return true; + } + + break; + } + + return base.OnKeyDown(e); + } + + #endregion } }