diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index 5467a64b85..3a3af43cb1 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -78,7 +78,7 @@ namespace osu.Game.Tests.Visual.Navigation 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 1e2283b58b..c0de7a1d16 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input /// /// Invoked when the binding of this row is updated with a change being written. /// - public Action BindingUpdated { get; set; } + public Action? BindingUpdated { get; init; } - private readonly object action; - private readonly IEnumerable bindings; + /// + /// Whether left and right mouse button clicks should be included in the edited bindings. + /// + public bool AllowMainMouseButtons { get; init; } - private const float transition_time = 150; + /// + /// The default key bindings for this row. + /// + public IEnumerable Defaults { get; init; } = Array.Empty(); - private const float height = 20; - - private const float padding = 5; + #region IFilterable private bool matchingFilter; @@ -60,24 +63,45 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private Container content; + public bool FilteringActive { get; set; } + + public IEnumerable FilterTerms => bindings.Select(b => (LocalisableString)keyCombinationProvider.GetReadableString(b.KeyCombination)).Prepend(text.Text); + + #endregion + + private readonly object action; + private readonly IEnumerable bindings; + + private Bindable isDefault { get; } = new BindableBool(true); + + [Resolved] + private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } = null!; + + [Resolved] + private RealmAccess realm { get; set; } = null!; + + private Container content = null!; + + 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 bool FilteringActive { get; set; } - - [Resolved] - private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } - - private OsuSpriteText text; - private FillFlowContainer cancelAndClearButtons; - private FillFlowContainer buttons; - - private Bindable isDefault { get; } = new BindableBool(true); - - public IEnumerable FilterTerms => bindings.Select(b => (LocalisableString)keyCombinationProvider.GetReadableString(b.KeyCombination)).Prepend(text.Text); + 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input AutoSizeAxes = Axes.Y; } - [Resolved] - private RealmAccess realm { get; set; } - [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { @@ -205,21 +226,18 @@ namespace osu.Game.Overlays.Settings.Sections.Input 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input return; } + Debug.Assert(bindTarget != null); + if (bindTarget.IsHovered) finalise(false); // prevent updating bind target before clear button's action @@ -256,6 +276,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input { 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromJoystickButton(e.Button)); finalise(); @@ -316,6 +342,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromMidiKey(e.Key)); finalise(); @@ -338,6 +366,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromTabletAuxiliaryButton(e.Button)); finalise(); @@ -360,6 +390,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (!HasFocus) return false; + Debug.Assert(bindTarget != null); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromTabletPenButton(e.Button)); finalise(); @@ -473,10 +505,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input { 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 d6d4abfa92..8285204bb3 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input /// 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 @@ namespace osu.Game.Overlays.Settings.Sections.Input [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)