1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-12 07:27:51 +08:00

Merge pull request #18264 from peppy/deselect-all-mods-key

Add key binding to deselect all mods
This commit is contained in:
Bartłomiej Dach 2022-05-14 20:48:42 +02:00 committed by GitHub
commit 351f5a30d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 30 deletions

View File

@ -7,6 +7,7 @@ using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods;
@ -55,6 +56,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("customisation area not expanded", () => this.ChildrenOfType<ModSettingsArea>().Single().Height == 0); AddAssert("customisation area not expanded", () => this.ChildrenOfType<ModSettingsArea>().Single().Height == 0);
} }
[Test]
public void TestSelectDeselectAllViaKeyboard()
{
createFreeModSelect();
AddStep("press ctrl+a", () => InputManager.Keys(PlatformAction.SelectAll));
AddUntilStep("all mods selected", assertAllAvailableModsSelected);
AddStep("press backspace", () => InputManager.Key(Key.BackSpace));
AddUntilStep("all mods deselected", () => !freeModSelectOverlay.SelectedMods.Value.Any());
}
[Test] [Test]
public void TestSelectDeselectAll() public void TestSelectDeselectAll()
{ {

View File

@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
@ -416,6 +416,19 @@ namespace osu.Game.Tests.Visual.UserInterface
AddAssert("unimplemented mod panel is filtered", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value); AddAssert("unimplemented mod panel is filtered", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value);
} }
[Test]
public void TestDeselectAllViaKey()
{
createScreen();
changeRuleset(0);
AddStep("select DT + HD", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden() });
AddAssert("DT + HD selected", () => modSelectOverlay.ChildrenOfType<ModPanel>().Count(panel => panel.Active.Value) == 2);
AddStep("press backspace", () => InputManager.Key(Key.BackSpace));
AddUntilStep("all mods deselected", () => !SelectedMods.Value.Any());
}
[Test] [Test]
public void TestDeselectAllViaButton() public void TestDeselectAllViaButton()
{ {

View File

@ -109,6 +109,7 @@ namespace osu.Game.Input.Bindings
new KeyBinding(InputKey.F2, GlobalAction.SelectNextRandom), new KeyBinding(InputKey.F2, GlobalAction.SelectNextRandom),
new KeyBinding(new[] { InputKey.Shift, InputKey.F2 }, GlobalAction.SelectPreviousRandom), new KeyBinding(new[] { InputKey.Shift, InputKey.F2 }, GlobalAction.SelectPreviousRandom),
new KeyBinding(InputKey.F3, GlobalAction.ToggleBeatmapOptions), new KeyBinding(InputKey.F3, GlobalAction.ToggleBeatmapOptions),
new KeyBinding(InputKey.BackSpace, GlobalAction.DeselectAllMods),
}; };
public IEnumerable<KeyBinding> AudioControlKeyBindings => new[] public IEnumerable<KeyBinding> AudioControlKeyBindings => new[]
@ -318,5 +319,8 @@ namespace osu.Game.Input.Bindings
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectNextGroup))] [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectNextGroup))]
SelectNextGroup, SelectNextGroup,
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.DeselectAllMods))]
DeselectAllMods,
} }
} }

View File

@ -207,7 +207,12 @@ namespace osu.Game.Localisation
/// <summary> /// <summary>
/// "Toggle Mod Select" /// "Toggle Mod Select"
/// </summary> /// </summary>
public static LocalisableString ToggleModSelection => new TranslatableString(getKey(@"toggle_mod_selection"), @"Toggle Mod Select"); public static LocalisableString ToggleModSelection => new TranslatableString(getKey(@"toggle_mod_selection"), @"Toggle mod select");
/// <summary>
/// "Deselect all mods"
/// </summary>
public static LocalisableString DeselectAllMods => new TranslatableString(getKey(@"deselect_all_mods"), @"Deselect all mods");
/// <summary> /// <summary>
/// "Random" /// "Random"

View File

@ -56,11 +56,32 @@ namespace osu.Game.Overlays.Mods
/// </summary> /// </summary>
protected virtual bool ShowTotalMultiplier => true; protected virtual bool ShowTotalMultiplier => true;
/// <summary>
/// Whether per-mod customisation controls are visible.
/// </summary>
protected virtual bool AllowCustomisation => true;
protected virtual ModColumn CreateModColumn(ModType modType, Key[]? toggleKeys = null) => new ModColumn(modType, false, toggleKeys); protected virtual ModColumn CreateModColumn(ModType modType, Key[]? toggleKeys = null) => new ModColumn(modType, false, toggleKeys);
protected virtual IReadOnlyList<Mod> ComputeNewModsFromSelection(IReadOnlyList<Mod> oldSelection, IReadOnlyList<Mod> newSelection) => newSelection; protected virtual IReadOnlyList<Mod> ComputeNewModsFromSelection(IReadOnlyList<Mod> oldSelection, IReadOnlyList<Mod> newSelection) => newSelection;
protected virtual IEnumerable<ShearedButton> CreateFooterButtons() => createDefaultFooterButtons(); protected virtual IEnumerable<ShearedButton> CreateFooterButtons()
{
if (AllowCustomisation)
{
yield return customisationButton = new ShearedToggleButton(BUTTON_WIDTH)
{
Text = ModSelectOverlayStrings.ModCustomisation,
Active = { BindTarget = customisationVisible }
};
}
yield return deselectAllButton = new ShearedButton(BUTTON_WIDTH)
{
Text = CommonStrings.DeselectAll,
Action = DeselectAll
};
}
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>(); private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
private readonly Dictionary<ModType, IReadOnlyList<ModState>> localAvailableMods = new Dictionary<ModType, IReadOnlyList<ModState>>(); private readonly Dictionary<ModType, IReadOnlyList<ModState>> localAvailableMods = new Dictionary<ModType, IReadOnlyList<ModState>>();
@ -77,6 +98,7 @@ namespace osu.Game.Overlays.Mods
private DifficultyMultiplierDisplay? multiplierDisplay; private DifficultyMultiplierDisplay? multiplierDisplay;
private ShearedToggleButton? customisationButton; private ShearedToggleButton? customisationButton;
private ShearedButton? deselectAllButton;
protected ModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Green) protected ModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Green)
: base(colourScheme) : base(colourScheme)
@ -201,7 +223,7 @@ namespace osu.Game.Overlays.Mods
// This is an optimisation to prevent refreshing the available settings controls when it can be // This is an optimisation to prevent refreshing the available settings controls when it can be
// reasonably assumed that the settings panel is never to be displayed (e.g. FreeModSelectOverlay). // reasonably assumed that the settings panel is never to be displayed (e.g. FreeModSelectOverlay).
if (customisationButton != null) if (AllowCustomisation)
((IBindable<IReadOnlyList<Mod>>)modSettingsArea.SelectedMods).BindTo(SelectedMods); ((IBindable<IReadOnlyList<Mod>>)modSettingsArea.SelectedMods).BindTo(SelectedMods);
SelectedMods.BindValueChanged(val => SelectedMods.BindValueChanged(val =>
@ -256,21 +278,6 @@ namespace osu.Game.Overlays.Mods
}; };
} }
private ShearedButton[] createDefaultFooterButtons()
=> new[]
{
customisationButton = new ShearedToggleButton(BUTTON_WIDTH)
{
Text = ModSelectOverlayStrings.ModCustomisation,
Active = { BindTarget = customisationVisible }
},
new ShearedButton(BUTTON_WIDTH)
{
Text = CommonStrings.DeselectAll,
Action = DeselectAll
}
};
private void createLocalMods() private void createLocalMods()
{ {
localAvailableMods.Clear(); localAvailableMods.Clear();
@ -508,6 +515,10 @@ namespace osu.Game.Overlays.Mods
hideOverlay(true); hideOverlay(true);
return true; return true;
} }
case GlobalAction.DeselectAllMods:
deselectAllButton?.TriggerClick();
return true;
} }
return base.OnPressed(e); return base.OnPressed(e);

View File

@ -4,7 +4,11 @@
using System; using System;
using osu.Game.Overlays; using osu.Game.Overlays;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -13,16 +17,20 @@ using osu.Game.Localisation;
namespace osu.Game.Screens.OnlinePlay namespace osu.Game.Screens.OnlinePlay
{ {
public class FreeModSelectOverlay : ModSelectOverlay public class FreeModSelectOverlay : ModSelectOverlay, IKeyBindingHandler<PlatformAction>
{ {
protected override bool ShowTotalMultiplier => false; protected override bool ShowTotalMultiplier => false;
protected override bool AllowCustomisation => false;
public new Func<Mod, bool> IsValidMod public new Func<Mod, bool> IsValidMod
{ {
get => base.IsValidMod; get => base.IsValidMod;
set => base.IsValidMod = m => m.UserPlayable && value.Invoke(m); set => base.IsValidMod = m => m.UserPlayable && value.Invoke(m);
} }
private ShearedButton selectAllButton;
public FreeModSelectOverlay() public FreeModSelectOverlay()
: base(OverlayColourScheme.Plum) : base(OverlayColourScheme.Plum)
{ {
@ -31,22 +39,32 @@ namespace osu.Game.Screens.OnlinePlay
protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new ModColumn(modType, true, toggleKeys); protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new ModColumn(modType, true, toggleKeys);
protected override IEnumerable<ShearedButton> CreateFooterButtons() => new[] protected override IEnumerable<ShearedButton> CreateFooterButtons() => base.CreateFooterButtons().Prepend(
{ selectAllButton = new ShearedButton(BUTTON_WIDTH)
new ShearedButton(BUTTON_WIDTH)
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Text = CommonStrings.SelectAll, Text = CommonStrings.SelectAll,
Action = SelectAll Action = SelectAll
}, });
new ShearedButton(BUTTON_WIDTH)
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
{
if (e.Repeat)
return false;
switch (e.Action)
{ {
Anchor = Anchor.BottomLeft, case PlatformAction.SelectAll:
Origin = Anchor.BottomLeft, selectAllButton.TriggerClick();
Text = CommonStrings.DeselectAll, return true;
Action = DeselectAll
} }
};
return false;
}
public void OnReleased(KeyBindingReleaseEvent<PlatformAction> e)
{
}
} }
} }