diff --git a/osu-framework b/osu-framework index e2d41820b3..1ba1e8ef1e 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e2d41820b3795d97f8510a18fad5e42caeb23f0a +Subproject commit 1ba1e8ef1e5ec0466632be02492023a081cb85ab diff --git a/osu.Desktop.Tests/Visual/OsuTestCase.cs b/osu.Desktop.Tests/Visual/OsuTestCase.cs index e54f7dbeb5..e366aecb21 100644 --- a/osu.Desktop.Tests/Visual/OsuTestCase.cs +++ b/osu.Desktop.Tests/Visual/OsuTestCase.cs @@ -14,7 +14,7 @@ namespace osu.Desktop.Tests.Visual [Test] public override void RunTest() { - using (var host = new HeadlessGameHost()) + using (var host = new HeadlessGameHost(realtime: false)) host.Run(new OsuTestCaseTestRunner(this)); } diff --git a/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs index 7dcc48c778..76235bbf19 100644 --- a/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using OpenTK; @@ -40,8 +41,8 @@ namespace osu.Desktop.Tests.Visual RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableNote(new Note { StartTime = 5000 }) { AccentColour = Color4.Red }, - new DrawableNote(new Note { StartTime = 6000 }) { AccentColour = Color4.Red } + new DrawableNote(new Note { StartTime = 5000 }, ManiaAction.Key1) { AccentColour = Color4.Red }, + new DrawableNote(new Note { StartTime = 6000 }, ManiaAction.Key1) { AccentColour = Color4.Red } } } } @@ -66,7 +67,7 @@ namespace osu.Desktop.Tests.Visual { StartTime = 5000, Duration = 1000 - }) { AccentColour = Color4.Red } + }, ManiaAction.Key1) { AccentColour = Color4.Red } } } } diff --git a/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs index ed0e5d81e9..c52594930e 100644 --- a/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs @@ -3,109 +3,34 @@ using System; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; -using osu.Framework.Input; using osu.Framework.Timing; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Timing; using OpenTK; -using OpenTK.Input; +using osu.Game.Rulesets; namespace osu.Desktop.Tests.Visual { internal class TestCaseManiaPlayfield : OsuTestCase { + private const double start_time = 500; + private const double duration = 500; + public override string Description => @"Mania playfield"; protected override double TimePerAction => 200; + private RulesetInfo maniaRuleset; + public TestCaseManiaPlayfield() { - Action createPlayfield = (cols, pos) => - { - Clear(); - Add(new ManiaPlayfield(cols) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - SpecialColumnPosition = pos, - Scale = new Vector2(1, -1) - }); - }; - - const double start_time = 500; - const double duration = 500; - - Func createTimingChange = (time, gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) - { - TimingPoint = { BeatLength = 1000 } - }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); - - Action createPlayfieldWithNotes = gravity => - { - Clear(); - - var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; - - ManiaPlayfield playField; - Add(playField = new ManiaPlayfield(4) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1, -1), - Clock = new FramedClock(rateAdjustClock) - }); - - if (!gravity) - playField.Columns.ForEach(c => c.Add(createTimingChange(0, false))); - - for (double t = start_time; t <= start_time + duration; t += 100) - { - if (gravity) - playField.Columns.ElementAt(0).Add(createTimingChange(t, true)); - - playField.Add(new DrawableNote(new Note - { - StartTime = t, - Column = 0 - }, new Bindable(Key.D))); - - if (gravity) - playField.Columns.ElementAt(3).Add(createTimingChange(t, true)); - - playField.Add(new DrawableNote(new Note - { - StartTime = t, - Column = 3 - }, new Bindable(Key.K))); - } - - if (gravity) - playField.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); - - playField.Add(new DrawableHoldNote(new HoldNote - { - StartTime = start_time, - Duration = duration, - Column = 1 - }, new Bindable(Key.F))); - - if (gravity) - playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); - - playField.Add(new DrawableHoldNote(new HoldNote - { - StartTime = start_time, - Duration = duration, - Column = 2 - }, new Bindable(Key.J))); - }; - AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal)); AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal)); AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left)); @@ -122,21 +47,94 @@ namespace osu.Desktop.Tests.Visual AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction)); } - private void triggerKeyDown(Column column) + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) { - column.TriggerOnKeyDown(new InputState(), new KeyDownEventArgs + maniaRuleset = rulesets.GetRuleset(3); + } + + private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) + { + TimingPoint = { BeatLength = 1000 } + }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); + + private void createPlayfield(int cols, SpecialColumnPosition specialPos) + { + Clear(); + + var inputManager = new ManiaInputManager(maniaRuleset, cols) { RelativeSizeAxes = Axes.Both }; + Add(inputManager); + + inputManager.Add(new ManiaPlayfield(cols) { - Key = column.Key, - Repeat = false + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + SpecialColumnPosition = specialPos, + Scale = new Vector2(1, -1) }); } - private void triggerKeyUp(Column column) + private void createPlayfieldWithNotes(bool gravity) { - column.TriggerOnKeyUp(new InputState(), new KeyUpEventArgs + Clear(); + + var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; + + var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both }; + Add(inputManager); + + ManiaPlayfield playField; + inputManager.Add(playField = new ManiaPlayfield(4) { - Key = column.Key + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1, -1), + Clock = new FramedClock(rateAdjustClock) }); + + if (!gravity) + playField.Columns.ForEach(c => c.Add(createTimingChange(0, false))); + + for (double t = start_time; t <= start_time + duration; t += 100) + { + if (gravity) + playField.Columns.ElementAt(0).Add(createTimingChange(t, true)); + + playField.Add(new DrawableNote(new Note + { + StartTime = t, + Column = 0 + }, ManiaAction.Key1)); + + if (gravity) + playField.Columns.ElementAt(3).Add(createTimingChange(t, true)); + + playField.Add(new DrawableNote(new Note + { + StartTime = t, + Column = 3 + }, ManiaAction.Key4)); + } + + if (gravity) + playField.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); + + playField.Add(new DrawableHoldNote(new HoldNote + { + StartTime = start_time, + Duration = duration, + Column = 1 + }, ManiaAction.Key2)); + + if (gravity) + playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); + + playField.Add(new DrawableHoldNote(new HoldNote + { + StartTime = start_time, + Duration = duration, + Column = 2 + }, ManiaAction.Key3)); } } } diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index b608e4d8d6..a574bc75ec 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.ComponentModel; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.UI; @@ -8,14 +9,33 @@ namespace osu.Game.Rulesets.Mania { public class ManiaInputManager : RulesetInputManager { - public ManiaInputManager(RulesetInfo ruleset) - : base(ruleset, 0, SimultaneousBindingMode.Unique) + public ManiaInputManager(RulesetInfo ruleset, int variant) + : base(ruleset, variant, SimultaneousBindingMode.Unique) { } } public enum ManiaAction { - // placeholder + [Description("Special")] + Special, + [Description("Key 1")] + Key1 = 10, + [Description("Key 2")] + Key2, + [Description("Key 3")] + Key3, + [Description("Key 4")] + Key4, + [Description("Key 5")] + Key5, + [Description("Key 6")] + Key6, + [Description("Key 7")] + Key7, + [Description("Key 8")] + Key8, + [Description("Key 9")] + Key9 } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c7809f83ed..ed46da4f85 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Scoring; @@ -120,5 +121,43 @@ namespace osu.Game.Rulesets.Mania : base(rulesetInfo) { } + + public override IEnumerable AvailableVariants => new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + public override IEnumerable GetDefaultKeyBindings(int variant = 0) + { + var leftKeys = new[] + { + InputKey.A, + InputKey.S, + InputKey.D, + InputKey.F + }; + + var rightKeys = new[] + { + InputKey.J, + InputKey.K, + InputKey.L, + InputKey.Semicolon + }; + + ManiaAction currentKey = ManiaAction.Key1; + + var bindings = new List(); + + for (int i = leftKeys.Length - variant / 2; i < leftKeys.Length; i++) + bindings.Add(new KeyBinding(leftKeys[i], currentKey++)); + + for (int i = 0; i < variant / 2; i++) + bindings.Add(new KeyBinding(rightKeys[i], currentKey++)); + + if (variant % 2 == 1) + bindings.Add(new KeyBinding(InputKey.Space, ManiaAction.Special)); + + return bindings; + } + + public override string GetVariantName(int variant) => $"{variant}K"; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 17b0b0a607..e06f71cb64 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -5,20 +5,18 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; -using osu.Framework.Configuration; -using OpenTK.Input; -using osu.Framework.Input; using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Input.Bindings; namespace osu.Game.Rulesets.Mania.Objects.Drawables { /// /// Visualises a hit object. /// - public class DrawableHoldNote : DrawableManiaHitObject + public class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler { private readonly DrawableNote head; private readonly DrawableNote tail; @@ -36,8 +34,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; - public DrawableHoldNote(HoldNote hitObject, Bindable key = null) - : base(hitObject, key) + public DrawableHoldNote(HoldNote hitObject, ManiaAction action) + : base(hitObject, action) { RelativeSizeAxes = Axes.Both; Height = (float)HitObject.Duration; @@ -58,12 +56,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), RelativeChildSize = new Vector2(1, (float)HitObject.Duration) }, - head = new DrawableHeadNote(this, key) + head = new DrawableHeadNote(this, action) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre }, - tail = new DrawableTailNote(this, key) + tail = new DrawableTailNote(this, action) { Anchor = Anchor.BottomCentre, Origin = Anchor.TopCentre @@ -106,16 +104,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(ManiaAction action) { - // Make sure the keypress happened within the body of the hold note + // Make sure the action happened within the body of the hold note if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime) return false; - if (args.Key != Key) - return false; - - if (args.Repeat) + if (action != Action) return false; // The user has pressed during the body of the hold note, after the head note and its hit windows have passed @@ -126,13 +121,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return true; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + public bool OnReleased(ManiaAction action) { // Make sure that the user started holding the key during the hold note if (!holdStartTime.HasValue) return false; - if (args.Key != Key) + if (action != Action) return false; holdStartTime = null; @@ -151,8 +146,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { private readonly DrawableHoldNote holdNote; - public DrawableHeadNote(DrawableHoldNote holdNote, Bindable key = null) - : base(holdNote.HitObject.Head, key) + public DrawableHeadNote(DrawableHoldNote holdNote, ManiaAction action) + : base(holdNote.HitObject.Head, action) { this.holdNote = holdNote; @@ -160,9 +155,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Y = 0; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public override bool OnPressed(ManiaAction action) { - if (!base.OnKeyDown(state, args)) + if (!base.OnPressed(action)) return false; // We only want to trigger a holding state from the head if the head has received a judgement @@ -188,8 +183,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { private readonly DrawableHoldNote holdNote; - public DrawableTailNote(DrawableHoldNote holdNote, Bindable key = null) - : base(holdNote.HitObject.Tail, key) + public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action) + : base(holdNote.HitObject.Tail, action) { this.holdNote = holdNote; @@ -210,7 +205,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables tailJudgement.HasBroken = holdNote.hasBroken; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down + + public override bool OnReleased(ManiaAction action) { // Make sure that the user started holding the key during the hold note if (!holdNote.holdStartTime.HasValue) @@ -219,7 +216,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Judgement.Result != HitResult.None) return false; - if (args.Key != Key) + if (action != Action) return false; UpdateJudgement(true); @@ -227,12 +224,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // Handled by the hold note, which will set holding = false return false; } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - // Tail doesn't handle key down - return false; - } } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 10dc607ec3..bfef05ea07 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using OpenTK.Input; -using osu.Framework.Configuration; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Objects.Drawables; @@ -15,17 +13,17 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// The key that will trigger input for this hit object. /// - protected Bindable Key { get; private set; } = new Bindable(); + protected ManiaAction Action { get; } public new TObject HitObject; - protected DrawableManiaHitObject(TObject hitObject, Bindable key = null) + protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { HitObject = hitObject; - if (key != null) - Key.BindTo(key); + if (action != null) + Action = action.Value; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 9322fed3eb..c201ab7bd0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -3,10 +3,8 @@ using System; using OpenTK.Graphics; -using OpenTK.Input; -using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Objects.Drawables; @@ -16,12 +14,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Visualises a hit object. /// - public class DrawableNote : DrawableManiaHitObject + public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { private readonly NotePiece headPiece; - public DrawableNote(Note hitObject, Bindable key = null) - : base(hitObject, key) + public DrawableNote(Note hitObject, ManiaAction action) + : base(hitObject, action) { RelativeSizeAxes = Axes.X; Height = 100; @@ -81,18 +79,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public virtual bool OnPressed(ManiaAction action) { - if (Judgement.Result != HitResult.None) - return false; - - if (args.Key != Key) - return false; - - if (args.Repeat) + if (action != Action) return false; return UpdateJudgement(true); } + + public virtual bool OnReleased(ManiaAction action) => false; } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 9fbc9ba5e7..a8f5b4919d 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -3,17 +3,15 @@ using OpenTK; using OpenTK.Graphics; -using OpenTK.Input; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Colour; -using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System; -using osu.Framework.Configuration; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; @@ -32,10 +30,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - /// - /// The key that will trigger input actions for this column and hit objects contained inside it. - /// - public Bindable Key = new Bindable(); + public ManiaAction Action; private readonly Box background; private readonly Container hitTargetBar; @@ -101,8 +96,8 @@ namespace osu.Game.Rulesets.Mania.UI // For column lighting, we need to capture input events before the notes new InputTarget { - KeyDown = onKeyDown, - KeyUp = onKeyUp + Pressed = onPressed, + Released = onReleased } } }, @@ -199,12 +194,9 @@ namespace osu.Game.Rulesets.Mania.UI HitObjects.Add(hitObject); } - private bool onKeyDown(InputState state, KeyDownEventArgs args) + private bool onPressed(ManiaAction action) { - if (args.Repeat) - return false; - - if (args.Key == Key) + if (action == Action) { background.FadeTo(background.Alpha + 0.2f, 50, Easing.OutQuint); keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint); @@ -213,9 +205,9 @@ namespace osu.Game.Rulesets.Mania.UI return false; } - private bool onKeyUp(InputState state, KeyUpEventArgs args) + private bool onReleased(ManiaAction action) { - if (args.Key == Key) + if (action == Action) { background.FadeTo(0.2f, 800, Easing.OutQuart); keyIcon.ScaleTo(1f, 400, Easing.OutQuart); @@ -227,10 +219,10 @@ namespace osu.Game.Rulesets.Mania.UI /// /// This is a simple container which delegates various input events that have to be captured before the notes. /// - private class InputTarget : Container + private class InputTarget : Container, IKeyBindingHandler { - public Func KeyDown; - public Func KeyUp; + public Func Pressed; + public Func Released; public InputTarget() { @@ -239,8 +231,8 @@ namespace osu.Game.Rulesets.Mania.UI Alpha = 0; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => KeyDown?.Invoke(state, args) ?? false; - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => KeyUp?.Invoke(state, args) ?? false; + public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false; + public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false; } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 0c9351cad2..be14585354 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -122,12 +122,16 @@ namespace osu.Game.Rulesets.Mania.UI } }; + var currentAction = ManiaAction.Key1; for (int i = 0; i < columnCount; i++) { var c = new Column(); c.Reversed.BindTo(Reversed); c.VisibleTimeRange.BindTo(VisibleTimeRange); + c.IsSpecial = isSpecialColumn(i); + c.Action = c.IsSpecial ? ManiaAction.Special : currentAction++; + columns.Add(c); AddNested(c); } @@ -145,15 +149,11 @@ namespace osu.Game.Rulesets.Mania.UI specialColumnColour = colours.BlueDark; // Set the special column + colour + key - for (int i = 0; i < columnCount; i++) + foreach (var column in Columns) { - Column column = Columns.ElementAt(i); - column.IsSpecial = isSpecialColumn(i); - if (!column.IsSpecial) continue; - column.Key.Value = Key.Space; column.AccentColour = specialColumnColour; } @@ -167,21 +167,6 @@ namespace osu.Game.Rulesets.Mania.UI nonSpecialColumns[i].AccentColour = colour; nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour; } - - // We'll set the keys for non-special columns in another separate loop because it's not mirrored like the above colours - // Todo: This needs to go when we get to bindings and use Button1, ..., ButtonN instead - for (int i = 0; i < nonSpecialColumns.Count; i++) - { - Column column = nonSpecialColumns[i]; - - int keyOffset = default_keys.Length / 2 - nonSpecialColumns.Count / 2 + i; - if (keyOffset >= 0 && keyOffset < default_keys.Length) - column.Key.Value = default_keys[keyOffset]; - else - // There is no default key defined for this column. Let's set this to Unknown for now - // however note that this will be gone after bindings are in place - column.Key.Value = Key.Unknown; - } } /// diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 0e750a348e..5a3da6d074 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -5,9 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenTK; -using OpenTK.Input; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -85,7 +83,7 @@ namespace osu.Game.Rulesets.Mania.UI public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); - public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo); + public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, availableColumns); protected override BeatmapConverter CreateBeatmapConverter() { @@ -109,15 +107,15 @@ namespace osu.Game.Rulesets.Mania.UI protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { - Bindable key = Playfield.Columns.ElementAt(h.Column).Key; + ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action; var holdNote = h as HoldNote; if (holdNote != null) - return new DrawableHoldNote(holdNote, key); + return new DrawableHoldNote(holdNote, action); var note = h as Note; if (note != null) - return new DrawableNote(note, key); + return new DrawableNote(note, action); return null; } diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 56302acafe..c5ba1683dd 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -22,7 +22,7 @@ namespace osu.Game.Input { var ruleset = info.CreateInstance(); foreach (var variant in ruleset.AvailableVariants) - insertDefaults(ruleset.GetDefaultKeyBindings(), info.ID, variant); + insertDefaults(ruleset.GetDefaultKeyBindings(variant), info.ID, variant); } } diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index 7dd9919e5d..8ebd4ac545 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -3,21 +3,29 @@ using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Overlays.Settings; namespace osu.Game.Overlays.KeyBinding { - public class GlobalKeyBindingsSection : KeyBindingsSection + public class GlobalKeyBindingsSection : SettingsSection { - private readonly string name; + public override FontAwesome Icon => FontAwesome.fa_osu_hot; + public override string Header => "Global"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => name; - - public GlobalKeyBindingsSection(KeyBindingInputManager manager, string name) + public GlobalKeyBindingsSection(KeyBindingInputManager manager) { - this.name = name; + Add(new DefaultBindingsSubsection(manager)); + } - Defaults = manager.DefaultKeyBindings; + private class DefaultBindingsSubsection : KeyBindingsSubsection + { + protected override string Header => string.Empty; + + public DefaultBindingsSubsection(KeyBindingInputManager manager) + : base(null) + { + Defaults = manager.DefaultKeyBindings; + } } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 6c697c8660..c182382d70 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -1,7 +1,6 @@ // 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; @@ -22,7 +21,7 @@ namespace osu.Game.Overlays.KeyBinding { internal class KeyBindingRow : Container, IFilterable { - private readonly Enum action; + private readonly object action; private readonly IEnumerable bindings; private const float transition_time = 150; @@ -50,7 +49,7 @@ namespace osu.Game.Overlays.KeyBinding public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); - public KeyBindingRow(Enum action, IEnumerable bindings) + public KeyBindingRow(object action, IEnumerable bindings) { this.action = action; this.bindings = bindings; diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs similarity index 57% rename from osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs rename to osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 44c28ee9c8..38a5b1a171 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -1,7 +1,6 @@ // 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; @@ -12,38 +11,34 @@ using OpenTK; namespace osu.Game.Overlays.KeyBinding { - public abstract class KeyBindingsSection : SettingsSection + public abstract class KeyBindingsSubsection : SettingsSubsection { protected IEnumerable Defaults; protected RulesetInfo Ruleset; - protected KeyBindingsSection() + private readonly int? variant; + + protected KeyBindingsSubsection(int? variant) { + this.variant = variant; + FlowContent.Spacing = new Vector2(0, 1); } [BackgroundDependencyLoader] private void load(KeyBindingStore store) { - var enumType = Defaults?.FirstOrDefault()?.Action?.GetType(); - - if (enumType == null) return; - - // for now let's just assume a variant of zero. - // this will need to be implemented in a better way in the future. - int? variant = null; - if (Ruleset != null) - variant = 0; - var bindings = store.Query(Ruleset?.ID, variant); - foreach (Enum v in Enum.GetValues(enumType)) + foreach (var defaultBinding in Defaults) + { // one row per valid action. - Add(new KeyBindingRow(v, bindings.Where(b => b.Action.Equals((int)(object)v))) + Add(new KeyBindingRow(defaultBinding.Action, bindings.Where(b => b.Action.Equals((int)defaultBinding.Action))) { AllowMainMouseButtons = Ruleset != null }); + } } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs index 20941115e3..885e149cb2 100644 --- a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs @@ -2,20 +2,26 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets; namespace osu.Game.Overlays.KeyBinding { - public class RulesetBindingsSection : KeyBindingsSection + public class RulesetBindingsSection : SettingsSection { - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => Ruleset.Name; + public override FontAwesome Icon => FontAwesome.fa_osu_hot; + public override string Header => ruleset.Name; + + private readonly RulesetInfo ruleset; public RulesetBindingsSection(RulesetInfo ruleset) { - Ruleset = ruleset; + this.ruleset = ruleset; - Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); + var r = ruleset.CreateInstance(); + + foreach (var variant in r.AvailableVariants) + Add(new VariantBindingsSubsection(ruleset, variant)); } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs new file mode 100644 index 0000000000..dca5f53b4a --- /dev/null +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyBinding +{ + public class VariantBindingsSubsection : KeyBindingsSubsection + { + protected override string Header => variantName; + private readonly string variantName; + + public VariantBindingsSubsection(RulesetInfo ruleset, int variant) + : base(variant) + { + Ruleset = ruleset; + + var rulesetInstance = ruleset.CreateInstance(); + + variantName = rulesetInstance.GetVariantName(variant); + Defaults = rulesetInstance.GetDefaultKeyBindings(variant); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index 827d361099..72c653030c 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader(permitNulls: true)] private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global) { - AddSection(new GlobalKeyBindingsSection(global, "Global")); + AddSection(new GlobalKeyBindingsSection(global)); foreach (var ruleset in rulesets.AllRulesets) AddSection(new RulesetBindingsSection(ruleset)); diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index ac6d2fa239..0fbb5b92f7 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -7,14 +7,15 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; namespace osu.Game.Overlays.Settings { public abstract class SettingsSubsection : FillFlowContainer, IHasFilterableChildren { - protected override Container Content => content; + protected override Container Content => FlowContent; - private readonly Container content; + protected readonly FillFlowContainer FlowContent; protected abstract string Header { get; } @@ -33,6 +34,19 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; + + FlowContent = new FillFlowContainer + { + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + } + + [BackgroundDependencyLoader] + private void load() + { AddRangeInternal(new Drawable[] { new OsuSpriteText @@ -41,13 +55,7 @@ namespace osu.Game.Overlays.Settings Margin = new MarginPadding { Bottom = 10 }, Font = @"Exo2.0-Black", }, - content = new FillFlowContainer - { - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, + FlowContent }); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 32d958b462..c54aeb7852 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -63,5 +63,12 @@ namespace osu.Game.Rulesets /// A variant. /// A list of valid s. public virtual IEnumerable GetDefaultKeyBindings(int variant = 0) => new KeyBinding[] { }; + + /// + /// Gets the name for a key binding variant. This is used for display in the settings overlay. + /// + /// The variant. + /// A descriptive name of the variant. + public virtual string GetVariantName(int variant) => string.Empty; } } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 8a12286bc6..84cadeb2a1 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.UI /// /// The key conversion input manager for this RulesetContainer. /// - public readonly PassThroughInputManager KeyBindingInputManager; + public PassThroughInputManager KeyBindingInputManager; /// /// Whether we are currently providing the local user a gameplay cursor. @@ -76,6 +76,11 @@ namespace osu.Game.Rulesets.UI internal RulesetContainer(Ruleset ruleset) { Ruleset = ruleset; + } + + [BackgroundDependencyLoader] + private void load() + { KeyBindingInputManager = CreateInputManager(); KeyBindingInputManager.RelativeSizeAxes = Axes.Both; } @@ -244,7 +249,7 @@ namespace osu.Game.Rulesets.UI public Playfield Playfield { get; private set; } protected override Container Content => content; - private readonly Container content; + private Container content; private readonly List> drawableObjects = new List>(); @@ -256,6 +261,11 @@ namespace osu.Game.Rulesets.UI /// Whether to assume the beatmap is for the current ruleset. protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) + { + } + + [BackgroundDependencyLoader] + private void load() { InputManager.Add(content = new Container { @@ -264,11 +274,6 @@ namespace osu.Game.Rulesets.UI }); AddInternal(InputManager); - } - - [BackgroundDependencyLoader] - private void load() - { KeyBindingInputManager.Add(Playfield = CreatePlayfield()); loadObjects(); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 11b99c1796..32a8df6357 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -105,9 +105,10 @@ - + +