diff --git a/osu-framework b/osu-framework index 67d89a3601..2a56eb0619 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 67d89a36016f98c0ede576b859a2ccafe114fce8 +Subproject commit 2a56eb0619adf654ed4927af1a4b227596c87494 diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index eada5cf532..446f9b2787 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -2,31 +2,38 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using osu.Game.Input; +using System.ComponentModel; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; using OpenTK.Input; namespace osu.Game.Rulesets.Catch { - public class CatchInputManager : ActionMappingInputManager + public class CatchInputManager : DatabasedKeyBindingInputManager { - public CatchInputManager(RulesetInfo ruleset) : base(ruleset) + public CatchInputManager(RulesetInfo ruleset) + : base(ruleset, simultaneousMode: SimultaneousBindingMode.Unique) { - Mappings = new Dictionary - { - { Key.Z, CatchAction.MoveLeft }, - { Key.Left, CatchAction.MoveLeft }, - { Key.X, CatchAction.MoveRight }, - { Key.Right, CatchAction.MoveRight }, - { Key.LShift, CatchAction.Dash }, - { Key.RShift, CatchAction.Dash }, - }; } + + protected override IEnumerable CreateDefaultMappings() => new[] + { + new KeyBinding(Key.Z, CatchAction.MoveLeft), + new KeyBinding(Key.Left, CatchAction.MoveLeft), + new KeyBinding(Key.X, CatchAction.MoveRight), + new KeyBinding(Key.Right, CatchAction.MoveRight), + new KeyBinding(Key.LShift, CatchAction.Dash), + new KeyBinding(Key.RShift, CatchAction.Dash), + }; } public enum CatchAction { + [Description("Move left")] MoveLeft, + [Description("Move right")] MoveRight, + [Description("Engage dash")] Dash } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 27cc05c47a..8469be24dd 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); - protected override PassThroughInputManager CreateActionMappingInputManager() => new CatchInputManager(Ruleset.RulesetInfo); + protected override PassThroughInputManager CreateActionMappingInputManager() => new CatchInputManager(Ruleset?.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) { diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 776f2119ab..f416f6acfb 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Catch.UI catcher.Size = new Vector2(DrawSize.Y); } - private class Catcher : Container + private class Catcher : Container, IKeyBindingHandler { private Texture texture; @@ -104,48 +104,40 @@ namespace osu.Game.Rulesets.Catch.UI OriginPosition = new Vector2(DrawWidth / 2, 10) //temporary until the sprite is aligned correctly. }; - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(CatchAction action) { - if (args.Repeat) return true; - - if (state.Data is CatchAction) + switch (action) { - switch ((CatchAction)state.Data) - { - case CatchAction.MoveLeft: - currentDirection--; - return true; - case CatchAction.MoveRight: - currentDirection++; - return true; - case CatchAction.Dash: - Dashing = true; - return true; - } + case CatchAction.MoveLeft: + currentDirection--; + return true; + case CatchAction.MoveRight: + currentDirection++; + return true; + case CatchAction.Dash: + Dashing = true; + return true; } - return base.OnKeyDown(state, args); + return false; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + public bool OnReleased(CatchAction action) { - if (state.Data is CatchAction) + switch (action) { - switch ((CatchAction)state.Data) - { - case CatchAction.MoveLeft: - currentDirection++; - return true; - case CatchAction.MoveRight: - currentDirection--; - return true; - case CatchAction.Dash: - Dashing = false; - return true; - } + case CatchAction.MoveLeft: + currentDirection++; + return true; + case CatchAction.MoveRight: + currentDirection--; + return true; + case CatchAction.Dash: + Dashing = false; + return true; } - return base.OnKeyUp(state, args); + return false; } protected override void Update() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index 3004dafda7..0c3c4f0a6d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -7,12 +7,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using OpenTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { - public class CirclePiece : Container + public class CirclePiece : Container, IKeyBindingHandler { private readonly Sprite disc; @@ -49,9 +49,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces disc.Texture = textures.Get(@"Play/osu/disc"); } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + public bool OnPressed(OsuAction action) { - return Hit?.Invoke() ?? false; + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + return IsHovered && (Hit?.Invoke() ?? false); + } + + return false; } + + public bool OnReleased(OsuAction action) => false; } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs new file mode 100644 index 0000000000..c1ee19d8c5 --- /dev/null +++ b/osu.Game.Rulesets.Osu/OsuInputManager.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.Collections.Generic; +using System.Linq; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; +using OpenTK.Input; +using KeyboardState = osu.Framework.Input.KeyboardState; +using MouseState = osu.Framework.Input.MouseState; + +namespace osu.Game.Rulesets.Osu +{ + public class OsuInputManager : DatabasedKeyBindingInputManager + { + public OsuInputManager(RulesetInfo ruleset) : base(ruleset, simultaneousMode: SimultaneousBindingMode.Unique) + { + + } + protected override void TransformState(InputState state) + { + base.TransformState(state); + + var mouse = state.Mouse as MouseState; + var keyboard = state.Keyboard as KeyboardState; + + if (mouse != null && keyboard != null) + { + if (mouse.IsPressed(MouseButton.Left)) + keyboard.Keys = keyboard.Keys.Concat(new[] { Key.LastKey + 1 }); + if (mouse.IsPressed(MouseButton.Right)) + keyboard.Keys = keyboard.Keys.Concat(new[] { Key.LastKey + 2 }); + } + } + + protected override IEnumerable CreateDefaultMappings() => new[] + { + new KeyBinding(Key.Z, OsuAction.LeftButton), + new KeyBinding(Key.X, OsuAction.RightButton), + new KeyBinding(Key.LastKey + 1, OsuAction.LeftButton), + new KeyBinding(Key.LastKey + 2, OsuAction.RightButton), + }; + } + + public enum OsuAction + { + LeftButton, + RightButton + } +} diff --git a/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs b/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs deleted file mode 100644 index 10adca4e43..0000000000 --- a/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Linq; -using osu.Framework.Input; -using OpenTK.Input; -using KeyboardState = osu.Framework.Input.KeyboardState; -using MouseState = osu.Framework.Input.MouseState; - -namespace osu.Game.Rulesets.Osu -{ - public class OsuKeyConversionInputManager : PassThroughInputManager - { - private bool leftViaKeyboard; - private bool rightViaKeyboard; - - protected override void TransformState(InputState state) - { - base.TransformState(state); - - var mouse = state.Mouse as MouseState; - var keyboard = state.Keyboard as KeyboardState; - - if (keyboard != null) - { - leftViaKeyboard = keyboard.Keys.Contains(Key.Z); - rightViaKeyboard = keyboard.Keys.Contains(Key.X); - } - - if (mouse != null) - { - if (leftViaKeyboard) - mouse.SetPressed(MouseButton.Left, true); - if (rightViaKeyboard) - mouse.SetPressed(MouseButton.Right, true); - } - } - } -} diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs similarity index 96% rename from osu.Game/Graphics/Cursor/CursorTrail.cs rename to osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 035f6f98b0..a5be6a7952 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -1,22 +1,22 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.OpenGL.Buffers; +using osu.Framework.Graphics.OpenGL.Vertices; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Textures; using osu.Framework.Input; -using OpenTK; -using System; -using osu.Framework.Graphics.OpenGL.Buffers; -using OpenTK.Graphics.ES30; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Colour; using osu.Framework.Timing; -using System.Diagnostics; -using osu.Framework.Graphics.OpenGL.Vertices; +using OpenTK; +using OpenTK.Graphics.ES30; -namespace osu.Game.Graphics.Cursor +namespace osu.Game.Rulesets.Osu.UI.Cursor { internal class CursorTrail : Drawable { diff --git a/osu.Game/Graphics/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs similarity index 82% rename from osu.Game/Graphics/Cursor/GameplayCursor.cs rename to osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs index 9f771ae56d..adfc946f86 100644 --- a/osu.Game/Graphics/Cursor/GameplayCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -10,13 +8,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Configuration; +using OpenTK; +using OpenTK.Graphics; -namespace osu.Game.Graphics.Cursor +namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class GameplayCursor : CursorContainer + public class GameplayCursor : CursorContainer, IKeyBindingHandler { protected override Drawable CreateCursor() => new OsuCursor(); @@ -25,19 +25,7 @@ namespace osu.Game.Graphics.Cursor Add(new CursorTrail { Depth = 1 }); } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - ActiveCursor.Scale = new Vector2(1); - ActiveCursor.ScaleTo(1.2f, 100, Easing.OutQuad); - return base.OnMouseDown(state, args); - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - if (!state.Mouse.HasMainButtonPressed) - ActiveCursor.ScaleTo(1, 200, Easing.OutQuad); - return base.OnMouseUp(state, args); - } + private int downCount; public class OsuCursor : Container { @@ -143,5 +131,33 @@ namespace osu.Game.Graphics.Cursor cursorContainer.Scale = new Vector2(scale); } } + + public bool OnPressed(OsuAction action) + { + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + downCount++; + ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad); + break; + } + + return false; + } + + public bool OnReleased(OsuAction action) + { + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + if (--downCount == 0) + ActiveCursor.ScaleTo(1, 200, Easing.OutQuad); + break; + } + + return false; + } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 2604b1ee8a..9b88c9d1b3 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -10,8 +10,8 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.UI; using System.Linq; -using osu.Game.Graphics.Cursor; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.UI.Cursor; namespace osu.Game.Rulesets.Osu.UI { diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index d029524a32..538b94603c 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override Playfield CreatePlayfield() => new OsuPlayfield(); - protected override PassThroughInputManager CreateActionMappingInputManager() => new OsuKeyConversionInputManager(); + protected override PassThroughInputManager CreateActionMappingInputManager() => new OsuInputManager(Ruleset?.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index b24d5b3a4a..1422ded407 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -77,7 +77,9 @@ - + + + diff --git a/osu.Game/Input/ActionMappingInputManager.cs b/osu.Game/Input/ActionMappingInputManager.cs deleted file mode 100644 index c918982fab..0000000000 --- a/osu.Game/Input/ActionMappingInputManager.cs +++ /dev/null @@ -1,74 +0,0 @@ -// 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 osu.Framework.Allocation; -using osu.Framework.Input; -using osu.Game.Rulesets; -using OpenTK.Input; - -namespace osu.Game.Input -{ - /// - /// Maps custom action data of type and stores to . - /// - /// The type of the custom action. - public class ActionMappingInputManager : PassThroughInputManager - where T : struct - { - private readonly RulesetInfo ruleset; - - private readonly int? variant; - - /// - /// Create a new instance. - /// - /// A reference to identify the current . Used to lookup mappings. Null for global mappings. - /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. - protected ActionMappingInputManager(RulesetInfo ruleset = null, int? variant = null) - { - this.ruleset = ruleset; - this.variant = variant; - } - - protected IDictionary Mappings { get; set; } - - [BackgroundDependencyLoader] - private void load(BindingStore bindings) - { - var rulesetId = ruleset?.ID; - foreach (var b in bindings.Query(b => b.RulesetID == rulesetId && b.Variant == variant)) - Mappings[b.Key] = (T)(object)b.Action; - } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - mapKey(state, args.Key); - return base.OnKeyDown(state, args); - } - - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) - { - mapKey(state, args.Key); - return base.OnKeyUp(state, args); - } - - private void mapKey(InputState state, Key key) - { - T mappedData; - if (Mappings.TryGetValue(key, out mappedData)) - state.Data = mappedData; - } - - private T parseStringRepresentation(string str) - { - T res; - - if (Enum.TryParse(str, out res)) - return res; - - return default(T); - } - } -} diff --git a/osu.Game/Input/Binding.cs b/osu.Game/Input/Binding.cs deleted file mode 100644 index e887d15a65..0000000000 --- a/osu.Game/Input/Binding.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets; -using OpenTK.Input; -using SQLite.Net.Attributes; -using SQLiteNetExtensions.Attributes; - -namespace osu.Game.Input -{ - public class Binding - { - [ForeignKey(typeof(RulesetInfo))] - public int? RulesetID { get; set; } - - [Indexed] - public int? Variant { get; set; } - - public Key Key { get; set; } - - public int Action { get; set; } - } -} \ No newline at end of file diff --git a/osu.Game/Input/BindingStore.cs b/osu.Game/Input/BindingStore.cs index aa47bee068..25a997e29d 100644 --- a/osu.Game/Input/BindingStore.cs +++ b/osu.Game/Input/BindingStore.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Platform; using osu.Game.Database; +using osu.Game.Input.Bindings; using SQLite.Net; namespace osu.Game.Input @@ -15,14 +16,32 @@ namespace osu.Game.Input { } + protected override int StoreVersion => 2; + + protected override void PerformMigration(int currentVersion, int targetVersion) + { + base.PerformMigration(currentVersion, targetVersion); + + while (currentVersion++ < targetVersion) + { + switch (currentVersion) + { + case 1: + // cannot migrate; breaking underlying changes. + Reset(); + break; + } + } + } + protected override void Prepare(bool reset = false) { - Connection.CreateTable(); + Connection.CreateTable(); } protected override Type[] ValidTypes => new[] { - typeof(Binding) + typeof(DatabasedKeyBinding) }; } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs new file mode 100644 index 0000000000..278033899c --- /dev/null +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -0,0 +1,34 @@ +// 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.Rulesets; +using SQLite.Net.Attributes; +using SQLiteNetExtensions.Attributes; + +namespace osu.Game.Input.Bindings +{ + [Table("KeyBinding")] + public class DatabasedKeyBinding : KeyBinding + { + [ForeignKey(typeof(RulesetInfo))] + public int? RulesetID { get; set; } + + [Indexed] + public int? Variant { get; set; } + + [Column("Keys")] + public string KeysString + { + get { return KeyCombination.ToString(); } + private set { KeyCombination = value; } + } + + [Column("Action")] + public new int Action + { + get { return base.Action; } + private set { base.Action = value; } + } + } +} \ No newline at end of file diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs new file mode 100644 index 0000000000..5c62f1ddc8 --- /dev/null +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -0,0 +1,57 @@ +// 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.Input.Bindings; +using osu.Game.Rulesets; + +namespace osu.Game.Input.Bindings +{ + /// + /// A KeyBindingInputManager with a database backing for custom overrides. + /// + /// The type of the custom action. + public abstract class DatabasedKeyBindingInputManager : KeyBindingInputManager + where T : struct + { + private readonly RulesetInfo ruleset; + + private readonly int? variant; + + private BindingStore store; + + /// + /// Create a new instance. + /// + /// A reference to identify the current . Used to lookup mappings. Null for global mappings. + /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. + /// Specify how to deal with multiple matches of s and s. + protected DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) + : base(simultaneousMode) + { + this.ruleset = ruleset; + this.variant = variant; + } + + [BackgroundDependencyLoader] + private void load(BindingStore bindings) + { + store = bindings; + } + + protected override void ReloadMappings() + { + // load defaults + base.ReloadMappings(); + + var rulesetId = ruleset?.ID; + + // load from database if present. + if (store != null) + { + foreach (var b in store.Query(b => b.RulesetID == rulesetId && b.Variant == variant)) + KeyBindings.Add(b); + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Input/Bindings/GlobalBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalBindingInputManager.cs new file mode 100644 index 0000000000..60a4faa8cd --- /dev/null +++ b/osu.Game/Input/Bindings/GlobalBindingInputManager.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Input; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; + +namespace osu.Game.Input.Bindings +{ + public class GlobalBindingInputManager : DatabasedKeyBindingInputManager + { + private readonly Drawable handler; + + public GlobalBindingInputManager(OsuGameBase game) + { + if (game is IKeyBindingHandler) + handler = game; + } + + protected override IEnumerable CreateDefaultMappings() => new[] + { + new KeyBinding(Key.F8, GlobalAction.ToggleChat), + new KeyBinding(Key.F9, GlobalAction.ToggleSocial), + new KeyBinding(new[] { Key.LControl, Key.LAlt, Key.R }, GlobalAction.ResetInputSettings), + new KeyBinding(new[] { Key.LControl, Key.T }, GlobalAction.ToggleToolbar), + new KeyBinding(new[] { Key.LControl, Key.O }, GlobalAction.ToggleSettings), + new KeyBinding(new[] { Key.LControl, Key.D }, GlobalAction.ToggleDirect), + }; + + protected override bool PropagateKeyDown(IEnumerable drawables, InputState state, KeyDownEventArgs args) + { + if (handler != null) + drawables = new[] { handler }.Concat(drawables); + + // always handle ourselves before all children. + return base.PropagateKeyDown(drawables, state, args); + } + + protected override bool PropagateKeyUp(IEnumerable drawables, InputState state, KeyUpEventArgs args) + { + if (handler != null) + drawables = new[] { handler }.Concat(drawables); + + // always handle ourselves before all children. + return base.PropagateKeyUp(drawables, state, args); + } + } + + public enum GlobalAction + { + [Description("Toggle chat overlay")] + ToggleChat, + [Description("Toggle social overlay")] + ToggleSocial, + [Description("Reset input settings")] + ResetInputSettings, + [Description("Toggle toolbar")] + ToggleToolbar, + [Description("Toggle settings")] + ToggleSettings, + [Description("Toggle osu!direct")] + ToggleDirect, + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 8d8c5cf26e..f54fba4a0b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -9,17 +9,16 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Framework.Input; -using OpenTK.Input; using osu.Framework.Logging; using osu.Game.Graphics.UserInterface.Volume; using osu.Framework.Allocation; -using osu.Framework.Timing; using osu.Game.Overlays.Toolbar; using osu.Game.Screens; using osu.Game.Screens.Menu; using OpenTK; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Graphics; @@ -27,10 +26,11 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Screens.Play; +using osu.Game.Input.Bindings; namespace osu.Game { - public class OsuGame : OsuGameBase + public class OsuGame : OsuGameBase, IKeyBindingHandler { public Toolbar Toolbar; @@ -169,10 +169,6 @@ namespace osu.Game volume = new VolumeControl(), overlayContent = new Container { RelativeSizeAxes = Axes.Both }, new OnScreenDisplay(), - new GlobalHotkeys //exists because UserInputManager is at a level below us. - { - Handler = globalHotkeyPressed - } }); LoadComponentAsync(screenStack = new Loader(), d => @@ -252,63 +248,43 @@ namespace osu.Game Cursor.State = Visibility.Hidden; } - private bool globalHotkeyPressed(InputState state, KeyDownEventArgs args) + public bool OnPressed(GlobalAction action) { - if (args.Repeat || intro == null) return false; + if (intro == null) return false; - switch (args.Key) + switch (action) { - case Key.F8: + case GlobalAction.ToggleChat: chat.ToggleVisibility(); return true; - case Key.F9: + case GlobalAction.ToggleSocial: social.ToggleVisibility(); return true; - case Key.PageUp: - case Key.PageDown: - var swClock = (Clock as ThrottledFrameClock)?.Source as StopwatchClock; - if (swClock == null) return false; + case GlobalAction.ResetInputSettings: + var sensitivity = frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity); - swClock.Rate *= args.Key == Key.PageUp ? 1.1f : 0.9f; - Logger.Log($@"Adjusting game clock to {swClock.Rate}", LoggingTarget.Debug); + sensitivity.Disabled = false; + sensitivity.Value = 1; + sensitivity.Disabled = true; + + frameworkConfig.Set(FrameworkSetting.ActiveInputHandlers, string.Empty); + return true; + case GlobalAction.ToggleToolbar: + Toolbar.ToggleVisibility(); + return true; + case GlobalAction.ToggleSettings: + settings.ToggleVisibility(); + return true; + case GlobalAction.ToggleDirect: + direct.ToggleVisibility(); return true; - } - - if (state.Keyboard.ControlPressed) - { - switch (args.Key) - { - case Key.R: - if (state.Keyboard.AltPressed) - { - var sensitivity = frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity); - - sensitivity.Disabled = false; - sensitivity.Value = 1; - sensitivity.Disabled = true; - - frameworkConfig.Set(FrameworkSetting.ActiveInputHandlers, string.Empty); - return true; - } - break; - case Key.T: - Toolbar.ToggleVisibility(); - return true; - case Key.O: - settings.ToggleVisibility(); - return true; - case Key.D: - if (state.Keyboard.ShiftPressed || state.Keyboard.AltPressed) - return false; - - direct.ToggleVisibility(); - return true; - } } return false; } + public bool OnReleased(GlobalAction action) => false; + public event Action ScreenChanged; private Container mainContent; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index b76235f3f4..344b23cca4 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -20,6 +20,7 @@ using SQLite.Net; using osu.Framework.Graphics.Performance; using osu.Game.Database; using osu.Game.Input; +using osu.Game.Input.Bindings; using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; @@ -187,13 +188,14 @@ namespace osu.Game Children = new Drawable[] { Cursor = new MenuCursor(), - new OsuTooltipContainer(Cursor) + new GlobalBindingInputManager(this) { RelativeSizeAxes = Axes.Both, - Child = content = new OsuContextMenuContainer + Child = new OsuTooltipContainer(Cursor) { RelativeSizeAxes = Axes.Both, - }, + Child = content = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both }, + } } } }); diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 0a410f0e0f..c66cc7beff 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Select.Options /// Colour of the button. /// Icon of the button. /// Hotkey of the button. - /// Action the button does. + /// Binding the button does. /// /// Lower depth to be put on the left, and higher to be put on the right. /// Notice this is different to ! diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index aba4384b59..7690a56378 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -92,8 +92,10 @@ - + + + @@ -120,7 +122,6 @@ - @@ -142,8 +143,6 @@ - -