diff --git a/osu.Framework.Tests/Visual/Input/TestSceneInputManager.cs b/osu.Framework.Tests/Visual/Input/TestSceneInputManager.cs index d15aeb41a9..0e533224c0 100644 --- a/osu.Framework.Tests/Visual/Input/TestSceneInputManager.cs +++ b/osu.Framework.Tests/Visual/Input/TestSceneInputManager.cs @@ -74,6 +74,9 @@ public partial class ContainingInputManagerStatusText : Container mouseStatus, keyboardStatus, joystickStatus, + touchStatus, + midiStatus, + tabletStatus, onMouseDownStatus, onMouseUpStatus, onMouseMoveStatus, @@ -100,6 +103,9 @@ public ContainingInputManagerStatusText() mouseStatus = new SmallText(), keyboardStatus = new SmallText(), joystickStatus = new SmallText(), + touchStatus = new SmallText(), + midiStatus = new SmallText(), + tabletStatus = new SmallText(), onMouseDownStatus = new SmallText { Text = "OnMouseDown 0" }, onMouseUpStatus = new SmallText { Text = "OnMouseUp 0" }, onMouseMoveStatus = new SmallText { Text = "OnMouseMove 0" }, @@ -114,11 +120,13 @@ protected override void Update() { var inputManager = GetContainingInputManager(); var currentState = inputManager!.CurrentState; - var mouse = currentState.Mouse; inputManagerStatus.Text = $"{inputManager}"; - mouseStatus.Text = $"Mouse: {mouse.Position} {mouse.Scroll} " + string.Join(' ', mouse.Buttons); + mouseStatus.Text = $"Mouse: {currentState.Mouse.Position} {currentState.Mouse.Scroll} " + string.Join(' ', currentState.Mouse.Buttons); keyboardStatus.Text = "Keyboard: " + string.Join(' ', currentState.Keyboard.Keys); joystickStatus.Text = "Joystick: " + string.Join(' ', currentState.Joystick.Buttons); + touchStatus.Text = $"Touch: {string.Join(' ', currentState.Touch.ActiveSources.Select(s => $"({s},{currentState.Touch.GetTouchPosition(s)})"))}"; + midiStatus.Text = "MIDI: " + string.Join(' ', currentState.Midi.Keys.Select(k => $"({k},{currentState.Midi.Velocities[k]})")); + tabletStatus.Text = "Tablet: " + string.Join(' ', currentState.Tablet.PenButtons) + " " + string.Join(' ', currentState.Tablet.AuxiliaryButtons); base.Update(); } diff --git a/osu.Framework.Tests/Visual/Input/TestScenePassThroughInputManager.cs b/osu.Framework.Tests/Visual/Input/TestScenePassThroughInputManager.cs index 2f01d18b3c..3b1e485bc0 100644 --- a/osu.Framework.Tests/Visual/Input/TestScenePassThroughInputManager.cs +++ b/osu.Framework.Tests/Visual/Input/TestScenePassThroughInputManager.cs @@ -50,25 +50,6 @@ private void addTestInputManagerStep() ChildrenEnumerable = Enumerable.Empty(); }); - [Test] - public void ReceiveInitialState() - { - AddStep("Press mouse left", () => InputManager.PressButton(MouseButton.Left)); - AddStep("Press A", () => InputManager.PressKey(Key.A)); - AddStep("Press Joystick", () => InputManager.PressJoystickButton(JoystickButton.Button1)); - addTestInputManagerStep(); - AddAssert("mouse left not pressed", () => !mouse.IsPressed(MouseButton.Left)); - AddAssert("A pressed", () => keyboard.IsPressed(Key.A)); - AddAssert("Joystick pressed", () => joystick.IsPressed(JoystickButton.Button1)); - AddStep("Release", () => - { - InputManager.ReleaseButton(MouseButton.Left); - InputManager.ReleaseKey(Key.A); - InputManager.ReleaseJoystickButton(JoystickButton.Button1); - }); - AddAssert("All released", () => !mouse.HasAnyButtonPressed && !keyboard.HasAnyButtonPressed && !joystick.HasAnyButtonPressed); - } - [Test] public void UseParentInputChange() { @@ -94,22 +75,7 @@ public void UseParentInputChange() } [Test] - public void TestUpReceivedOnDownFromSync() - { - addTestInputManagerStep(); - AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); - AddStep("press keyboard", () => InputManager.PressKey(Key.A)); - AddAssert("key not pressed", () => !testInputManager.CurrentState.Keyboard.Keys.HasAnyButtonPressed); - - AddStep("UseParentInput = true", () => testInputManager.UseParentInput = true); - AddAssert("key pressed", () => testInputManager.CurrentState.Keyboard.Keys.Single() == Key.A); - - AddStep("release keyboard", () => InputManager.ReleaseKey(Key.A)); - AddAssert("key released", () => !testInputManager.CurrentState.Keyboard.Keys.HasAnyButtonPressed); - } - - [Test] - public void MouseDownNoSync() + public void TestMouseDownNoSync() { addTestInputManagerStep(); AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); @@ -119,7 +85,7 @@ public void MouseDownNoSync() } [Test] - public void NoMouseUp() + public void TestNoMouseUp() { addTestInputManagerStep(); AddStep("Press left", () => InputManager.PressButton(MouseButton.Left)); @@ -134,28 +100,50 @@ public void NoMouseUp() AddAssert("mouse up count == 0", () => testInputManager.Status.MouseUpCount == 0); } + [Test] + public void TestKeyInput() + { + addTestInputManagerStep(); + AddStep("press key", () => InputManager.PressKey(Key.A)); + AddAssert("key pressed", () => testInputManager.CurrentState.Keyboard.Keys.Single() == Key.A); + + AddStep("release key", () => InputManager.ReleaseKey(Key.A)); + AddAssert("key released", () => !testInputManager.CurrentState.Keyboard.Keys.HasAnyButtonPressed); + + AddStep("press key", () => InputManager.PressKey(Key.A)); + AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); + AddStep("release key", () => InputManager.ReleaseKey(Key.A)); + AddStep("press another key", () => InputManager.PressKey(Key.B)); + + AddAssert("only first key pressed", () => testInputManager.CurrentState.Keyboard.Keys.Single() == Key.A); + + AddStep("UseParentInput = true", () => testInputManager.UseParentInput = true); + AddAssert("key released", () => !testInputManager.CurrentState.Keyboard.Keys.HasAnyButtonPressed); + } + [Test] public void TestTouchInput() { addTestInputManagerStep(); AddStep("begin first touch", () => InputManager.BeginTouch(new Touch(TouchSource.Touch1, Vector2.Zero))); - AddAssert("synced properly", () => + AddAssert("first touch active", () => testInputManager.CurrentState.Touch.ActiveSources.Single() == TouchSource.Touch1 && testInputManager.CurrentState.Touch.TouchPositions[(int)TouchSource.Touch1] == Vector2.Zero); + AddStep("end first touch", () => InputManager.EndTouch(new Touch(TouchSource.Touch1, Vector2.Zero))); + AddAssert("first touch not active", () => !testInputManager.CurrentState.Touch.ActiveSources.HasAnyButtonPressed); + + AddStep("begin first touch", () => InputManager.BeginTouch(new Touch(TouchSource.Touch1, Vector2.Zero))); AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); AddStep("end first touch", () => InputManager.EndTouch(new Touch(TouchSource.Touch1, Vector2.Zero))); AddStep("begin second touch", () => InputManager.BeginTouch(new Touch(TouchSource.Touch2, Vector2.One))); + AddAssert("only first touch active", () => + testInputManager.CurrentState.Touch.ActiveSources.Single() == TouchSource.Touch1 && + testInputManager.CurrentState.Touch.TouchPositions[(int)TouchSource.Touch1] == Vector2.Zero); + AddStep("UseParentInput = true", () => testInputManager.UseParentInput = true); - AddAssert("synced properly", () => - testInputManager.CurrentState.Touch.ActiveSources.Single() == TouchSource.Touch2 && - testInputManager.CurrentState.Touch.TouchPositions[(int)TouchSource.Touch2] == Vector2.One); - - AddStep("end second touch", () => InputManager.EndTouch(new Touch(TouchSource.Touch2, new Vector2(2)))); - AddAssert("synced properly", () => - !testInputManager.CurrentState.Touch.ActiveSources.HasAnyButtonPressed && - testInputManager.CurrentState.Touch.TouchPositions[(int)TouchSource.Touch2] == new Vector2(2)); + AddAssert("no touches active", () => !testInputManager.CurrentState.Touch.ActiveSources.HasAnyButtonPressed); } [Test] @@ -164,20 +152,55 @@ public void TestMidiInput() addTestInputManagerStep(); AddStep("press C3", () => InputManager.PressMidiKey(MidiKey.C3, 70)); - AddAssert("synced properly", () => + AddAssert("C3 pressed", () => testInputManager.CurrentState.Midi.Keys.IsPressed(MidiKey.C3) && testInputManager.CurrentState.Midi.Velocities[MidiKey.C3] == 70); + AddStep("release C3", () => InputManager.ReleaseMidiKey(MidiKey.C3, 40)); + AddAssert("C3 released", () => !testInputManager.CurrentState.Midi.Keys.HasAnyButtonPressed); + + AddStep("press C3", () => InputManager.PressMidiKey(MidiKey.C3, 70)); AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); AddStep("release C3", () => InputManager.ReleaseMidiKey(MidiKey.C3, 40)); AddStep("press F#3", () => InputManager.PressMidiKey(MidiKey.FSharp3, 65)); + AddAssert("only C3 pressed", () => + testInputManager.CurrentState.Midi.Keys.Single() == MidiKey.C3 + && testInputManager.CurrentState.Midi.Velocities[MidiKey.C3] == 70); + + AddStep("UseParentInput = true", () => testInputManager.UseParentInput = true); + AddAssert("C3 released", () => !testInputManager.CurrentState.Midi.Keys.HasAnyButtonPressed); + } + + [Test] + public void TestTabletButtonInput() + { + addTestInputManagerStep(); + + AddStep("press primary pen button", () => InputManager.PressTabletPenButton(TabletPenButton.Primary)); + AddStep("press auxiliary button 4", () => InputManager.PressTabletAuxiliaryButton(TabletAuxiliaryButton.Button4)); + AddAssert("primary pen button pressed", () => testInputManager.CurrentState.Tablet.PenButtons.Single() == TabletPenButton.Primary); + AddAssert("auxiliary button 4 pressed", () => testInputManager.CurrentState.Tablet.AuxiliaryButtons.Single() == TabletAuxiliaryButton.Button4); + + AddStep("release primary pen button", () => InputManager.ReleaseTabletPenButton(TabletPenButton.Primary)); + AddStep("release auxiliary button 4", () => InputManager.ReleaseTabletAuxiliaryButton(TabletAuxiliaryButton.Button4)); + AddAssert("primary pen button pressed", () => !testInputManager.CurrentState.Tablet.PenButtons.HasAnyButtonPressed); + AddAssert("auxiliary button 4 pressed", () => !testInputManager.CurrentState.Tablet.AuxiliaryButtons.HasAnyButtonPressed); + + AddStep("press primary pen button", () => InputManager.PressTabletPenButton(TabletPenButton.Primary)); + AddStep("press auxiliary button 4", () => InputManager.PressTabletAuxiliaryButton(TabletAuxiliaryButton.Button4)); + AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); + AddStep("release primary pen button", () => InputManager.ReleaseTabletPenButton(TabletPenButton.Primary)); + AddStep("release auxiliary button 4", () => InputManager.ReleaseTabletAuxiliaryButton(TabletAuxiliaryButton.Button4)); + AddStep("press secondary pen button", () => InputManager.PressTabletPenButton(TabletPenButton.Secondary)); + AddStep("press auxiliary button 2", () => InputManager.PressTabletAuxiliaryButton(TabletAuxiliaryButton.Button2)); + + AddAssert("only primary pen button pressed", () => testInputManager.CurrentState.Tablet.PenButtons.Single() == TabletPenButton.Primary); + AddAssert("only auxiliary button 4 pressed", () => testInputManager.CurrentState.Tablet.AuxiliaryButtons.Single() == TabletAuxiliaryButton.Button4); + AddStep("UseParentInput = true", () => testInputManager.UseParentInput = true); - AddAssert("synced properly", () => - !testInputManager.CurrentState.Midi.Keys.IsPressed(MidiKey.C3) && - testInputManager.CurrentState.Midi.Velocities[MidiKey.C3] == 40 && - testInputManager.CurrentState.Midi.Keys.IsPressed(MidiKey.FSharp3) && - testInputManager.CurrentState.Midi.Velocities[MidiKey.FSharp3] == 65); + AddAssert("primary pen button released", () => !testInputManager.CurrentState.Tablet.PenButtons.HasAnyButtonPressed); + AddAssert("auxiliary button 4 released", () => !testInputManager.CurrentState.Tablet.AuxiliaryButtons.HasAnyButtonPressed); } [Test] @@ -217,30 +240,6 @@ public void TestMouseTouchProductionOnPassThrough() AddAssert("pass-through handled mouse", () => testInputManager.CurrentState.Mouse.Buttons.Single() == MouseButton.Left); } - [Test] - public void TestTabletButtonInput() - { - addTestInputManagerStep(); - - AddStep("press primary pen button", () => InputManager.PressTabletPenButton(TabletPenButton.Primary)); - AddStep("press auxiliary button 4", () => InputManager.PressTabletAuxiliaryButton(TabletAuxiliaryButton.Button4)); - - AddStep("UseParentInput = false", () => testInputManager.UseParentInput = false); - - AddStep("release primary pen button", () => InputManager.ReleaseTabletPenButton(TabletPenButton.Primary)); - AddStep("press tertiary pen button", () => InputManager.PressTabletPenButton(TabletPenButton.Tertiary)); - AddStep("release auxiliary button 4", () => InputManager.ReleaseTabletAuxiliaryButton(TabletAuxiliaryButton.Button4)); - AddStep("press auxiliary button 2", () => InputManager.PressTabletAuxiliaryButton(TabletAuxiliaryButton.Button2)); - - AddStep("UseParentInput = true", () => testInputManager.UseParentInput = true); - AddAssert("pen buttons synced properly", () => - !testInputManager.CurrentState.Tablet.PenButtons.Contains(TabletPenButton.Primary) - && testInputManager.CurrentState.Tablet.PenButtons.Contains(TabletPenButton.Tertiary)); - AddAssert("auxiliary buttons synced properly", () => - !testInputManager.CurrentState.Tablet.AuxiliaryButtons.Contains(TabletAuxiliaryButton.Button4) - && testInputManager.CurrentState.Tablet.AuxiliaryButtons.Contains(TabletAuxiliaryButton.Button2)); - } - public partial class TestInputManager : ManualInputManager { public readonly TestSceneInputManager.ContainingInputManagerStatusText Status; diff --git a/osu.Framework/Input/PassThroughInputManager.cs b/osu.Framework/Input/PassThroughInputManager.cs index 5856141d71..587993ad9a 100644 --- a/osu.Framework/Input/PassThroughInputManager.cs +++ b/osu.Framework/Input/PassThroughInputManager.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -29,6 +27,8 @@ namespace osu.Framework.Input /// public partial class PassThroughInputManager : CustomInputManager, IRequireHighFrequencyMousePosition { + private bool useParentInput = true; + /// /// If there's an InputManager above us, decide whether we should use their available state. /// @@ -42,13 +42,22 @@ public virtual bool UseParentInput useParentInput = value; if (UseParentInput) - Sync(); + { + syncReleasedInputs(); + syncJoystickAxes(); + } } } - private bool useParentInput = true; + private InputManager? parentInputManager; + + protected override void LoadComplete() + { + base.LoadComplete(); + parentInputManager = GetContainingInputManager(); + } - public override bool HandleHoverEvents => UseParentInput ? parentInputManager.HandleHoverEvents : base.HandleHoverEvents; + public override bool HandleHoverEvents => parentInputManager != null && UseParentInput ? parentInputManager.HandleHoverEvents : base.HandleHoverEvents; internal override bool BuildNonPositionalInputQueue(List queue, bool allowBlocking = true) { @@ -76,9 +85,7 @@ protected override List GetPendingInputs() var pendingInputs = base.GetPendingInputs(); if (UseParentInput) - { pendingInputs.Clear(); - } return pendingInputs; } @@ -94,137 +101,131 @@ protected override bool Handle(UIEvent e) switch (e) { + case MouseDownEvent mouseDown: + new MouseButtonInput(mouseDown.Button, true).Apply(CurrentState, this); + break; + + case MouseUpEvent mouseUp: + new MouseButtonInput(mouseUp.Button, false).Apply(CurrentState, this); + break; + case MouseMoveEvent mouseMove: if (mouseMove.ScreenSpaceMousePosition != CurrentState.Mouse.Position) new MousePositionAbsoluteInput { Position = mouseMove.ScreenSpaceMousePosition }.Apply(CurrentState, this); break; - case MouseDownEvent mouseDown: - // safe-guard for edge cases. - if (!CurrentState.Mouse.IsPressed(mouseDown.Button)) - new MouseButtonInput(mouseDown.Button, true).Apply(CurrentState, this); + case ScrollEvent scroll: + new MouseScrollRelativeInput { Delta = scroll.ScrollDelta, IsPrecise = scroll.IsPrecise }.Apply(CurrentState, this); break; - case MouseUpEvent mouseUp: - // safe-guard for edge cases. - if (CurrentState.Mouse.IsPressed(mouseUp.Button)) - new MouseButtonInput(mouseUp.Button, false).Apply(CurrentState, this); + case KeyDownEvent keyDown: + if (keyDown.Repeat) + return false; + + new KeyboardKeyInput(keyDown.Key, true).Apply(CurrentState, this); break; - case ScrollEvent scroll: - new MouseScrollRelativeInput { Delta = scroll.ScrollDelta, IsPrecise = scroll.IsPrecise }.Apply(CurrentState, this); + case KeyUpEvent keyUp: + new KeyboardKeyInput(keyUp.Key, false).Apply(CurrentState, this); break; case TouchEvent touch: new TouchInput(touch.ScreenSpaceTouch, touch.IsActive(touch.ScreenSpaceTouch)).Apply(CurrentState, this); break; - case MidiEvent midi: - new MidiKeyInput(midi.Key, midi.Velocity, midi.IsPressed(midi.Key)).Apply(CurrentState, this); + case JoystickPressEvent joystickPress: + new JoystickButtonInput(joystickPress.Button, true).Apply(CurrentState, this); break; - case KeyboardEvent: - case JoystickButtonEvent: - case JoystickAxisMoveEvent: - case TabletPenButtonEvent: - case TabletAuxiliaryButtonEvent: - SyncInputState(e.CurrentState); + case JoystickReleaseEvent joystickRelease: + new JoystickButtonInput(joystickRelease.Button, false).Apply(CurrentState, this); break; - } - return false; - } + case JoystickAxisMoveEvent joystickAxisMove: + new JoystickAxisInput(joystickAxisMove.Axis).Apply(CurrentState, this); + break; - private InputManager parentInputManager; + case MidiDownEvent midiDown: + new MidiKeyInput(midiDown.Key, midiDown.Velocity, true).Apply(CurrentState, this); + break; - protected override void LoadComplete() - { - base.LoadComplete(); - Sync(); - } + case MidiUpEvent midiUp: + new MidiKeyInput(midiUp.Key, midiUp.Velocity, false).Apply(CurrentState, this); + break; - protected override void Update() - { - base.Update(); + case TabletPenButtonPressEvent tabletPenButtonPress: + new TabletPenButtonInput(tabletPenButtonPress.Button, true).Apply(CurrentState, this); + break; - // Some non-positional events are blocked. Sync every frame. - if (UseParentInput) Sync(true); - } + case TabletPenButtonReleaseEvent tabletPenButtonRelease: + new TabletPenButtonInput(tabletPenButtonRelease.Button, false).Apply(CurrentState, this); + break; - /// - /// Sync input state to parent 's . - /// Call this when parent changed somehow. - /// - /// If this is false, assume parent input manager is unchanged from before. - public void Sync(bool useCachedParentInputManager = false) - { - if (!UseParentInput) return; + case TabletAuxiliaryButtonPressEvent tabletAuxiliaryButtonPress: + new TabletAuxiliaryButtonInput(tabletAuxiliaryButtonPress.Button, true).Apply(CurrentState, this); + break; - if (!useCachedParentInputManager) - parentInputManager = GetContainingInputManager(); + case TabletAuxiliaryButtonReleaseEvent tabletAuxiliaryButtonRelease: + new TabletAuxiliaryButtonInput(tabletAuxiliaryButtonRelease.Button, false).Apply(CurrentState, this); + break; + } - SyncInputState(parentInputManager?.CurrentState); + return false; } /// - /// Sync current state to a certain state. + /// Updates state of any buttons that have been released by parent while was disabled. /// - /// The state to synchronise current with. If this is null, it is regarded as an empty state. - protected virtual void SyncInputState(InputState state) + private void syncReleasedInputs() { - // invariant: if mouse button is currently pressed, then it has been pressed in parent (but not the converse) - // therefore, mouse up events are always synced from parent - // mouse down events are not synced to prevent false clicks - var mouseDiff = (state?.Mouse?.Buttons ?? new ButtonStates()).EnumerateDifference(CurrentState.Mouse.Buttons); + if (parentInputManager == null) + return; + + var parentState = parentInputManager.CurrentState; + var mouseDiff = (parentState?.Mouse?.Buttons ?? new ButtonStates()).EnumerateDifference(CurrentState.Mouse.Buttons); + var keyDiff = (parentState?.Keyboard.Keys ?? new ButtonStates()).EnumerateDifference(CurrentState.Keyboard.Keys); + var touchDiff = (parentState?.Touch ?? new TouchState()).EnumerateDifference(CurrentState.Touch); + var joyButtonDiff = (parentState?.Joystick?.Buttons ?? new ButtonStates()).EnumerateDifference(CurrentState.Joystick.Buttons); + var midiDiff = (parentState?.Midi?.Keys ?? new ButtonStates()).EnumerateDifference(CurrentState.Midi.Keys); + var tabletPenDiff = (parentState?.Tablet?.PenButtons ?? new ButtonStates()).EnumerateDifference(CurrentState.Tablet.PenButtons); + var tabletAuxiliaryDiff = (parentState?.Tablet?.AuxiliaryButtons ?? new ButtonStates()).EnumerateDifference(CurrentState.Tablet.AuxiliaryButtons); + if (mouseDiff.Released.Length > 0) new MouseButtonInput(mouseDiff.Released.Select(button => new ButtonInputEntry(button, false))).Apply(CurrentState, this); - - var keyDiff = (state?.Keyboard.Keys ?? new ButtonStates()).EnumerateDifference(CurrentState.Keyboard.Keys); foreach (var key in keyDiff.Released) new KeyboardKeyInput(key, false).Apply(CurrentState, this); - foreach (var key in keyDiff.Pressed) - new KeyboardKeyInput(key, true).Apply(CurrentState, this); - - var touchDiff = (state?.Touch ?? new TouchState()).EnumerateDifference(CurrentState.Touch); if (touchDiff.deactivated.Length > 0) new TouchInput(touchDiff.deactivated, false).Apply(CurrentState, this); - if (touchDiff.activated.Length > 0) - new TouchInput(touchDiff.activated, true).Apply(CurrentState, this); - - var joyButtonDiff = (state?.Joystick?.Buttons ?? new ButtonStates()).EnumerateDifference(CurrentState.Joystick.Buttons); foreach (var button in joyButtonDiff.Released) new JoystickButtonInput(button, false).Apply(CurrentState, this); - foreach (var button in joyButtonDiff.Pressed) - new JoystickButtonInput(button, true).Apply(CurrentState, this); + foreach (var key in midiDiff.Released) + new MidiKeyInput(key, parentState?.Midi?.Velocities.GetValueOrDefault(key) ?? 0, false).Apply(CurrentState, this); + foreach (var button in tabletPenDiff.Released) + new TabletPenButtonInput(button, false).Apply(CurrentState, this); + foreach (var button in tabletAuxiliaryDiff.Released) + new TabletAuxiliaryButtonInput(button, false).Apply(CurrentState, this); + } + + /// + /// Updates state of joystick axes that have changed values while was disabled. + /// + private void syncJoystickAxes() + { + if (parentInputManager == null) + return; + + var parentState = parentInputManager.CurrentState; // Basically only perform the full state diff if we have found that any axis changed. // This avoids unnecessary alloc overhead. for (int i = 0; i < JoystickState.MAX_AXES; i++) { - if (state?.Joystick?.AxesValues[i] != CurrentState.Joystick.AxesValues[i]) + if (parentState?.Joystick?.AxesValues[i] != CurrentState.Joystick.AxesValues[i]) { - new JoystickAxisInput(state?.Joystick?.GetAxes() ?? Array.Empty()).Apply(CurrentState, this); + new JoystickAxisInput(parentState?.Joystick?.GetAxes() ?? Array.Empty()).Apply(CurrentState, this); break; } } - - var midiDiff = (state?.Midi?.Keys ?? new ButtonStates()).EnumerateDifference(CurrentState.Midi.Keys); - foreach (var key in midiDiff.Released) - new MidiKeyInput(key, state?.Midi?.Velocities.GetValueOrDefault(key) ?? 0, false).Apply(CurrentState, this); - foreach (var key in midiDiff.Pressed) - new MidiKeyInput(key, state?.Midi?.Velocities.GetValueOrDefault(key) ?? 0, true).Apply(CurrentState, this); - - var tabletPenDiff = (state?.Tablet?.PenButtons ?? new ButtonStates()).EnumerateDifference(CurrentState.Tablet.PenButtons); - foreach (var button in tabletPenDiff.Released) - new TabletPenButtonInput(button, false).Apply(CurrentState, this); - foreach (var button in tabletPenDiff.Pressed) - new TabletPenButtonInput(button, true).Apply(CurrentState, this); - - var tabletAuxiliaryDiff = (state?.Tablet?.AuxiliaryButtons ?? new ButtonStates()).EnumerateDifference(CurrentState.Tablet.AuxiliaryButtons); - foreach (var button in tabletAuxiliaryDiff.Released) - new TabletAuxiliaryButtonInput(button, false).Apply(CurrentState, this); - foreach (var button in tabletAuxiliaryDiff.Pressed) - new TabletAuxiliaryButtonInput(button, true).Apply(CurrentState, this); } } }