public void Actions_CanPerformDoubleTapInteraction() { var gamepad = InputSystem.AddDevice <Gamepad>(); runtime.advanceTimeEachDynamicUpdate = 0; var action = new InputAction(binding: "<Gamepad>/buttonSouth", interactions: "multitap(tapTime=0.5,tapDelay=0.75,tapCount=2)"); action.Enable(); using (var trace = new InputActionTrace()) { trace.SubscribeTo(action); // Press button. runtime.currentTime = 1; InputSystem.QueueStateEvent(gamepad, new GamepadState().WithButton(GamepadButton.South), 1); InputSystem.Update(); var actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(1)); Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Started)); Assert.That(actions[0].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[0].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[0].time, Is.EqualTo(1).Within(0.00001)); trace.Clear(); // Release before tap time and make sure the double tap cancels. runtime.currentTime = 12; InputSystem.QueueStateEvent(gamepad, new GamepadState(), 1.75); InputSystem.Update(); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(1)); Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Canceled)); Assert.That(actions[0].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[0].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[0].time, Is.EqualTo(1.75).Within(0.00001)); trace.Clear(); // Press again and then release before tap time. Should see only the start from // the initial press. runtime.currentTime = 2.5; InputSystem.QueueStateEvent(gamepad, new GamepadState().WithButton(GamepadButton.South), 2); InputSystem.QueueStateEvent(gamepad, new GamepadState(), 2.25); InputSystem.Update(); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(1)); Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Started)); Assert.That(actions[0].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[0].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[0].time, Is.EqualTo(2).Within(0.00001)); Assert.That(actions[0].ReadValue <float>(), Is.EqualTo(1).Within(0.00001)); trace.Clear(); // Wait for longer than tapDelay and make sure we're seeing a cancellation. runtime.currentTime = 4; InputSystem.Update(); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(1)); Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Canceled)); Assert.That(actions[0].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[0].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[0].time, Is.EqualTo(4).Within(0.00001)); Assert.That(actions[0].ReadValue <float>(), Is.EqualTo(0).Within(0.00001));// Button isn't pressed currently. trace.Clear(); // Now press and release within tap time. Then press again within delay time but release // only after tap time. Should we started and canceled. runtime.currentTime = 6; InputSystem.QueueStateEvent(gamepad, new GamepadState().WithButton(GamepadButton.South), 4.7); InputSystem.QueueStateEvent(gamepad, new GamepadState(), 4.9); InputSystem.QueueStateEvent(gamepad, new GamepadState().WithButton(GamepadButton.South), 5); InputSystem.QueueStateEvent(gamepad, new GamepadState(), 5.9); InputSystem.Update(); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(2)); Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Started)); Assert.That(actions[0].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[0].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[0].time, Is.EqualTo(4.7).Within(0.00001)); Assert.That(actions[0].ReadValue <float>(), Is.EqualTo(1).Within(0.00001)); Assert.That(actions[1].phase, Is.EqualTo(InputActionPhase.Canceled)); Assert.That(actions[1].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[1].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[1].time, Is.EqualTo(5.9).Within(0.00001)); Assert.That(actions[1].ReadValue <float>(), Is.EqualTo(0).Within(0.00001)); trace.Clear(); // Finally perform a full, proper double tap cycle. runtime.currentTime = 8; InputSystem.QueueStateEvent(gamepad, new GamepadState().WithButton(GamepadButton.South), 7); InputSystem.QueueStateEvent(gamepad, new GamepadState(), 7.25); InputSystem.QueueStateEvent(gamepad, new GamepadState().WithButton(GamepadButton.South), 7.5); InputSystem.QueueStateEvent(gamepad, new GamepadState(), 7.75); InputSystem.Update(); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(2)); Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Started)); Assert.That(actions[0].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[0].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[0].time, Is.EqualTo(7).Within(0.00001)); Assert.That(actions[0].ReadValue <float>(), Is.EqualTo(1).Within(0.00001)); Assert.That(actions[1].phase, Is.EqualTo(InputActionPhase.Performed)); Assert.That(actions[1].interaction, Is.TypeOf <MultiTapInteraction>()); Assert.That(actions[1].control, Is.SameAs(gamepad.buttonSouth)); Assert.That(actions[1].time, Is.EqualTo(7.75).Within(0.00001)); Assert.That(actions[1].ReadValue <float>(), Is.Zero.Within(0.00001)); } }
public void Actions_CanPerformPressInteraction() { var gamepad = InputSystem.AddDevice <Gamepad>(); // We add a second input device (and bind to it), to test that the binding // conflict resolution will not interfere with the interaction handling. InputSystem.AddDevice <Keyboard>(); // Test all three press behaviors concurrently. var pressOnlyAction = new InputAction("PressOnly", binding: "<Gamepad>/buttonSouth", interactions: "press"); pressOnlyAction.AddBinding("<Keyboard>/a"); var releaseOnlyAction = new InputAction("ReleaseOnly", binding: "<Gamepad>/buttonSouth", interactions: "press(behavior=1)"); releaseOnlyAction.AddBinding("<Keyboard>/s"); var pressAndReleaseAction = new InputAction("PressAndRelease", binding: "<Gamepad>/buttonSouth", interactions: "press(behavior=2)"); pressAndReleaseAction.AddBinding("<Keyboard>/d"); pressOnlyAction.Enable(); releaseOnlyAction.Enable(); pressAndReleaseAction.Enable(); using (var trace = new InputActionTrace()) { trace.SubscribeToAll(); runtime.currentTime = 1; Press(gamepad.buttonSouth); var actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(5)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Performed).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressAndReleaseAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressAndReleaseAction).And.With.Property("phase") .EqualTo(InputActionPhase.Performed).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(releaseOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); trace.Clear(); runtime.currentTime = 2; Release(gamepad.buttonSouth); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(3)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(releaseOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Performed).And.With.Property("duration") .EqualTo(1)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressAndReleaseAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressAndReleaseAction).And.With.Property("phase") .EqualTo(InputActionPhase.Performed).And.With.Property("duration") .EqualTo(0)); trace.Clear(); runtime.currentTime = 5; Press(gamepad.buttonSouth); actions = trace.ToArray(); Assert.That(actions, Has.Length.EqualTo(5)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Performed).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressAndReleaseAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(pressAndReleaseAction).And.With.Property("phase") .EqualTo(InputActionPhase.Performed).And.With.Property("duration") .EqualTo(0)); Assert.That(actions, Has.Exactly(1).With.Property("action").SameAs(releaseOnlyAction).And.With.Property("phase") .EqualTo(InputActionPhase.Started).And.With.Property("duration") .EqualTo(0)); } }