1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-06 09:03:01 +08:00

Prepare KeyBindingRow for accepting external changes

This commit is contained in:
Bartłomiej Dach 2023-10-11 11:08:10 +02:00
parent c2e92cbb70
commit 5f0b1d69a5
No known key found for this signature in database
5 changed files with 108 additions and 31 deletions

View File

@ -207,7 +207,7 @@ namespace osu.Game.Tests.Visual.Settings
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0); AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0);
AddAssert("binding cleared", AddAssert("binding cleared",
() => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0))); () => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.Value.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
} }
[Test] [Test]
@ -237,7 +237,7 @@ namespace osu.Game.Tests.Visual.Settings
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0); AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0);
AddAssert("binding cleared", AddAssert("binding cleared",
() => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0))); () => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.Value.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
} }
[Test] [Test]

View File

@ -0,0 +1,60 @@
// 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.
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Framework.Testing;
using osu.Game.Input.Bindings;
using osu.Game.Overlays;
using osu.Game.Overlays.Settings.Sections.Input;
namespace osu.Game.Tests.Visual.Settings
{
public partial class TestSceneKeyBindingRow : OsuTestScene
{
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
[Test]
public void TestChangesAfterConstruction()
{
KeyBindingRow row = null!;
AddStep("create row", () => Child = new Container
{
Width = 500,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Child = row = new KeyBindingRow(GlobalAction.Back)
{
Defaults = new[]
{
new KeyCombination(InputKey.Escape),
new KeyCombination(InputKey.ExtraMouseButton1)
}
}
});
AddStep("change key bindings", () =>
{
row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.Escape)));
row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.ExtraMouseButton1)));
});
AddUntilStep("revert to default button not shown", () => row.ChildrenOfType<RevertToDefaultButton<bool>>().Single().Alpha, () => Is.Zero);
AddStep("change key bindings", () =>
{
row.KeyBindings.Clear();
row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.X)));
row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.Z)));
row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.I)));
});
AddUntilStep("revert to default button not shown", () => row.ChildrenOfType<RevertToDefaultButton<bool>>().Single().Alpha, () => Is.Not.Zero);
}
}
}

View File

@ -44,6 +44,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
/// </summary> /// </summary>
public bool AllowMainMouseButtons { get; init; } public bool AllowMainMouseButtons { get; init; }
/// <summary>
/// The bindings to display in this row.
/// </summary>
public BindableList<RealmKeyBinding> KeyBindings { get; } = new BindableList<RealmKeyBinding>();
/// <summary> /// <summary>
/// The default key bindings for this row. /// The default key bindings for this row.
/// </summary> /// </summary>
@ -65,12 +70,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public bool FilteringActive { get; set; } public bool FilteringActive { get; set; }
public IEnumerable<LocalisableString> FilterTerms => bindings.Select(b => (LocalisableString)keyCombinationProvider.GetReadableString(b.KeyCombination)).Prepend(text.Text); public IEnumerable<LocalisableString> FilterTerms => KeyBindings.Select(b => (LocalisableString)keyCombinationProvider.GetReadableString(b.KeyCombination)).Prepend(text.Text);
#endregion #endregion
private readonly object action; private readonly object action;
private readonly IEnumerable<RealmKeyBinding> bindings;
private Bindable<bool> isDefault { get; } = new BindableBool(true); private Bindable<bool> isDefault { get; } = new BindableBool(true);
@ -101,11 +105,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input
/// Creates a new <see cref="KeyBindingRow"/>. /// Creates a new <see cref="KeyBindingRow"/>.
/// </summary> /// </summary>
/// <param name="action">The action that this row contains bindings for.</param> /// <param name="action">The action that this row contains bindings for.</param>
/// <param name="bindings">The keybindings to display in this row.</param> public KeyBindingRow(object action)
public KeyBindingRow(object action, List<RealmKeyBinding> bindings)
{ {
this.action = action; this.action = action;
this.bindings = bindings;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
@ -191,10 +193,23 @@ namespace osu.Game.Overlays.Settings.Sections.Input
} }
}; };
foreach (var b in bindings) KeyBindings.BindCollectionChanged((_, _) =>
buttons.Add(new KeyButton(b)); {
Scheduler.AddOnce(updateButtons);
updateIsDefaultValue();
}, true);
}
updateIsDefaultValue(); private void updateButtons()
{
if (buttons.Count > KeyBindings.Count)
buttons.RemoveRange(buttons.Skip(KeyBindings.Count).ToArray(), true);
while (buttons.Count < KeyBindings.Count)
buttons.Add(new KeyButton());
foreach (var (button, binding) in buttons.Zip(KeyBindings))
button.KeyBinding.Value = binding;
} }
public void RestoreDefaults() public void RestoreDefaults()
@ -472,11 +487,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
} }
private void updateStoreFromButton(KeyButton button) => private void updateStoreFromButton(KeyButton button) =>
realm.WriteAsync(r => r.Find<RealmKeyBinding>(button.KeyBinding.ID)!.KeyCombinationString = button.KeyBinding.KeyCombinationString); realm.WriteAsync(r => r.Find<RealmKeyBinding>(button.KeyBinding.Value.ID)!.KeyCombinationString = button.KeyBinding.Value.KeyCombinationString);
private void updateIsDefaultValue() private void updateIsDefaultValue()
{ {
isDefault.Value = bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults); isDefault.Value = KeyBindings.Select(b => b.KeyCombination).SequenceEqual(Defaults);
} }
private partial class CancelButton : RoundedButton private partial class CancelButton : RoundedButton
@ -499,7 +514,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public partial class KeyButton : Container public partial class KeyButton : Container
{ {
public readonly RealmKeyBinding KeyBinding; public Bindable<RealmKeyBinding> KeyBinding { get; } = new Bindable<RealmKeyBinding>();
private readonly Box box; private readonly Box box;
public readonly OsuSpriteText Text; public readonly OsuSpriteText Text;
@ -525,13 +540,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
} }
} }
public KeyButton(RealmKeyBinding keyBinding) public KeyButton()
{ {
if (keyBinding.IsManaged)
throw new ArgumentException("Key binding should not be attached as we make temporary changes", nameof(keyBinding));
KeyBinding = keyBinding;
Margin = new MarginPadding(padding); Margin = new MarginPadding(padding);
Masking = true; Masking = true;
@ -567,6 +577,13 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
base.LoadComplete(); base.LoadComplete();
KeyBinding.BindValueChanged(_ =>
{
if (KeyBinding.Value.IsManaged)
throw new ArgumentException("Key binding should not be attached as we make temporary changes", nameof(KeyBinding));
updateKeyCombinationText();
});
keyCombinationProvider.KeymapChanged += updateKeyCombinationText; keyCombinationProvider.KeymapChanged += updateKeyCombinationText;
updateKeyCombinationText(); updateKeyCombinationText();
} }
@ -575,6 +592,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private void load() private void load()
{ {
updateHoverState(); updateHoverState();
FinishTransforms(true);
} }
protected override bool OnHover(HoverEvent e) protected override bool OnHover(HoverEvent e)
@ -613,10 +631,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public void UpdateKeyCombination(KeyCombination newCombination) public void UpdateKeyCombination(KeyCombination newCombination)
{ {
if (KeyBinding.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination)) if (KeyBinding.Value.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
return; return;
KeyBinding.KeyCombination = newCombination; KeyBinding.Value.KeyCombination = newCombination;
updateKeyCombinationText(); updateKeyCombinationText();
} }
@ -624,7 +642,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
Scheduler.AddOnce(updateText); Scheduler.AddOnce(updateText);
void updateText() => Text.Text = keyCombinationProvider.GetReadableString(KeyBinding.KeyCombination); void updateText() => Text.Text = keyCombinationProvider.GetReadableString(KeyBinding.Value.KeyCombination);
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -42,11 +42,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input
int intKey = (int)defaultGroup.Key; int intKey = (int)defaultGroup.Key;
// one row per valid action. // one row per valid action.
Add(CreateKeyBindingRow( var row = CreateKeyBindingRow(defaultGroup.Key, defaultGroup)
defaultGroup.Key, .With(row => row.BindingUpdated = onBindingUpdated);
bindings.Where(b => b.ActionInt.Equals(intKey)).ToList(), row.KeyBindings.AddRange(bindings.Where(b => b.ActionInt.Equals(intKey)));
defaultGroup) Add(row);
.With(row => row.BindingUpdated = onBindingUpdated));
} }
Add(new ResetButton Add(new ResetButton
@ -57,8 +56,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
protected abstract IEnumerable<RealmKeyBinding> GetKeyBindings(Realm realm); protected abstract IEnumerable<RealmKeyBinding> GetKeyBindings(Realm realm);
protected virtual KeyBindingRow CreateKeyBindingRow(object action, IEnumerable<RealmKeyBinding> keyBindings, IEnumerable<KeyBinding> defaults) protected virtual KeyBindingRow CreateKeyBindingRow(object action, IEnumerable<KeyBinding> defaults)
=> new KeyBindingRow(action, keyBindings.ToList()) => new KeyBindingRow(action)
{ {
AllowMainMouseButtons = false, AllowMainMouseButtons = false,
Defaults = defaults.Select(d => d.KeyCombination), Defaults = defaults.Select(d => d.KeyCombination),

View File

@ -39,8 +39,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
.Where(b => b.RulesetName == rulesetName && b.Variant == variant); .Where(b => b.RulesetName == rulesetName && b.Variant == variant);
} }
protected override KeyBindingRow CreateKeyBindingRow(object action, IEnumerable<RealmKeyBinding> keyBindings, IEnumerable<KeyBinding> defaults) protected override KeyBindingRow CreateKeyBindingRow(object action, IEnumerable<KeyBinding> defaults)
=> new KeyBindingRow(action, keyBindings.ToList()) => new KeyBindingRow(action)
{ {
AllowMainMouseButtons = true, AllowMainMouseButtons = true,
Defaults = defaults.Select(d => d.KeyCombination), Defaults = defaults.Select(d => d.KeyCombination),