From d9f5b578bf6f81fad7037480cf8ce95ac47eadad Mon Sep 17 00:00:00 2001 From: Swords Date: Tue, 25 May 2021 21:08:40 +1000 Subject: [PATCH] Restore class names --- .../Settings/TestSceneKeyBindingPanel.cs | 42 +- .../Overlays/KeyBinding/BasicKeyBindingRow.cs | 460 ----------------- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 474 ++++++++++++++++-- .../KeyBinding/KeyBindingsSubsection.cs | 4 +- .../KeyBinding/RestorableKeyBindingRow.cs | 64 +++ 5 files changed, 522 insertions(+), 522 deletions(-) delete mode 100644 osu.Game/Overlays/KeyBinding/BasicKeyBindingRow.cs create mode 100644 osu.Game/Overlays/KeyBinding/RestorableKeyBindingRow.cs diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index face2a498d..bd3e94dffa 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -31,11 +31,11 @@ namespace osu.Game.Tests.Visual.Settings [Test] public void TestClickTwiceOnClearButton() { - BasicKeyBindingRow firstRow = null; + KeyBindingRow firstRow = null; AddStep("click first row", () => { - firstRow = panel.ChildrenOfType().First(); + firstRow = panel.ChildrenOfType().First(); InputManager.MoveMouseTo(firstRow); InputManager.Click(MouseButton.Left); @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Settings AddStep("schedule button clicks", () => { - var clearButton = firstRow.ChildrenOfType().Single(); + var clearButton = firstRow.ChildrenOfType().Single(); InputManager.MoveMouseTo(clearButton); @@ -68,22 +68,22 @@ namespace osu.Game.Tests.Visual.Settings [Test] public void TestClearButtonOnBindings() { - BasicKeyBindingRow multiBindingRow = null; + KeyBindingRow multiBindingRow = null; AddStep("click first row with two bindings", () => { - multiBindingRow = panel.ChildrenOfType().First(row => row.Defaults.Count() > 1); + multiBindingRow = panel.ChildrenOfType().First(row => row.Defaults.Count() > 1); InputManager.MoveMouseTo(multiBindingRow); InputManager.Click(MouseButton.Left); }); clickClearButton(); - AddAssert("first binding cleared", () => string.IsNullOrEmpty(multiBindingRow.ChildrenOfType().First().Text.Text.ToString())); + AddAssert("first binding cleared", () => string.IsNullOrEmpty(multiBindingRow.ChildrenOfType().First().Text.Text.ToString())); AddStep("click second binding", () => { - var target = multiBindingRow.ChildrenOfType().ElementAt(1); + var target = multiBindingRow.ChildrenOfType().ElementAt(1); InputManager.MoveMouseTo(target); InputManager.Click(MouseButton.Left); @@ -91,13 +91,13 @@ namespace osu.Game.Tests.Visual.Settings clickClearButton(); - AddAssert("second binding cleared", () => string.IsNullOrEmpty(multiBindingRow.ChildrenOfType().ElementAt(1).Text.Text.ToString())); + AddAssert("second binding cleared", () => string.IsNullOrEmpty(multiBindingRow.ChildrenOfType().ElementAt(1).Text.Text.ToString())); void clickClearButton() { AddStep("click clear button", () => { - var clearButton = multiBindingRow.ChildrenOfType().Single(); + var clearButton = multiBindingRow.ChildrenOfType().Single(); InputManager.MoveMouseTo(clearButton); InputManager.Click(MouseButton.Left); @@ -108,11 +108,11 @@ namespace osu.Game.Tests.Visual.Settings [Test] public void TestSingleBindingResetButton() { - KeyBindingRow settingsKeyBindingRow = null; + RestorableKeyBindingRow settingsKeyBindingRow = null; AddStep("click first row", () => { - settingsKeyBindingRow = panel.ChildrenOfType().First(); + settingsKeyBindingRow = panel.ChildrenOfType().First(); InputManager.MoveMouseTo(settingsKeyBindingRow); InputManager.Click(MouseButton.Left); @@ -131,17 +131,17 @@ namespace osu.Game.Tests.Visual.Settings AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha == 0); - AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.BasicKeyBindingRow.Defaults.ElementAt(0))); + AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.BasicKeyBindingRow.Defaults.ElementAt(0))); } [Test] public void TestResetAllBindingsButton() { - KeyBindingRow settingsKeyBindingRow = null; + RestorableKeyBindingRow settingsKeyBindingRow = null; AddStep("click first row", () => { - settingsKeyBindingRow = panel.ChildrenOfType().First(); + settingsKeyBindingRow = panel.ChildrenOfType().First(); InputManager.MoveMouseTo(settingsKeyBindingRow); InputManager.Click(MouseButton.Left); @@ -160,26 +160,26 @@ namespace osu.Game.Tests.Visual.Settings AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha == 0); - AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.BasicKeyBindingRow.Defaults.ElementAt(0))); + AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.BasicKeyBindingRow.Defaults.ElementAt(0))); } [Test] public void TestClickRowSelectsFirstBinding() { - BasicKeyBindingRow multiBindingRow = null; + KeyBindingRow multiBindingRow = null; AddStep("click first row with two bindings", () => { - multiBindingRow = panel.ChildrenOfType().First(row => row.Defaults.Count() > 1); + multiBindingRow = panel.ChildrenOfType().First(row => row.Defaults.Count() > 1); InputManager.MoveMouseTo(multiBindingRow); InputManager.Click(MouseButton.Left); }); - AddAssert("first binding selected", () => multiBindingRow.ChildrenOfType().First().IsBinding); + AddAssert("first binding selected", () => multiBindingRow.ChildrenOfType().First().IsBinding); AddStep("click second binding", () => { - var target = multiBindingRow.ChildrenOfType().ElementAt(1); + var target = multiBindingRow.ChildrenOfType().ElementAt(1); InputManager.MoveMouseTo(target); InputManager.Click(MouseButton.Left); @@ -187,12 +187,12 @@ namespace osu.Game.Tests.Visual.Settings AddStep("click back binding row", () => { - multiBindingRow = panel.ChildrenOfType().ElementAt(10); + multiBindingRow = panel.ChildrenOfType().ElementAt(10); InputManager.MoveMouseTo(multiBindingRow); InputManager.Click(MouseButton.Left); }); - AddAssert("first binding selected", () => multiBindingRow.ChildrenOfType().First().IsBinding); + AddAssert("first binding selected", () => multiBindingRow.ChildrenOfType().First().IsBinding); } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/BasicKeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/BasicKeyBindingRow.cs deleted file mode 100644 index 91d9aa70bd..0000000000 --- a/osu.Game/Overlays/KeyBinding/BasicKeyBindingRow.cs +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Extensions; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Input; -using osuTK; -using osuTK.Graphics; -using osuTK.Input; - -namespace osu.Game.Overlays.KeyBinding -{ - public class BasicKeyBindingRow : Container - { - private readonly object action; - private readonly IEnumerable bindings; - - private const float transition_time = 150; - - private const float height = 20; - - private const float padding = 5; - - private FillFlowContainer cancelAndClearButtons; - private FillFlowContainer buttons; - - public Bindable IsDefault { get; } = new BindableBool(true); - - public BasicKeyBindingRow(object action, IEnumerable bindings) - { - this.action = action; - this.bindings = bindings; - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Masking = true; - CornerRadius = padding; - } - - [Resolved] - private KeyBindingStore store { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - updateIsDefaultValue(); - - EdgeEffect = new EdgeEffectParameters - { - Radius = 2, - Colour = colours.YellowDark.Opacity(0), - Type = EdgeEffectType.Shadow, - Hollow = true, - }; - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, - new OsuSpriteText - { - Text = action.GetDescription(), - Margin = new MarginPadding(padding), - }, - buttons = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }, - cancelAndClearButtons = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding(padding) { Top = height + padding * 2 }, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Alpha = 0, - Spacing = new Vector2(5), - Children = new Drawable[] - { - new CancelButton { Action = finalise }, - new ClearButton { Action = clear }, - }, - } - }; - foreach (var b in bindings) - buttons.Add(new KeyButton(b)); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - IsDefault.BindValueChanged(isDefault => - { - if (isDefault.NewValue) - { - finalise(); - } - }); - } - - public void RestoreDefaults() - { - int i = 0; - - foreach (var d in Defaults) - { - var button = buttons[i++]; - button.UpdateKeyCombination(d); - store.Update(button.KeyBinding); - } - - updateIsDefaultValue(); - } - - protected override bool OnHover(HoverEvent e) - { - FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); - - 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) - return base.OnMouseDown(e); - - if (!AllowMainMouseButtons) - { - switch (e.Button) - { - case MouseButton.Left: - case MouseButton.Right: - return true; - } - } - - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); - return true; - } - - protected override void OnMouseUp(MouseUpEvent e) - { - // don't do anything until the last button is released. - if (!HasFocus || e.HasAnyButtonPressed) - { - base.OnMouseUp(e); - return; - } - - if (bindTarget.IsHovered) - finalise(); - // prevent updating bind target before clear button's action - else if (!cancelAndClearButtons.Any(b => b.IsHovered)) - updateBindTarget(); - } - - protected override bool OnScroll(ScrollEvent e) - { - if (HasFocus) - { - if (bindTarget.IsHovered) - { - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState, e.ScrollDelta)); - finalise(); - return true; - } - } - - return base.OnScroll(e); - } - - protected override bool OnKeyDown(KeyDownEvent e) - { - if (!HasFocus) - return false; - - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); - if (!isModifier(e.Key)) finalise(); - - return true; - } - - protected override void OnKeyUp(KeyUpEvent e) - { - if (!HasFocus) - { - base.OnKeyUp(e); - return; - } - - finalise(); - } - - protected override bool OnJoystickPress(JoystickPressEvent e) - { - if (!HasFocus) - return false; - - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); - finalise(); - - return true; - } - - protected override void OnJoystickRelease(JoystickReleaseEvent e) - { - if (!HasFocus) - { - base.OnJoystickRelease(e); - return; - } - - finalise(); - } - - protected override bool OnMidiDown(MidiDownEvent e) - { - if (!HasFocus) - return false; - - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); - finalise(); - - return true; - } - - protected override void OnMidiUp(MidiUpEvent e) - { - if (!HasFocus) - { - base.OnMidiUp(e); - return; - } - - finalise(); - } - - private void clear() - { - if (bindTarget == null) - return; - - bindTarget.UpdateKeyCombination(InputKey.None); - finalise(); - } - - private void finalise() - { - if (bindTarget != null) - { - store.Update(bindTarget.KeyBinding); - - updateIsDefaultValue(); - - bindTarget.IsBinding = false; - Schedule(() => - { - // schedule to ensure we don't instantly get focus back on next OnMouseClick (see AcceptFocus impl.) - bindTarget = null; - }); - } - - if (HasFocus) - GetContainingInputManager().ChangeFocus(null); - - cancelAndClearButtons.FadeOut(300, Easing.OutQuint); - cancelAndClearButtons.BypassAutoSizeAxes |= Axes.Y; - } - - private void updateIsDefaultValue() => IsDefault.Value = computeIsDefaultValue(); - - private bool computeIsDefaultValue() => bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults); - - protected override void OnFocus(FocusEvent e) - { - AutoSizeDuration = 500; - AutoSizeEasing = Easing.OutQuint; - - cancelAndClearButtons.FadeIn(300, Easing.OutQuint); - cancelAndClearButtons.BypassAutoSizeAxes &= ~Axes.Y; - - updateBindTarget(); - base.OnFocus(e); - } - - protected override void OnFocusLost(FocusLostEvent e) - { - finalise(); - base.OnFocusLost(e); - } - - /// - /// Updates the bind target to the currently hovered key button or the first if clicked anywhere else. - /// - private void updateBindTarget() - { - if (bindTarget != null) bindTarget.IsBinding = false; - bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); - if (bindTarget != null) bindTarget.IsBinding = true; - } - - private class CancelButton : TriangleButton - { - public CancelButton() - { - Text = "Cancel"; - Size = new Vector2(80, 20); - } - } - - public class ClearButton : DangerousTriangleButton - { - public ClearButton() - { - Text = "Clear"; - Size = new Vector2(80, 20); - } - } - - public class KeyButton : Container - { - public readonly Framework.Input.Bindings.KeyBinding KeyBinding; - - private readonly Box box; - public readonly OsuSpriteText Text; - - private Color4 hoverColour; - - private bool isBinding; - - public bool IsBinding - { - get => isBinding; - set - { - if (value == isBinding) return; - - isBinding = value; - - updateHoverState(); - } - } - - public KeyButton(Framework.Input.Bindings.KeyBinding keyBinding) - { - KeyBinding = keyBinding; - - Margin = new MarginPadding(padding); - - // todo: use this in a meaningful way - // var isDefault = keyBinding.Action is Enum; - - Masking = true; - CornerRadius = padding; - - Height = height; - AutoSizeAxes = Axes.X; - - Children = new Drawable[] - { - new Container - { - AlwaysPresent = true, - Width = 80, - Height = height, - }, - box = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - Text = new OsuSpriteText - { - Font = OsuFont.Numeric.With(size: 10), - Margin = new MarginPadding(5), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = keyBinding.KeyCombination.ReadableString(), - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoverColour = colours.YellowDark; - } - - protected override bool OnHover(HoverEvent e) - { - updateHoverState(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - updateHoverState(); - base.OnHoverLost(e); - } - - private void updateHoverState() - { - if (isBinding) - { - box.FadeColour(Color4.White, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - } - else - { - box.FadeColour(IsHovered ? hoverColour : Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(IsHovered ? Color4.Black : Color4.White, transition_time, Easing.OutQuint); - } - } - - public void UpdateKeyCombination(KeyCombination newCombination) - { - KeyBinding.KeyCombination = newCombination; - Text.Text = KeyBinding.KeyCombination.ReadableString(); - } - } - } -} diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index f799b4810f..216eabcf67 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -1,64 +1,460 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Input; +using osuTK; +using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Overlays.KeyBinding { - public class KeyBindingRow : Container, IFilterable + public class KeyBindingRow : Container { - private readonly object key; - private readonly ICollection bindings; - public readonly BasicKeyBindingRow BasicKeyBindingRow; + private readonly object action; + private readonly IEnumerable bindings; - private bool matchingFilter; + private const float transition_time = 150; - public bool MatchingFilter + private const float height = 20; + + private const float padding = 5; + + private FillFlowContainer cancelAndClearButtons; + private FillFlowContainer buttons; + + public Bindable IsDefault { get; } = new BindableBool(true); + + public KeyBindingRow(object action, IEnumerable bindings) { - get => matchingFilter; - set + this.action = action; + this.bindings = bindings; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Masking = true; + CornerRadius = padding; + } + + [Resolved] + private KeyBindingStore store { get; set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + updateIsDefaultValue(); + + EdgeEffect = new EdgeEffectParameters { - matchingFilter = value; - this.FadeTo(!matchingFilter ? 0 : 1); + Radius = 2, + Colour = colours.YellowDark.Opacity(0), + Type = EdgeEffectType.Shadow, + Hollow = true, + }; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + new OsuSpriteText + { + Text = action.GetDescription(), + Margin = new MarginPadding(padding), + }, + buttons = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }, + cancelAndClearButtons = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding(padding) { Top = height + padding * 2 }, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Alpha = 0, + Spacing = new Vector2(5), + Children = new Drawable[] + { + new CancelButton { Action = finalise }, + new ClearButton { Action = clear }, + }, + } + }; + foreach (var b in bindings) + buttons.Add(new KeyButton(b)); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + IsDefault.BindValueChanged(isDefault => + { + if (isDefault.NewValue) + { + finalise(); + } + }); + } + + public void RestoreDefaults() + { + int i = 0; + + foreach (var d in Defaults) + { + var button = buttons[i++]; + button.UpdateKeyCombination(d); + store.Update(button.KeyBinding); + } + + updateIsDefaultValue(); + } + + protected override bool OnHover(HoverEvent e) + { + FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); + + 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) + return base.OnMouseDown(e); + + if (!AllowMainMouseButtons) + { + switch (e.Button) + { + case MouseButton.Left: + case MouseButton.Right: + return true; + } + } + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); + return true; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + // don't do anything until the last button is released. + if (!HasFocus || e.HasAnyButtonPressed) + { + base.OnMouseUp(e); + return; + } + + if (bindTarget.IsHovered) + finalise(); + // prevent updating bind target before clear button's action + else if (!cancelAndClearButtons.Any(b => b.IsHovered)) + updateBindTarget(); + } + + protected override bool OnScroll(ScrollEvent e) + { + if (HasFocus) + { + if (bindTarget.IsHovered) + { + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState, e.ScrollDelta)); + finalise(); + return true; + } + } + + return base.OnScroll(e); + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (!HasFocus) + return false; + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); + if (!isModifier(e.Key)) finalise(); + + return true; + } + + protected override void OnKeyUp(KeyUpEvent e) + { + if (!HasFocus) + { + base.OnKeyUp(e); + return; + } + + finalise(); + } + + protected override bool OnJoystickPress(JoystickPressEvent e) + { + if (!HasFocus) + return false; + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); + finalise(); + + return true; + } + + protected override void OnJoystickRelease(JoystickReleaseEvent e) + { + if (!HasFocus) + { + base.OnJoystickRelease(e); + return; + } + + finalise(); + } + + protected override bool OnMidiDown(MidiDownEvent e) + { + if (!HasFocus) + return false; + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState)); + finalise(); + + return true; + } + + protected override void OnMidiUp(MidiUpEvent e) + { + if (!HasFocus) + { + base.OnMidiUp(e); + return; + } + + finalise(); + } + + private void clear() + { + if (bindTarget == null) + return; + + bindTarget.UpdateKeyCombination(InputKey.None); + finalise(); + } + + private void finalise() + { + if (bindTarget != null) + { + store.Update(bindTarget.KeyBinding); + + updateIsDefaultValue(); + + bindTarget.IsBinding = false; + Schedule(() => + { + // schedule to ensure we don't instantly get focus back on next OnMouseClick (see AcceptFocus impl.) + bindTarget = null; + }); + } + + if (HasFocus) + GetContainingInputManager().ChangeFocus(null); + + cancelAndClearButtons.FadeOut(300, Easing.OutQuint); + cancelAndClearButtons.BypassAutoSizeAxes |= Axes.Y; + } + + private void updateIsDefaultValue() => IsDefault.Value = computeIsDefaultValue(); + + private bool computeIsDefaultValue() => bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults); + + protected override void OnFocus(FocusEvent e) + { + AutoSizeDuration = 500; + AutoSizeEasing = Easing.OutQuint; + + cancelAndClearButtons.FadeIn(300, Easing.OutQuint); + cancelAndClearButtons.BypassAutoSizeAxes &= ~Axes.Y; + + updateBindTarget(); + base.OnFocus(e); + } + + protected override void OnFocusLost(FocusLostEvent e) + { + finalise(); + base.OnFocusLost(e); + } + + /// + /// Updates the bind target to the currently hovered key button or the first if clicked anywhere else. + /// + private void updateBindTarget() + { + if (bindTarget != null) bindTarget.IsBinding = false; + bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); + if (bindTarget != null) bindTarget.IsBinding = true; + } + + private class CancelButton : TriangleButton + { + public CancelButton() + { + Text = "Cancel"; + Size = new Vector2(80, 20); } } - public bool FilteringActive { get; set; } - - public IEnumerable FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(key.ToString()); - - public KeyBindingRow(object key, ICollection bindings, RulesetInfo ruleset, IEnumerable defaults) { - this.key = key; - this.bindings = bindings; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Right = SettingsPanel.CONTENT_MARGINS }; - - InternalChildren = new Drawable[] + public class ClearButton : DangerousTriangleButton + { + public ClearButton() { - new RestoreDefaultValueButton() + Text = "Clear"; + Size = new Vector2(80, 20); + } + } + + public class KeyButton : Container + { + public readonly Framework.Input.Bindings.KeyBinding KeyBinding; + + private readonly Box box; + public readonly OsuSpriteText Text; + + private Color4 hoverColour; + + private bool isBinding; + + public bool IsBinding + { + get => isBinding; + set { - Current = BasicKeyBindingRow.IsDefault, - Action = () => { BasicKeyBindingRow.RestoreDefaults(); } - }, - new FillFlowContainer + if (value == isBinding) return; + + isBinding = value; + + updateHoverState(); + } + } + + public KeyButton(Framework.Input.Bindings.KeyBinding keyBinding) + { + KeyBinding = keyBinding; + + Margin = new MarginPadding(padding); + + // todo: use this in a meaningful way + // var isDefault = keyBinding.Action is Enum; + + Masking = true; + CornerRadius = padding; + + Height = height; + AutoSizeAxes = Axes.X; + + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, - Child = BasicKeyBindingRow = new BasicKeyBindingRow(key, bindings.Where(b => ((int)b.Action).Equals((int)key))) + new Container { - AllowMainMouseButtons = ruleset != null, - Defaults = defaults - } - }, - }; + AlwaysPresent = true, + Width = 80, + Height = height, + }, + box = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + Text = new OsuSpriteText + { + Font = OsuFont.Numeric.With(size: 10), + Margin = new MarginPadding(5), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = keyBinding.KeyCombination.ReadableString(), + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverColour = colours.YellowDark; + } + + protected override bool OnHover(HoverEvent e) + { + updateHoverState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateHoverState(); + base.OnHoverLost(e); + } + + private void updateHoverState() + { + if (isBinding) + { + box.FadeColour(Color4.White, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + } + else + { + box.FadeColour(IsHovered ? hoverColour : Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(IsHovered ? Color4.Black : Color4.White, transition_time, Easing.OutQuint); + } + } + + public void UpdateKeyCombination(KeyCombination newCombination) + { + KeyBinding.KeyCombination = newCombination; + Text.Text = KeyBinding.KeyCombination.ReadableString(); + } } } } diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index b1a5895449..fc370bd87e 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -38,12 +38,12 @@ namespace osu.Game.Overlays.KeyBinding foreach (var defaultGroup in Defaults.GroupBy(d => d.Action)) { // one row per valid action. - Add(new KeyBindingRow(defaultGroup.Key, bindings, Ruleset, defaultGroup.Select(d => d.KeyCombination))); + Add(new RestorableKeyBindingRow(defaultGroup.Key, bindings, Ruleset, defaultGroup.Select(d => d.KeyCombination))); } Add(new ResetButton { - Action = () => Children.OfType().ForEach(k => k.BasicKeyBindingRow.RestoreDefaults()) + Action = () => Children.OfType().ForEach(k => k.BasicKeyBindingRow.RestoreDefaults()) }); } } diff --git a/osu.Game/Overlays/KeyBinding/RestorableKeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/RestorableKeyBindingRow.cs new file mode 100644 index 0000000000..9bfdda727c --- /dev/null +++ b/osu.Game/Overlays/KeyBinding/RestorableKeyBindingRow.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyBinding +{ + public class RestorableKeyBindingRow : Container, IFilterable + { + private readonly object key; + private readonly ICollection bindings; + public readonly KeyBindingRow BasicKeyBindingRow; + + private bool matchingFilter; + + public bool MatchingFilter + { + get => matchingFilter; + set + { + matchingFilter = value; + this.FadeTo(!matchingFilter ? 0 : 1); + } + } + + public bool FilteringActive { get; set; } + + public IEnumerable FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(key.ToString()); + + public RestorableKeyBindingRow(object key, ICollection bindings, RulesetInfo ruleset, IEnumerable defaults) { + this.key = key; + this.bindings = bindings; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Padding = new MarginPadding { Right = SettingsPanel.CONTENT_MARGINS }; + + InternalChildren = new Drawable[] + { + new RestoreDefaultValueButton() + { + Current = BasicKeyBindingRow.IsDefault, + Action = () => { BasicKeyBindingRow.RestoreDefaults(); } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, + Child = BasicKeyBindingRow = new KeyBindingRow(key, bindings.Where(b => ((int)b.Action).Equals((int)key))) + { + AllowMainMouseButtons = ruleset != null, + Defaults = defaults + } + }, + }; + } + } +}