1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:47:27 +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);
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]
@ -237,7 +237,7 @@ namespace osu.Game.Tests.Visual.Settings
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0);
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]

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>
public bool AllowMainMouseButtons { get; init; }
/// <summary>
/// The bindings to display in this row.
/// </summary>
public BindableList<RealmKeyBinding> KeyBindings { get; } = new BindableList<RealmKeyBinding>();
/// <summary>
/// The default key bindings for this row.
/// </summary>
@ -65,12 +70,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
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
private readonly object action;
private readonly IEnumerable<RealmKeyBinding> bindings;
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"/>.
/// </summary>
/// <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, List<RealmKeyBinding> bindings)
public KeyBindingRow(object action)
{
this.action = action;
this.bindings = bindings;
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
@ -191,10 +193,23 @@ namespace osu.Game.Overlays.Settings.Sections.Input
}
};
foreach (var b in bindings)
buttons.Add(new KeyButton(b));
KeyBindings.BindCollectionChanged((_, _) =>
{
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()
@ -472,11 +487,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
}
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()
{
isDefault.Value = bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults);
isDefault.Value = KeyBindings.Select(b => b.KeyCombination).SequenceEqual(Defaults);
}
private partial class CancelButton : RoundedButton
@ -499,7 +514,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public partial class KeyButton : Container
{
public readonly RealmKeyBinding KeyBinding;
public Bindable<RealmKeyBinding> KeyBinding { get; } = new Bindable<RealmKeyBinding>();
private readonly Box box;
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);
Masking = true;
@ -567,6 +577,13 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{
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;
updateKeyCombinationText();
}
@ -575,6 +592,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
private void load()
{
updateHoverState();
FinishTransforms(true);
}
protected override bool OnHover(HoverEvent e)
@ -613,10 +631,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public void UpdateKeyCombination(KeyCombination newCombination)
{
if (KeyBinding.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
if (KeyBinding.Value.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
return;
KeyBinding.KeyCombination = newCombination;
KeyBinding.Value.KeyCombination = newCombination;
updateKeyCombinationText();
}
@ -624,7 +642,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{
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)

View File

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