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/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 782fa5f69e..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; @@ -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; }