Merge branch 'master' into hardrock-flipping

This commit is contained in:
Dean Herbert 2017-08-23 17:00:41 +09:00 committed by GitHub
commit 1f04995a73
23 changed files with 314 additions and 245 deletions

@ -1 +1 @@
Subproject commit e2d41820b3795d97f8510a18fad5e42caeb23f0a Subproject commit 1ba1e8ef1e5ec0466632be02492023a081cb85ab

View File

@ -14,7 +14,7 @@ namespace osu.Desktop.Tests.Visual
[Test] [Test]
public override void RunTest() public override void RunTest()
{ {
using (var host = new HeadlessGameHost()) using (var host = new HeadlessGameHost(realtime: false))
host.Run(new OsuTestCaseTestRunner(this)); host.Run(new OsuTestCaseTestRunner(this));
} }

View File

@ -3,6 +3,7 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
using OpenTK; using OpenTK;
@ -40,8 +41,8 @@ namespace osu.Desktop.Tests.Visual
RelativeChildSize = new Vector2(1, 10000), RelativeChildSize = new Vector2(1, 10000),
Children = new[] Children = new[]
{ {
new DrawableNote(new Note { StartTime = 5000 }) { AccentColour = Color4.Red }, new DrawableNote(new Note { StartTime = 5000 }, ManiaAction.Key1) { AccentColour = Color4.Red },
new DrawableNote(new Note { StartTime = 6000 }) { 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, StartTime = 5000,
Duration = 1000 Duration = 1000
}) { AccentColour = Color4.Red } }, ManiaAction.Key1) { AccentColour = Color4.Red }
} }
} }
} }

View File

@ -3,57 +3,88 @@
using System; using System;
using System.Linq; using System.Linq;
using osu.Framework.Configuration; using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.Timing;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.Timing;
using OpenTK; using OpenTK;
using OpenTK.Input; using osu.Game.Rulesets;
namespace osu.Desktop.Tests.Visual namespace osu.Desktop.Tests.Visual
{ {
internal class TestCaseManiaPlayfield : OsuTestCase internal class TestCaseManiaPlayfield : OsuTestCase
{ {
private const double start_time = 500;
private const double duration = 500;
public override string Description => @"Mania playfield"; public override string Description => @"Mania playfield";
protected override double TimePerAction => 200; protected override double TimePerAction => 200;
private RulesetInfo maniaRuleset;
public TestCaseManiaPlayfield() public TestCaseManiaPlayfield()
{ {
Action<int, SpecialColumnPosition> createPlayfield = (cols, pos) => AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal));
{ AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal));
Clear(); AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left));
Add(new ManiaPlayfield(cols) AddStep("Right special style", () => createPlayfield(4, SpecialColumnPosition.Right));
{ AddStep("5 columns", () => createPlayfield(5, SpecialColumnPosition.Normal));
Anchor = Anchor.Centre, AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal));
Origin = Anchor.Centre, AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left));
SpecialColumnPosition = pos, AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right));
Scale = new Vector2(1, -1)
});
};
const double start_time = 500; AddStep("Notes with input", () => createPlayfieldWithNotes(false));
const double duration = 500; AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction));
Func<double, bool, SpeedAdjustmentContainer> createTimingChange = (time, gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) AddStep("Notes with gravity", () => createPlayfieldWithNotes(true));
AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction));
}
[BackgroundDependencyLoader]
private void load(RulesetStore rulesets)
{
maniaRuleset = rulesets.GetRuleset(3);
}
private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time)
{ {
TimingPoint = { BeatLength = 1000 } TimingPoint = { BeatLength = 1000 }
}, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic);
Action<bool> createPlayfieldWithNotes = gravity => private void createPlayfield(int cols, SpecialColumnPosition specialPos)
{
Clear();
var inputManager = new ManiaInputManager(maniaRuleset, cols) { RelativeSizeAxes = Axes.Both };
Add(inputManager);
inputManager.Add(new ManiaPlayfield(cols)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
SpecialColumnPosition = specialPos,
Scale = new Vector2(1, -1)
});
}
private void createPlayfieldWithNotes(bool gravity)
{ {
Clear(); Clear();
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both };
Add(inputManager);
ManiaPlayfield playField; ManiaPlayfield playField;
Add(playField = new ManiaPlayfield(4) inputManager.Add(playField = new ManiaPlayfield(4)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -73,7 +104,7 @@ namespace osu.Desktop.Tests.Visual
{ {
StartTime = t, StartTime = t,
Column = 0 Column = 0
}, new Bindable<Key>(Key.D))); }, ManiaAction.Key1));
if (gravity) if (gravity)
playField.Columns.ElementAt(3).Add(createTimingChange(t, true)); playField.Columns.ElementAt(3).Add(createTimingChange(t, true));
@ -82,7 +113,7 @@ namespace osu.Desktop.Tests.Visual
{ {
StartTime = t, StartTime = t,
Column = 3 Column = 3
}, new Bindable<Key>(Key.K))); }, ManiaAction.Key4));
} }
if (gravity) if (gravity)
@ -93,7 +124,7 @@ namespace osu.Desktop.Tests.Visual
StartTime = start_time, StartTime = start_time,
Duration = duration, Duration = duration,
Column = 1 Column = 1
}, new Bindable<Key>(Key.F))); }, ManiaAction.Key2));
if (gravity) if (gravity)
playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true));
@ -103,40 +134,7 @@ namespace osu.Desktop.Tests.Visual
StartTime = start_time, StartTime = start_time,
Duration = duration, Duration = duration,
Column = 2 Column = 2
}, new Bindable<Key>(Key.J))); }, ManiaAction.Key3));
};
AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal));
AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal));
AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left));
AddStep("Right special style", () => createPlayfield(4, SpecialColumnPosition.Right));
AddStep("5 columns", () => createPlayfield(5, SpecialColumnPosition.Normal));
AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal));
AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left));
AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right));
AddStep("Notes with input", () => createPlayfieldWithNotes(false));
AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction));
AddStep("Notes with gravity", () => createPlayfieldWithNotes(true));
AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction));
}
private void triggerKeyDown(Column column)
{
column.TriggerOnKeyDown(new InputState(), new KeyDownEventArgs
{
Key = column.Key,
Repeat = false
});
}
private void triggerKeyUp(Column column)
{
column.TriggerOnKeyUp(new InputState(), new KeyUpEventArgs
{
Key = column.Key
});
} }
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
@ -8,14 +9,33 @@ namespace osu.Game.Rulesets.Mania
{ {
public class ManiaInputManager : RulesetInputManager<ManiaAction> public class ManiaInputManager : RulesetInputManager<ManiaAction>
{ {
public ManiaInputManager(RulesetInfo ruleset) public ManiaInputManager(RulesetInfo ruleset, int variant)
: base(ruleset, 0, SimultaneousBindingMode.Unique) : base(ruleset, variant, SimultaneousBindingMode.Unique)
{ {
} }
} }
public enum ManiaAction 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
} }
} }

View File

@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input.Bindings;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -120,5 +121,43 @@ namespace osu.Game.Rulesets.Mania
: base(rulesetInfo) : base(rulesetInfo)
{ {
} }
public override IEnumerable<int> AvailableVariants => new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public override IEnumerable<KeyBinding> 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<KeyBinding>();
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";
} }
} }

View File

@ -5,20 +5,18 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Configuration;
using OpenTK.Input;
using osu.Framework.Input;
using OpenTK; using OpenTK;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Input.Bindings;
namespace osu.Game.Rulesets.Mania.Objects.Drawables namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
/// <summary> /// <summary>
/// Visualises a <see cref="HoldNote"/> hit object. /// Visualises a <see cref="HoldNote"/> hit object.
/// </summary> /// </summary>
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote> public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
{ {
private readonly DrawableNote head; private readonly DrawableNote head;
private readonly DrawableNote tail; private readonly DrawableNote tail;
@ -36,8 +34,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// </summary> /// </summary>
private bool hasBroken; private bool hasBroken;
public DrawableHoldNote(HoldNote hitObject, Bindable<Key> key = null) public DrawableHoldNote(HoldNote hitObject, ManiaAction action)
: base(hitObject, key) : base(hitObject, action)
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Height = (float)HitObject.Duration; Height = (float)HitObject.Duration;
@ -58,12 +56,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime),
RelativeChildSize = new Vector2(1, (float)HitObject.Duration) RelativeChildSize = new Vector2(1, (float)HitObject.Duration)
}, },
head = new DrawableHeadNote(this, key) head = new DrawableHeadNote(this, action)
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre Origin = Anchor.TopCentre
}, },
tail = new DrawableTailNote(this, key) tail = new DrawableTailNote(this, action)
{ {
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.TopCentre 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) if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime)
return false; return false;
if (args.Key != Key) if (action != Action)
return false;
if (args.Repeat)
return false; return false;
// The user has pressed during the body of the hold note, after the head note and its hit windows have passed // 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; 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 // Make sure that the user started holding the key during the hold note
if (!holdStartTime.HasValue) if (!holdStartTime.HasValue)
return false; return false;
if (args.Key != Key) if (action != Action)
return false; return false;
holdStartTime = null; holdStartTime = null;
@ -151,8 +146,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
private readonly DrawableHoldNote holdNote; private readonly DrawableHoldNote holdNote;
public DrawableHeadNote(DrawableHoldNote holdNote, Bindable<Key> key = null) public DrawableHeadNote(DrawableHoldNote holdNote, ManiaAction action)
: base(holdNote.HitObject.Head, key) : base(holdNote.HitObject.Head, action)
{ {
this.holdNote = holdNote; this.holdNote = holdNote;
@ -160,9 +155,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Y = 0; 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; return false;
// We only want to trigger a holding state from the head if the head has received a judgement // 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; private readonly DrawableHoldNote holdNote;
public DrawableTailNote(DrawableHoldNote holdNote, Bindable<Key> key = null) public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action)
: base(holdNote.HitObject.Tail, key) : base(holdNote.HitObject.Tail, action)
{ {
this.holdNote = holdNote; this.holdNote = holdNote;
@ -210,7 +205,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
tailJudgement.HasBroken = holdNote.hasBroken; 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 // Make sure that the user started holding the key during the hold note
if (!holdNote.holdStartTime.HasValue) if (!holdNote.holdStartTime.HasValue)
@ -219,7 +216,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (Judgement.Result != HitResult.None) if (Judgement.Result != HitResult.None)
return false; return false;
if (args.Key != Key) if (action != Action)
return false; return false;
UpdateJudgement(true); UpdateJudgement(true);
@ -227,12 +224,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
// Handled by the hold note, which will set holding = false // Handled by the hold note, which will set holding = false
return false; return false;
} }
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
// Tail doesn't handle key down
return false;
}
} }
} }
} }

View File

@ -2,8 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework.Configuration;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -15,17 +13,17 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// <summary> /// <summary>
/// The key that will trigger input for this hit object. /// The key that will trigger input for this hit object.
/// </summary> /// </summary>
protected Bindable<Key> Key { get; private set; } = new Bindable<Key>(); protected ManiaAction Action { get; }
public new TObject HitObject; public new TObject HitObject;
protected DrawableManiaHitObject(TObject hitObject, Bindable<Key> key = null) protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null)
: base(hitObject) : base(hitObject)
{ {
HitObject = hitObject; HitObject = hitObject;
if (key != null) if (action != null)
Key.BindTo(key); Action = action.Value;
} }
public override Color4 AccentColour public override Color4 AccentColour

View File

@ -3,10 +3,8 @@
using System; using System;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -16,12 +14,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
/// <summary> /// <summary>
/// Visualises a <see cref="Note"/> hit object. /// Visualises a <see cref="Note"/> hit object.
/// </summary> /// </summary>
public class DrawableNote : DrawableManiaHitObject<Note> public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
{ {
private readonly NotePiece headPiece; private readonly NotePiece headPiece;
public DrawableNote(Note hitObject, Bindable<Key> key = null) public DrawableNote(Note hitObject, ManiaAction action)
: base(hitObject, key) : base(hitObject, action)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = 100; 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) if (action != Action)
return false;
if (args.Key != Key)
return false;
if (args.Repeat)
return false; return false;
return UpdateJudgement(true); return UpdateJudgement(true);
} }
public virtual bool OnReleased(ManiaAction action) => false;
} }
} }

View File

@ -3,17 +3,15 @@
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Colour;
using osu.Framework.Input;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using System; using System;
using osu.Framework.Configuration; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Judgements; 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 column_width = 45;
private const float special_column_width = 70; private const float special_column_width = 70;
/// <summary> public ManiaAction Action;
/// The key that will trigger input actions for this column and hit objects contained inside it.
/// </summary>
public Bindable<Key> Key = new Bindable<Key>();
private readonly Box background; private readonly Box background;
private readonly Container hitTargetBar; 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 // For column lighting, we need to capture input events before the notes
new InputTarget new InputTarget
{ {
KeyDown = onKeyDown, Pressed = onPressed,
KeyUp = onKeyUp Released = onReleased
} }
} }
}, },
@ -199,12 +194,9 @@ namespace osu.Game.Rulesets.Mania.UI
HitObjects.Add(hitObject); HitObjects.Add(hitObject);
} }
private bool onKeyDown(InputState state, KeyDownEventArgs args) private bool onPressed(ManiaAction action)
{ {
if (args.Repeat) if (action == Action)
return false;
if (args.Key == Key)
{ {
background.FadeTo(background.Alpha + 0.2f, 50, Easing.OutQuint); background.FadeTo(background.Alpha + 0.2f, 50, Easing.OutQuint);
keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint); keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint);
@ -213,9 +205,9 @@ namespace osu.Game.Rulesets.Mania.UI
return false; 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); background.FadeTo(0.2f, 800, Easing.OutQuart);
keyIcon.ScaleTo(1f, 400, Easing.OutQuart); keyIcon.ScaleTo(1f, 400, Easing.OutQuart);
@ -227,10 +219,10 @@ namespace osu.Game.Rulesets.Mania.UI
/// <summary> /// <summary>
/// This is a simple container which delegates various input events that have to be captured before the notes. /// This is a simple container which delegates various input events that have to be captured before the notes.
/// </summary> /// </summary>
private class InputTarget : Container private class InputTarget : Container, IKeyBindingHandler<ManiaAction>
{ {
public Func<InputState, KeyDownEventArgs, bool> KeyDown; public Func<ManiaAction, bool> Pressed;
public Func<InputState, KeyUpEventArgs, bool> KeyUp; public Func<ManiaAction, bool> Released;
public InputTarget() public InputTarget()
{ {
@ -239,8 +231,8 @@ namespace osu.Game.Rulesets.Mania.UI
Alpha = 0; Alpha = 0;
} }
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => KeyDown?.Invoke(state, args) ?? false; public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false;
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => KeyUp?.Invoke(state, args) ?? false; public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false;
} }
} }
} }

View File

@ -122,12 +122,16 @@ namespace osu.Game.Rulesets.Mania.UI
} }
}; };
var currentAction = ManiaAction.Key1;
for (int i = 0; i < columnCount; i++) for (int i = 0; i < columnCount; i++)
{ {
var c = new Column(); var c = new Column();
c.Reversed.BindTo(Reversed); c.Reversed.BindTo(Reversed);
c.VisibleTimeRange.BindTo(VisibleTimeRange); c.VisibleTimeRange.BindTo(VisibleTimeRange);
c.IsSpecial = isSpecialColumn(i);
c.Action = c.IsSpecial ? ManiaAction.Special : currentAction++;
columns.Add(c); columns.Add(c);
AddNested(c); AddNested(c);
} }
@ -145,15 +149,11 @@ namespace osu.Game.Rulesets.Mania.UI
specialColumnColour = colours.BlueDark; specialColumnColour = colours.BlueDark;
// Set the special column + colour + key // 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) if (!column.IsSpecial)
continue; continue;
column.Key.Value = Key.Space;
column.AccentColour = specialColumnColour; column.AccentColour = specialColumnColour;
} }
@ -167,21 +167,6 @@ namespace osu.Game.Rulesets.Mania.UI
nonSpecialColumns[i].AccentColour = colour; nonSpecialColumns[i].AccentColour = colour;
nonSpecialColumns[nonSpecialColumns.Count - 1 - 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;
}
} }
/// <summary> /// <summary>

View File

@ -5,9 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenTK; using OpenTK;
using OpenTK.Input;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input;
@ -85,7 +83,7 @@ namespace osu.Game.Rulesets.Mania.UI
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); 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<ManiaHitObject> CreateBeatmapConverter() protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter()
{ {
@ -109,15 +107,15 @@ namespace osu.Game.Rulesets.Mania.UI
protected override DrawableHitObject<ManiaHitObject, ManiaJudgement> GetVisualRepresentation(ManiaHitObject h) protected override DrawableHitObject<ManiaHitObject, ManiaJudgement> GetVisualRepresentation(ManiaHitObject h)
{ {
Bindable<Key> key = Playfield.Columns.ElementAt(h.Column).Key; ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action;
var holdNote = h as HoldNote; var holdNote = h as HoldNote;
if (holdNote != null) if (holdNote != null)
return new DrawableHoldNote(holdNote, key); return new DrawableHoldNote(holdNote, action);
var note = h as Note; var note = h as Note;
if (note != null) if (note != null)
return new DrawableNote(note, key); return new DrawableNote(note, action);
return null; return null;
} }

View File

@ -22,7 +22,7 @@ namespace osu.Game.Input
{ {
var ruleset = info.CreateInstance(); var ruleset = info.CreateInstance();
foreach (var variant in ruleset.AvailableVariants) foreach (var variant in ruleset.AvailableVariants)
insertDefaults(ruleset.GetDefaultKeyBindings(), info.ID, variant); insertDefaults(ruleset.GetDefaultKeyBindings(variant), info.ID, variant);
} }
} }

View File

@ -3,21 +3,29 @@
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Overlays.Settings;
namespace osu.Game.Overlays.KeyBinding 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 GlobalKeyBindingsSection(KeyBindingInputManager manager)
public override string Header => name;
public GlobalKeyBindingsSection(KeyBindingInputManager manager, string name)
{ {
this.name = name; Add(new DefaultBindingsSubsection(manager));
}
private class DefaultBindingsSubsection : KeyBindingsSubsection
{
protected override string Header => string.Empty;
public DefaultBindingsSubsection(KeyBindingInputManager manager)
: base(null)
{
Defaults = manager.DefaultKeyBindings; Defaults = manager.DefaultKeyBindings;
} }
} }
}
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -22,7 +21,7 @@ namespace osu.Game.Overlays.KeyBinding
{ {
internal class KeyBindingRow : Container, IFilterable internal class KeyBindingRow : Container, IFilterable
{ {
private readonly Enum action; private readonly object action;
private readonly IEnumerable<Framework.Input.Bindings.KeyBinding> bindings; private readonly IEnumerable<Framework.Input.Bindings.KeyBinding> bindings;
private const float transition_time = 150; 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 string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray();
public KeyBindingRow(Enum action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings) public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
{ {
this.action = action; this.action = action;
this.bindings = bindings; this.bindings = bindings;

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -12,38 +11,34 @@ using OpenTK;
namespace osu.Game.Overlays.KeyBinding namespace osu.Game.Overlays.KeyBinding
{ {
public abstract class KeyBindingsSection : SettingsSection public abstract class KeyBindingsSubsection : SettingsSubsection
{ {
protected IEnumerable<Framework.Input.Bindings.KeyBinding> Defaults; protected IEnumerable<Framework.Input.Bindings.KeyBinding> Defaults;
protected RulesetInfo Ruleset; protected RulesetInfo Ruleset;
protected KeyBindingsSection() private readonly int? variant;
protected KeyBindingsSubsection(int? variant)
{ {
this.variant = variant;
FlowContent.Spacing = new Vector2(0, 1); FlowContent.Spacing = new Vector2(0, 1);
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(KeyBindingStore store) 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); var bindings = store.Query(Ruleset?.ID, variant);
foreach (Enum v in Enum.GetValues(enumType)) foreach (var defaultBinding in Defaults)
{
// one row per valid action. // 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 AllowMainMouseButtons = Ruleset != null
}); });
} }
} }
}
} }

View File

@ -2,20 +2,26 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets; using osu.Game.Rulesets;
namespace osu.Game.Overlays.KeyBinding namespace osu.Game.Overlays.KeyBinding
{ {
public class RulesetBindingsSection : KeyBindingsSection public class RulesetBindingsSection : SettingsSection
{ {
public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; public override FontAwesome Icon => FontAwesome.fa_osu_hot;
public override string Header => Ruleset.Name; public override string Header => ruleset.Name;
private readonly RulesetInfo ruleset;
public RulesetBindingsSection(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));
} }
} }
} }

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// 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);
}
}
}

View File

@ -17,7 +17,7 @@ namespace osu.Game.Overlays
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(permitNulls: true)]
private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global) private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global)
{ {
AddSection(new GlobalKeyBindingsSection(global, "Global")); AddSection(new GlobalKeyBindingsSection(global));
foreach (var ruleset in rulesets.AllRulesets) foreach (var ruleset in rulesets.AllRulesets)
AddSection(new RulesetBindingsSection(ruleset)); AddSection(new RulesetBindingsSection(ruleset));

View File

@ -7,14 +7,15 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation;
namespace osu.Game.Overlays.Settings namespace osu.Game.Overlays.Settings
{ {
public abstract class SettingsSubsection : FillFlowContainer, IHasFilterableChildren public abstract class SettingsSubsection : FillFlowContainer, IHasFilterableChildren
{ {
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => FlowContent;
private readonly Container<Drawable> content; protected readonly FillFlowContainer FlowContent;
protected abstract string Header { get; } protected abstract string Header { get; }
@ -33,6 +34,19 @@ namespace osu.Game.Overlays.Settings
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
Direction = FillDirection.Vertical; 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[] AddRangeInternal(new Drawable[]
{ {
new OsuSpriteText new OsuSpriteText
@ -41,13 +55,7 @@ namespace osu.Game.Overlays.Settings
Margin = new MarginPadding { Bottom = 10 }, Margin = new MarginPadding { Bottom = 10 },
Font = @"Exo2.0-Black", Font = @"Exo2.0-Black",
}, },
content = new FillFlowContainer FlowContent
{
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
},
}); });
} }
} }

View File

@ -63,5 +63,12 @@ namespace osu.Game.Rulesets
/// <param name="variant">A variant.</param> /// <param name="variant">A variant.</param>
/// <returns>A list of valid <see cref="KeyBinding"/>s.</returns> /// <returns>A list of valid <see cref="KeyBinding"/>s.</returns>
public virtual IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new KeyBinding[] { }; public virtual IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new KeyBinding[] { };
/// <summary>
/// Gets the name for a key binding variant. This is used for display in the settings overlay.
/// </summary>
/// <param name="variant">The variant.</param>
/// <returns>A descriptive name of the variant.</returns>
public virtual string GetVariantName(int variant) => string.Empty;
} }
} }

View File

@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.UI
/// <summary> /// <summary>
/// The key conversion input manager for this RulesetContainer. /// The key conversion input manager for this RulesetContainer.
/// </summary> /// </summary>
public readonly PassThroughInputManager KeyBindingInputManager; public PassThroughInputManager KeyBindingInputManager;
/// <summary> /// <summary>
/// Whether we are currently providing the local user a gameplay cursor. /// Whether we are currently providing the local user a gameplay cursor.
@ -76,6 +76,11 @@ namespace osu.Game.Rulesets.UI
internal RulesetContainer(Ruleset ruleset) internal RulesetContainer(Ruleset ruleset)
{ {
Ruleset = ruleset; Ruleset = ruleset;
}
[BackgroundDependencyLoader]
private void load()
{
KeyBindingInputManager = CreateInputManager(); KeyBindingInputManager = CreateInputManager();
KeyBindingInputManager.RelativeSizeAxes = Axes.Both; KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
} }
@ -244,7 +249,7 @@ namespace osu.Game.Rulesets.UI
public Playfield<TObject, TJudgement> Playfield { get; private set; } public Playfield<TObject, TJudgement> Playfield { get; private set; }
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private readonly Container content; private Container content;
private readonly List<DrawableHitObject<TObject, TJudgement>> drawableObjects = new List<DrawableHitObject<TObject, TJudgement>>(); private readonly List<DrawableHitObject<TObject, TJudgement>> drawableObjects = new List<DrawableHitObject<TObject, TJudgement>>();
@ -256,6 +261,11 @@ namespace osu.Game.Rulesets.UI
/// <param name="isForCurrentRuleset">Whether to assume the beatmap is for the current ruleset.</param> /// <param name="isForCurrentRuleset">Whether to assume the beatmap is for the current ruleset.</param>
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset)
{
}
[BackgroundDependencyLoader]
private void load()
{ {
InputManager.Add(content = new Container InputManager.Add(content = new Container
{ {
@ -264,11 +274,6 @@ namespace osu.Game.Rulesets.UI
}); });
AddInternal(InputManager); AddInternal(InputManager);
}
[BackgroundDependencyLoader]
private void load()
{
KeyBindingInputManager.Add(Playfield = CreatePlayfield()); KeyBindingInputManager.Add(Playfield = CreatePlayfield());
loadObjects(); loadObjects();

View File

@ -105,9 +105,10 @@
<Compile Include="Overlays\Chat\ChatTabControl.cs" /> <Compile Include="Overlays\Chat\ChatTabControl.cs" />
<Compile Include="Overlays\KeyBinding\GlobalKeyBindingsSection.cs" /> <Compile Include="Overlays\KeyBinding\GlobalKeyBindingsSection.cs" />
<Compile Include="Overlays\KeyBinding\KeyBindingRow.cs" /> <Compile Include="Overlays\KeyBinding\KeyBindingRow.cs" />
<Compile Include="Overlays\KeyBinding\KeyBindingsSection.cs" /> <Compile Include="Overlays\KeyBinding\KeyBindingsSubsection.cs" />
<Compile Include="Overlays\KeyBindingOverlay.cs" /> <Compile Include="Overlays\KeyBindingOverlay.cs" />
<Compile Include="Overlays\KeyBinding\RulesetBindingsSection.cs" /> <Compile Include="Overlays\KeyBinding\RulesetBindingsSection.cs" />
<Compile Include="Overlays\KeyBinding\VariantBindingsSubsection.cs" />
<Compile Include="Overlays\MainSettings.cs" /> <Compile Include="Overlays\MainSettings.cs" />
<Compile Include="Overlays\Music\CollectionsDropdown.cs" /> <Compile Include="Overlays\Music\CollectionsDropdown.cs" />
<Compile Include="Overlays\Music\FilterControl.cs" /> <Compile Include="Overlays\Music\FilterControl.cs" />