diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs index 077417577a..69489c51a1 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -1,27 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Overlays; -using osu.Game.Overlays.Settings; -using osu.Framework.Allocation; -using osu.Framework.Extensions; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Input; -using osu.Game.Rulesets; -using osu.Framework.Input.Bindings; -using osu.Game.Input.Bindings; -using OpenTK; -using OpenTK.Graphics; -using osu.Framework.Input; -using OpenTK.Input; +using osu.Game.Overlays.KeyConfiguration; namespace osu.Desktop.Tests.Visual { @@ -39,347 +19,7 @@ namespace osu.Desktop.Tests.Visual protected override void LoadComplete() { base.LoadComplete(); - configuration.Show(); } } - - public class KeyConfiguration : SettingsOverlay - { - protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(RulesetStore rulesets, GlobalBindingInputManager global) - { - AddSection(new GlobalBindingsSection(global, "Global")); - - foreach (var ruleset in rulesets.Query()) - AddSection(new RulesetBindingsSection(ruleset)); - } - - public KeyConfiguration() - : base(false) - { - } - } - - public class GlobalBindingsSection : KeyBindingsSection - { - private readonly string name; - - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => name; - - public GlobalBindingsSection(KeyBindingInputManager manager, string name) - { - this.name = name; - - Defaults = manager.DefaultMappings; - } - } - - public class RulesetBindingsSection : KeyBindingsSection - { - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => Ruleset.Name; - - public RulesetBindingsSection(RulesetInfo ruleset) - { - Ruleset = ruleset; - - Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); - } - } - - public abstract class KeyBindingsSection : SettingsSection - { - protected IEnumerable Defaults; - - protected RulesetInfo Ruleset; - - protected KeyBindingsSection() - { - FlowContent.Spacing = new Vector2(0, 1); - } - - [BackgroundDependencyLoader] - private void load(KeyBindingStore store) - { - var firstDefault = Defaults?.FirstOrDefault(); - - if (firstDefault == null) return; - - var actionType = firstDefault.Action.GetType(); - - var bindings = store.GetProcessedList(Defaults, Ruleset?.ID); - - foreach (Enum v in Enum.GetValues(actionType)) - { - Add(new KeyBindingRow(v, bindings.Where(b => (int)b.Action == (int)(object)v))); - } - } - } - - internal class KeyBindingRow : Container, IFilterable - { - private readonly Enum action; - private readonly IEnumerable bindings; - - private const float transition_time = 150; - - private const float height = 20; - - private const float padding = 5; - - private bool matchingFilter; - - public bool MatchingFilter - { - get { return matchingFilter; } - set - { - matchingFilter = value; - this.FadeTo(!matchingFilter ? 0 : 1); - } - } - - private OsuSpriteText text; - private OsuSpriteText pressAKey; - - private FillFlowContainer buttons; - - public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); - - public KeyBindingRow(Enum action, IEnumerable bindings) - { - this.action = action; - this.bindings = bindings; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Masking = true; - CornerRadius = padding; - } - - private KeyBindingStore store; - - [BackgroundDependencyLoader] - private void load(OsuColour colours, KeyBindingStore store) - { - this.store = store; - - 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, - }, - text = new OsuSpriteText - { - Text = action.GetDescription(), - Margin = new MarginPadding(padding), - }, - buttons = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }, - pressAKey = new OsuSpriteText - { - Text = "Press a key to change the binding, or ESC to cancel.", - Y = height, - Margin = new MarginPadding(padding), - Alpha = 0, - Colour = colours.YellowDark - } - }; - - reloadBindings(); - } - - private void reloadBindings() - { - buttons.Clear(); - foreach (var b in bindings) - buttons.Add(new KeyButton(b)); - } - - protected override bool OnHover(InputState state) - { - this.FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); - - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - this.FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); - - base.OnHoverLost(state); - } - - public override bool AcceptsFocus => true; - - private KeyButton bindTarget; - - protected override void OnFocus(InputState state) - { - AutoSizeDuration = 500; - AutoSizeEasing = Easing.OutQuint; - - pressAKey.FadeIn(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding(); - - base.OnFocus(state); - } - - private bool isModifier(Key k) => k < Key.F1; - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (HasFocus) - { - if (!isModifier(args.Key)) - { - bindTarget.KeyBinding.KeyCombination = new KeyCombination(state.Keyboard.Keys); - store.Update(bindTarget.KeyBinding); - GetContainingInputManager().ChangeFocus(null); - } - return true; - } - - return base.OnKeyDown(state, args); - } - - protected override void OnFocusLost(InputState state) - { - bindTarget.IsBinding = false; - bindTarget = null; - reloadBindings(); - - pressAKey.FadeOut(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; - base.OnFocusLost(state); - } - - protected override bool OnClick(InputState state) - { - bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); - if (bindTarget != null) bindTarget.IsBinding = true; - - return bindTarget != null; - } - - private class KeyButton : Container - { - public readonly KeyBinding KeyBinding; - - private readonly Box box; - public readonly OsuSpriteText Text; - - private Color4 hoverColour; - - private bool isBinding; - - public bool IsBinding - { - get { return isBinding; } - set - { - isBinding = value; - - if (value) - { - box.FadeColour(Color4.White, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - - } - else - { - box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); - } - } - } - - public KeyButton(KeyBinding keyBinding) - { - KeyBinding = keyBinding; - - Margin = new MarginPadding(padding); - - 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 = "Venera", - TextSize = 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(InputState state) - { - if (isBinding) - return false; - - box.FadeColour(hoverColour, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - if (isBinding) - return; - - box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); - - base.OnHoverLost(state); - } - } - } } diff --git a/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs new file mode 100644 index 0000000000..9d68b41045 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Input.Bindings; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public class GlobalBindingsSection : KeyBindingsSection + { + private readonly string name; + + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Header => name; + + public GlobalBindingsSection(KeyBindingInputManager manager, string name) + { + this.name = name; + + Defaults = manager.DefaultMappings; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs b/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs new file mode 100644 index 0000000000..a9ef10eae6 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs @@ -0,0 +1,284 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Input; +using OpenTK.Graphics; +using OpenTK.Input; + +namespace osu.Game.Overlays.KeyConfiguration +{ + internal class KeyBindingRow : Container, IFilterable + { + private readonly Enum action; + private readonly IEnumerable bindings; + + private const float transition_time = 150; + + private const float height = 20; + + private const float padding = 5; + + private bool matchingFilter; + + public bool MatchingFilter + { + get { return matchingFilter; } + set + { + matchingFilter = value; + this.FadeTo(!matchingFilter ? 0 : 1); + } + } + + private OsuSpriteText text; + private OsuSpriteText pressAKey; + + private FillFlowContainer buttons; + + public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); + + public KeyBindingRow(Enum action, IEnumerable bindings) + { + this.action = action; + this.bindings = bindings; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Masking = true; + CornerRadius = padding; + } + + private KeyBindingStore store; + + [BackgroundDependencyLoader] + private void load(OsuColour colours, KeyBindingStore store) + { + this.store = store; + + 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, + }, + text = new OsuSpriteText + { + Text = action.GetDescription(), + Margin = new MarginPadding(padding), + }, + buttons = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }, + pressAKey = new OsuSpriteText + { + Text = "Press a key to change binding, DEL to delete, ESC to cancel.", + Y = height, + Margin = new MarginPadding(padding), + Alpha = 0, + Colour = colours.YellowDark + } + }; + + reloadBindings(); + } + + private void reloadBindings() + { + buttons.Clear(); + foreach (var b in bindings) + buttons.Add(new KeyButton(b)); + } + + protected override bool OnHover(InputState state) + { + this.FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + this.FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + + public override bool AcceptsFocus => true; + + private KeyButton bindTarget; + + protected override void OnFocus(InputState state) + { + AutoSizeDuration = 500; + AutoSizeEasing = Easing.OutQuint; + + pressAKey.FadeIn(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding(); + + base.OnFocus(state); + } + + private bool isModifier(Key k) => k < Key.F1; + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (HasFocus && !isModifier(args.Key)) + { + bindTarget.KeyBinding.KeyCombination = args.Key == Key.Delete ? Key.Unknown : new KeyCombination(state.Keyboard.Keys); + + store.Update(bindTarget.KeyBinding); + GetContainingInputManager().ChangeFocus(null); + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override void OnFocusLost(InputState state) + { + bindTarget.IsBinding = false; + bindTarget = null; + reloadBindings(); + + pressAKey.FadeOut(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; + base.OnFocusLost(state); + } + + protected override bool OnClick(InputState state) + { + if (bindTarget != null) bindTarget.IsBinding = false; + bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); + if (bindTarget != null) bindTarget.IsBinding = true; + + return bindTarget != null; + } + + private class KeyButton : Container + { + public readonly KeyBinding KeyBinding; + + private readonly Box box; + public readonly OsuSpriteText Text; + + private Color4 hoverColour; + + private bool isBinding; + + public bool IsBinding + { + get { return isBinding; } + set + { + isBinding = value; + + if (value) + { + box.FadeColour(Color4.White, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + + } + else + { + box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); + } + } + } + + public KeyButton(KeyBinding keyBinding) + { + KeyBinding = keyBinding; + + Margin = new MarginPadding(padding); + + //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 = "Venera", + TextSize = 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(InputState state) + { + if (isBinding) + return false; + + box.FadeColour(hoverColour, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (isBinding) + return; + + box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs new file mode 100644 index 0000000000..1e574d5e55 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Input.Bindings; +using osu.Game.Input; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets; +using OpenTK; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public abstract class KeyBindingsSection : SettingsSection + { + protected IEnumerable Defaults; + + protected RulesetInfo Ruleset; + + protected KeyBindingsSection() + { + FlowContent.Spacing = new Vector2(0, 1); + } + + [BackgroundDependencyLoader] + private void load(KeyBindingStore store) + { + var firstDefault = Defaults?.FirstOrDefault(); + + if (firstDefault == null) return; + + var actionType = firstDefault.Action.GetType(); + + int? variant = null; + + // for now let's just assume a variant of zero. + // this will need to be implemented in a better way in the future. + if (Ruleset != null) + variant = 0; + + var bindings = store.Query(Ruleset?.ID, variant); + + foreach (Enum v in Enum.GetValues(actionType)) + { + Add(new KeyBindingRow(v, bindings.Where(b => (int)b.Action == (int)(object)v))); + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs b/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs new file mode 100644 index 0000000000..416f828495 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs @@ -0,0 +1,30 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Input.Bindings; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public class KeyConfiguration : SettingsOverlay + { + protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(RulesetStore rulesets, GlobalBindingInputManager global) + { + AddSection(new GlobalBindingsSection(global, "Global")); + + foreach (var ruleset in rulesets.Query()) + AddSection(new RulesetBindingsSection(ruleset)); + } + + public KeyConfiguration() + : base(false) + { + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs new file mode 100644 index 0000000000..038df5e122 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public class RulesetBindingsSection : KeyBindingsSection + { + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Header => Ruleset.Name; + + public RulesetBindingsSection(RulesetInfo ruleset) + { + Ruleset = ruleset; + + Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); + } + } +} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b324fb9f92..6eb0ece6ed 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -102,6 +102,11 @@ + + + + +