diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index f3b7d60cf0..8d27502b3c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Input.States; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; @@ -77,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Mods wasLeft = !wasLeft; } - osuInputManager.HandleCustomInput(new InputState(), state); + state.Apply(osuInputManager.CurrentState, osuInputManager); } public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) diff --git a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs index 45b5ec2c11..417b0f94d7 100644 --- a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs @@ -8,14 +8,14 @@ using System.Linq; using OpenTK.Input; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.EventArgs; using osu.Framework.Logging; using osu.Game.Screens.Play; +using OpenTK; namespace osu.Game.Tests.Visual { [Description("player pause/fail screens")] - public class TestCaseGameplayMenuOverlay : OsuTestCase + public class TestCaseGameplayMenuOverlay : ManualInputManagerTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer) }; @@ -73,12 +73,18 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => failOverlay.Show()); - AddStep("Hover first button", () => failOverlay.Buttons.First().TriggerOnMouseMove(null)); + AddStep("Hover first button", () => InputManager.MoveMouseTo(failOverlay.Buttons.First())); AddStep("Hide overlay", () => failOverlay.Hide()); AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected)); } + private void press(Key key) + { + InputManager.PressKey(key); + InputManager.ReleaseKey(key); + } + /// /// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred. /// @@ -86,7 +92,7 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => pauseOverlay.Show()); - AddStep("Press enter", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Enter })); + AddStep("Press enter", () => press(Key.Enter)); AddAssert("Overlay still open", () => pauseOverlay.State == Visibility.Visible); AddStep("Hide overlay", () => pauseOverlay.Hide()); @@ -99,7 +105,7 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => pauseOverlay.Show()); - AddStep("Up arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddStep("Up arrow", () => press(Key.Up)); AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected); AddStep("Hide overlay", () => pauseOverlay.Hide()); @@ -112,7 +118,7 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => pauseOverlay.Show()); - AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddStep("Down arrow", () => press(Key.Down)); AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); AddStep("Hide overlay", () => pauseOverlay.Hide()); @@ -125,11 +131,11 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => failOverlay.Show()); - AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddStep("Up arrow", () => press(Key.Up)); AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); - AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddStep("Up arrow", () => press(Key.Up)); AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); - AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddStep("Up arrow", () => press(Key.Up)); AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); AddStep("Hide overlay", () => failOverlay.Hide()); @@ -142,11 +148,11 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => failOverlay.Show()); - AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddStep("Down arrow", () => press(Key.Down)); AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); - AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddStep("Down arrow", () => press(Key.Down)); AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); - AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddStep("Down arrow", () => press(Key.Down)); AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); AddStep("Hide overlay", () => failOverlay.Hide()); @@ -161,8 +167,8 @@ namespace osu.Game.Tests.Visual var secondButton = pauseOverlay.Buttons.Skip(1).First(); - AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); - AddStep("Hover second button", () => secondButton.TriggerOnMouseMove(null)); + AddStep("Down arrow", () => press(Key.Down)); + AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected); AddAssert("Second button selected", () => secondButton.Selected); @@ -174,12 +180,16 @@ namespace osu.Game.Tests.Visual /// private void testKeySelectionAfterMouseSelection() { - AddStep("Show overlay", () => pauseOverlay.Show()); + AddStep("Show overlay", () => + { + pauseOverlay.Show(); + InputManager.MoveMouseTo(Vector2.Zero); + }); var secondButton = pauseOverlay.Buttons.Skip(1).First(); - AddStep("Hover second button", () => secondButton.TriggerOnMouseMove(null)); - AddStep("Up arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); + AddStep("Up arrow", () => press(Key.Up)); AddAssert("Second button not selected", () => !secondButton.Selected); AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); @@ -195,9 +205,9 @@ namespace osu.Game.Tests.Visual var secondButton = pauseOverlay.Buttons.Skip(1).First(); - AddStep("Hover second button", () => secondButton.TriggerOnMouseMove(null)); - AddStep("Unhover second button", () => secondButton.TriggerOnHoverLost(null)); - AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); + AddStep("Unhover second button", () => InputManager.MoveMouseTo(Vector2.Zero)); + AddStep("Down arrow", () => press(Key.Down)); AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); // Initial state condition AddStep("Hide overlay", () => pauseOverlay.Hide()); @@ -218,7 +228,7 @@ namespace osu.Game.Tests.Visual var lastAction = pauseOverlay.OnRetry; pauseOverlay.OnRetry = () => triggered = true; - retryButton.TriggerOnClick(); + retryButton.Click(); pauseOverlay.OnRetry = lastAction; }); @@ -235,23 +245,28 @@ namespace osu.Game.Tests.Visual AddStep("Select second button", () => { - pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }); - pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }); + press(Key.Down); + press(Key.Down); }); - var retryButton = pauseOverlay.Buttons.Skip(1).First(); - bool triggered = false; + Action lastAction = null; AddStep("Press enter", () => { - var lastAction = pauseOverlay.OnRetry; + lastAction = pauseOverlay.OnRetry; pauseOverlay.OnRetry = () => triggered = true; - - retryButton.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Enter }); - pauseOverlay.OnRetry = lastAction; + press(Key.Enter); }); - AddAssert("Action was triggered", () => triggered); + AddAssert("Action was triggered", () => + { + if (lastAction != null) + { + pauseOverlay.OnRetry = lastAction; + lastAction = null; + } + return triggered; + }); AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); } } diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index f31a687d2d..178b47ed33 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Input.EventArgs; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Screens.Play; @@ -15,7 +14,7 @@ using OpenTK.Input; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseKeyCounter : OsuTestCase + public class TestCaseKeyCounter : ManualInputManagerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -53,16 +52,16 @@ namespace osu.Game.Tests.Visual AddStep($"Press {testKey} key", () => { - rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = testKey, Repeat = false }); - rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = testKey }); + InputManager.PressKey(testKey); + InputManager.ReleaseKey(testKey); }); AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1); AddStep($"Press {testKey} key", () => { - rewindTestKeyCounterKeyboard.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = testKey, Repeat = false }); - rewindTestKeyCounterKeyboard.TriggerOnKeyUp(null, new KeyUpEventArgs { Key = testKey }); + InputManager.PressKey(testKey); + InputManager.ReleaseKey(testKey); time1 = Clock.CurrentTime; }); diff --git a/osu.Game/Input/Handlers/ReplayInputHandler.cs b/osu.Game/Input/Handlers/ReplayInputHandler.cs index 5f53868b28..0a62c6ca72 100644 --- a/osu.Game/Input/Handlers/ReplayInputHandler.cs +++ b/osu.Game/Input/Handlers/ReplayInputHandler.cs @@ -3,10 +3,13 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Input.Handlers; using osu.Framework.Input.StateChanges; +using osu.Framework.Input.StateChanges.Events; using osu.Framework.Input.States; using osu.Framework.Platform; +using osu.Game.Rulesets.UI; using OpenTK; namespace osu.Game.Input.Handlers @@ -40,7 +43,29 @@ namespace osu.Game.Input.Handlers public void Apply(InputState state, IInputStateChangeHandler handler) { - handler.HandleCustomInput(state, this); + if (!(state is RulesetInputManagerInputState inputState)) + throw new InvalidOperationException($"{nameof(ReplayState)} should only be applied to a {nameof(RulesetInputManagerInputState)}"); + + var lastPressed = inputState.LastReplayState?.PressedActions ?? new List(); + var released = lastPressed.Except(PressedActions).ToArray(); + var pressed = PressedActions.Except(lastPressed).ToArray(); + + inputState.LastReplayState = this; + + handler.HandleInputStateChange(new ReplayStateChangeEvent(state, this, released, pressed)); + } + } + + public class ReplayStateChangeEvent : InputStateChangeEvent + { + public readonly T[] ReleasedActions; + public readonly T[] PressedActions; + + public ReplayStateChangeEvent(InputState state, IInput input, T[] releasedActions, T[] pressedActions) + : base(state, input) + { + ReleasedActions = releasedActions; + PressedActions = pressedActions; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 18391c1177..b3072a02d9 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }; - Action = () => playButton.TriggerOnClick(); + Action = () => playButton.Click(); Playing.ValueChanged += newValue => progress.FadeTo(newValue ? 1 : 0, 100); } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index c9c90b4555..3f79fa98e5 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -199,7 +199,7 @@ namespace osu.Game.Overlays.Dialog switch (action) { case GlobalAction.Select: - Buttons.OfType().FirstOrDefault()?.TriggerOnClick(); + Buttons.OfType().FirstOrDefault()?.Click(); return true; } @@ -252,7 +252,7 @@ namespace osu.Game.Overlays.Dialog if (!actionInvoked) // In the case a user did not choose an action before a hide was triggered, press the last button. // This is presumed to always be a sane default "cancel" action. - buttonsContainer.Last().TriggerOnClick(); + buttonsContainer.Last().Click(); base.PopOut(); content.FadeOut(EXIT_DURATION, Easing.InSine); @@ -261,7 +261,7 @@ namespace osu.Game.Overlays.Dialog private void pressButtonAtIndex(int index) { if (index < Buttons.Count()) - Buttons.Skip(index).First().TriggerOnClick(); + Buttons.Skip(index).First().Click(); } } } diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 6e8b4494dc..b22904e724 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -155,7 +155,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - TriggerOnClick(); + Click(); return true; } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index b05efce146..af1dc98fec 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -10,7 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.EventArgs; -using osu.Framework.Input.StateChanges; +using osu.Framework.Input.StateChanges.Events; using osu.Framework.Input.States; using osu.Framework.Timing; using osu.Game.Configuration; @@ -56,33 +55,20 @@ namespace osu.Game.Rulesets.UI #region Action mapping (for replays) - private List lastPressedActions = new List(); - - public override void HandleCustomInput(InputState state, IInput input) + public override void HandleInputStateChange(InputStateChangeEvent inputStateChange) { - if (!(input is ReplayState replayState)) + if (inputStateChange is ReplayStateChangeEvent replayStateChanged) { - base.HandleCustomInput(state, input); - return; - } + foreach (var action in replayStateChanged.ReleasedActions) + KeyBindingContainer.TriggerReleased(action); - if (state is RulesetInputManagerInputState inputState) + foreach (var action in replayStateChanged.PressedActions) + KeyBindingContainer.TriggerPressed(action); + } + else { - inputState.LastReplayState = replayState; + base.HandleInputStateChange(inputStateChange); } - - // Here we handle states specifically coming from a replay source. - // These have extra action information rather than keyboard keys or mouse buttons. - - List newActions = replayState.PressedActions; - - foreach (var released in lastPressedActions.Except(newActions)) - KeyBindingContainer.TriggerReleased(released); - - foreach (var pressed in newActions.Except(lastPressedActions)) - KeyBindingContainer.TriggerPressed(pressed); - - lastPressedActions = newActions; } #endregion diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index b9a799328e..dba0a3ac50 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Menu case GlobalAction.Back: return goBack(); case GlobalAction.Select: - logo?.TriggerOnClick(); + logo?.Click(); return true; default: return false; @@ -133,7 +133,7 @@ namespace osu.Game.Screens.Menu sampleBack?.Play(); return true; case ButtonSystemState.Play: - backButton.TriggerOnClick(); + backButton.Click(); return true; default: return false; @@ -150,10 +150,10 @@ namespace osu.Game.Screens.Menu State = ButtonSystemState.TopLevel; return true; case ButtonSystemState.TopLevel: - buttonsTopLevel.First().TriggerOnClick(); + buttonsTopLevel.First().Click(); return false; case ButtonSystemState.Play: - buttonsPlay.First().TriggerOnClick(); + buttonsPlay.First().Click(); return false; } } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 1ca3bc2189..f50b3e9661 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play /// /// Action that is invoked when is triggered. /// - protected virtual Action BackAction => () => InternalButtons.Children.Last().TriggerOnClick(); + protected virtual Action BackAction => () => InternalButtons.Children.Last().Click(); public abstract string Header { get; } public abstract string Description { get; } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 2a737d974b..76c102c840 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -7,8 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.EventArgs; -using osu.Framework.Input.States; +using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Configuration; using OpenTK; @@ -152,13 +151,18 @@ namespace osu.Game.Screens.Play public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyDown(state, args)); - - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyUp(state, args)); - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => Target.Children.Any(c => c.TriggerOnMouseDown(state, args)); - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => Target.Children.Any(c => c.TriggerOnMouseUp(state, args)); + protected override bool Handle(UIEvent e) + { + switch (e) + { + case KeyDownEvent _: + case KeyUpEvent _: + case MouseDownEvent _: + case MouseUpEvent _: + return Target.Children.Any(c => c.TriggerEvent(e)); + } + return base.Handle(e); + } } } } diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index d9677e5daf..25e701294a 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Screens.Play public override string Header => "paused"; public override string Description => "you're not going to do what i think you're going to do, are ya?"; - protected override Action BackAction => () => InternalButtons.Children.First().TriggerOnClick(); + protected override Action BackAction => () => InternalButtons.Children.First().Click(); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 06837c9274..046a00d79b 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -141,7 +141,7 @@ namespace osu.Game.Screens.Play switch (action) { case GlobalAction.SkipCutscene: - button.TriggerOnClick(); + button.Click(); return true; }