diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index 5467a64b859c..3a3af43cb16f 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -78,7 +78,7 @@ public void TestGameplayKeyBindings() private KeyBindingsSubsection osuBindingSubsection => keyBindingPanel .ChildrenOfType() - .FirstOrDefault(s => s.Ruleset.ShortName == "osu"); + .FirstOrDefault(s => s.Ruleset!.ShortName == "osu"); private OsuButton configureBindingsButton => Game.Settings .ChildrenOfType().SingleOrDefault()? diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 1e2283b58b72..c0de7a1d163c 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -1,15 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -37,16 +37,19 @@ public partial class KeyBindingRow : Container, IFilterable /// /// Invoked when the binding of this row is updated with a change being written. /// - public Action BindingUpdated { get; set; } - - private readonly object action; - private readonly IEnumerable bindings; + public Action? BindingUpdated { get; init; } - private const float transition_time = 150; + /// + /// Whether left and right mouse button clicks should be included in the edited bindings. + /// + public bool AllowMainMouseButtons { get; init; } - private const float height = 20; + /// + /// The default key bindings for this row. + /// + public IEnumerable Defaults { get; init; } = Array.Empty(); - private const float padding = 5; + #region IFilterable private bool matchingFilter; @@ -60,24 +63,45 @@ public bool MatchingFilter } } - private Container content; + public bool FilteringActive { get; set; } - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => - content.ReceivePositionalInputAt(screenSpacePos); + public IEnumerable FilterTerms => bindings.Select(b => (LocalisableString)keyCombinationProvider.GetReadableString(b.KeyCombination)).Prepend(text.Text); - public bool FilteringActive { get; set; } + #endregion + + private readonly object action; + private readonly IEnumerable bindings; + + private Bindable isDefault { get; } = new BindableBool(true); [Resolved] - private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } + private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } = null!; - private OsuSpriteText text; - private FillFlowContainer cancelAndClearButtons; - private FillFlowContainer buttons; + [Resolved] + private RealmAccess realm { get; set; } = null!; - private Bindable isDefault { get; } = new BindableBool(true); + private Container content = null!; - public IEnumerable FilterTerms => bindings.Select(b => (LocalisableString)keyCombinationProvider.GetReadableString(b.KeyCombination)).Prepend(text.Text); + private OsuSpriteText text = null!; + private FillFlowContainer cancelAndClearButtons = null!; + private FillFlowContainer buttons = null!; + + private KeyButton? bindTarget; + + private const float transition_time = 150; + private const float height = 20; + private const float padding = 5; + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + content.ReceivePositionalInputAt(screenSpacePos); + + public override bool AcceptsFocus => bindTarget == null; + /// + /// Creates a new . + /// + /// The action that this row contains bindings for. + /// The keybindings to display in this row. public KeyBindingRow(object action, List bindings) { this.action = action; @@ -87,9 +111,6 @@ public KeyBindingRow(object action, List bindings) AutoSizeAxes = Axes.Y; } - [Resolved] - private RealmAccess realm { get; set; } - [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { @@ -205,21 +226,18 @@ protected override void OnHoverLost(HoverLostEvent e) base.OnHoverLost(e); } - public override bool AcceptsFocus => bindTarget == null; - - private KeyButton bindTarget; - - public bool AllowMainMouseButtons; - - public IEnumerable Defaults; - private bool isModifier(Key k) => k < Key.F1; protected override bool OnClick(ClickEvent e) => true; protected override bool OnMouseDown(MouseDownEvent e) { - if (!HasFocus || !bindTarget.IsHovered) + if (!HasFocus) + return base.OnMouseDown(e); + + Debug.Assert(bindTarget != null); + + if (!bindTarget.IsHovered) return base.OnMouseDown(e); if (!AllowMainMouseButtons) @@ -245,6 +263,8 @@ protected override void OnMouseUp(MouseUpEvent e) return; } + Debug.Assert(bindTarget != null); + if (bindTarget.IsHovered) finalise(false); // prevent updating bind target before clear button's action @@ -256,6 +276,8 @@ protected override bool OnScroll(ScrollEvent e) { if (HasFocus) { + Debug.Assert(bindTarget != null); + if (bindTarget.IsHovered) { bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState, e.ScrollDelta), KeyCombination.FromScrollDelta(e.ScrollDelta).First()); @@ -272,6 +294,8 @@ protected override bool OnKeyDown(KeyDownEvent e) if (!HasFocus || e.Repeat) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromKey(e.Key)); if (!isModifier(e.Key)) finalise(); @@ -294,6 +318,8 @@ protected override bool OnJoystickPress(JoystickPressEvent e) if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromJoystickButton(e.Button)); finalise(); @@ -316,6 +342,8 @@ protected override bool OnMidiDown(MidiDownEvent e) if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromMidiKey(e.Key)); finalise(); @@ -338,6 +366,8 @@ protected override bool OnTabletAuxiliaryButtonPress(TabletAuxiliaryButtonPressE if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromTabletAuxiliaryButton(e.Button)); finalise(); @@ -360,6 +390,8 @@ protected override bool OnTabletPenButtonPress(TabletPenButtonPressEvent e) if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromTabletPenButton(e.Button)); finalise(); @@ -473,10 +505,10 @@ public partial class KeyButton : Container public readonly OsuSpriteText Text; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; [Resolved] - private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } + private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } = null!; private bool isBinding; @@ -599,7 +631,7 @@ protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - if (keyCombinationProvider != null) + if (keyCombinationProvider.IsNotNull()) keyCombinationProvider.KeymapChanged -= updateKeyCombinationText; } } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index d6d4abfa92e6..8285204bb3fd 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -1,13 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Framework.Localisation; using osu.Game.Database; using osu.Game.Input.Bindings; @@ -25,9 +25,9 @@ public abstract partial class KeyBindingsSubsection : SettingsSubsection /// protected virtual bool AutoAdvanceTarget => false; - protected IEnumerable Defaults; + protected IEnumerable Defaults { get; init; } = Array.Empty(); - public RulesetInfo Ruleset { get; protected set; } + public RulesetInfo? Ruleset { get; protected set; } private readonly int? variant; @@ -41,7 +41,7 @@ protected KeyBindingsSubsection(int? variant) [BackgroundDependencyLoader] private void load(RealmAccess realm) { - string rulesetName = Ruleset?.ShortName; + string? rulesetName = Ruleset?.ShortName; var bindings = realm.Run(r => r.All() .Where(b => b.RulesetName == rulesetName && b.Variant == variant)