public void Editor_CanGenerateCodeWrapperForInputAsset_WhenAssetNameContainsSpacesAndSymbols()
    {
        var set1 = new InputActionMap("set1");

        set1.AddAction(name: "action ^&", binding: "/gamepad/leftStick");
        set1.AddAction(name: "1thing", binding: "/gamepad/leftStick");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(set1);
        asset.name = "New Controls (4)";

        var code = InputActionCodeGenerator.GenerateWrapperCode(asset,
                                                                new InputActionCodeGenerator.Options {
            sourceAssetPath = "test"
        });

        Assert.That(code, Contains.Substring("class NewControls4"));
        Assert.That(code, Contains.Substring("public InputAction @action"));
        Assert.That(code, Contains.Substring("public InputAction @_1thing"));
    }
        public static InputActionAsset GetDefaultInputActionAsset()
        {
            var asset = ScriptableObject.CreateInstance <InputActionAsset>();

            var map = new InputActionMap(InputConstants.MapCabinetSwitches);

            map.AddAction(InputConstants.ActionUpperLeftFlipper, InputActionType.Button, "<Keyboard>/a");
            map.AddAction(InputConstants.ActionUpperRightFlipper, InputActionType.Button, "<Keyboard>/quote");
            map.AddAction(InputConstants.ActionLeftFlipper, InputActionType.Button, "<Keyboard>/leftShift");
            map.AddAction(InputConstants.ActionRightFlipper, InputActionType.Button, "<Keyboard>/rightShift");
            map.AddAction(InputConstants.ActionRightMagnasave, InputActionType.Button, "<Keyboard>/rightCtrl");
            map.AddAction(InputConstants.ActionLeftMagnasave, InputActionType.Button, "<Keyboard>/leftCtrl");
            map.AddAction(InputConstants.ActionFire1, InputActionType.Button, "<Keyboard>/leftCtrl");
            map.AddAction(InputConstants.ActionFire2, InputActionType.Button, "<Keyboard>/rightAlt");
            map.AddAction(InputConstants.ActionFrontBuyIn, InputActionType.Button, "<Keyboard>/2");
            map.AddAction(InputConstants.ActionStartGame, InputActionType.Button, "<Keyboard>/1");
            map.AddAction(InputConstants.ActionPlunger, InputActionType.Button, "<Keyboard>/enter");
            map.AddAction(InputConstants.ActionInsertCoin1, InputActionType.Button, "<Keyboard>/3");
            map.AddAction(InputConstants.ActionInsertCoin2, InputActionType.Button, "<Keyboard>/4");
            map.AddAction(InputConstants.ActionInsertCoin3, InputActionType.Button, "<Keyboard>/5");
            map.AddAction(InputConstants.ActionInsertCoin4, InputActionType.Button, "<Keyboard>/6");
            map.AddAction(InputConstants.ActionCoinDoorOpenClose, InputActionType.Button, "<Keyboard>/end");
            map.AddAction(InputConstants.ActionCoinDoorCancel, InputActionType.Button, "<Keyboard>/7");
            map.AddAction(InputConstants.ActionCoinDoorDown, InputActionType.Button, "<Keyboard>/8");
            map.AddAction(InputConstants.ActionCoinDoorUp, InputActionType.Button, "<Keyboard>/9");
            map.AddAction(InputConstants.ActionCoinDoorEnter, InputActionType.Button, "<Keyboard>/0");
            map.AddAction(InputConstants.ActionCoinDoorAdvance, InputActionType.Button, "<Keyboard>/8");
            map.AddAction(InputConstants.ActionCoinDoorUpDown, InputActionType.Button, "<Keyboard>/7");
            map.AddAction(InputConstants.ActionSlamTilt, InputActionType.Button, "<Keyboard>/home");

            asset.AddActionMap(map);

            map = new InputActionMap(InputConstants.MapDebug);
            map.AddAction(InputConstants.ActionCreateBall, InputActionType.Button, "<Keyboard>/b");
            map.AddAction(InputConstants.ActionKicker, InputActionType.Button, "<Keyboard>/n");

            asset.AddActionMap(map);

            return(asset);
        }
Beispiel #3
0
    public void Components_TrackedPoseDriver_DoesNotEnableOrDisableReferenceActions()
    {
        var map = new InputActionMap("map");

        map.AddAction("Position", binding: "<TestHMD>/vector3");
        map.AddAction("Rotation", binding: "<TestHMD>/quaternion");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(map);

        var positionReference = ScriptableObject.CreateInstance <InputActionReference>();
        var rotationReference = ScriptableObject.CreateInstance <InputActionReference>();

        positionReference.Set(asset, "map", "Position");
        rotationReference.Set(asset, "map", "Rotation");

        var positionInput = new InputActionProperty(positionReference);
        var rotationInput = new InputActionProperty(rotationReference);

        var go        = new GameObject();
        var component = go.AddComponent <TrackedPoseDriver>();

        component.enabled       = false;
        component.positionInput = positionInput;
        component.rotationInput = rotationInput;

        Assert.That(positionInput.action.enabled, Is.False);
        Assert.That(rotationInput.action.enabled, Is.False);

        component.enabled = true;

        Assert.That(positionInput.action.enabled, Is.False);
        Assert.That(rotationInput.action.enabled, Is.False);

        component.enabled = false;

        Assert.That(positionInput.action.enabled, Is.False);
        Assert.That(rotationInput.action.enabled, Is.False);
    }
    public void Editor_InputAsset_CanAddAndRemoveBindingThroughSerialization()
    {
        var map = new InputActionMap("set");

        map.AddAction(name: "action1", binding: "/gamepad/leftStick");
        map.AddAction(name: "action2", binding: "/gamepad/rightStick");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(map);

        var obj             = new SerializedObject(asset);
        var mapProperty     = obj.FindProperty("m_ActionMaps").GetArrayElementAtIndex(0);
        var action1Property = mapProperty.FindPropertyRelative("m_Actions").GetArrayElementAtIndex(0);

        InputActionSerializationHelpers.AppendBinding(action1Property, mapProperty);
        obj.ApplyModifiedPropertiesWithoutUndo();

        // Maps and actions aren't UnityEngine.Objects so the modifications will not
        // be in-place. Look up the actions after each apply.
        var action1 = asset.actionMaps[0].TryGetAction("action1");
        var action2 = asset.actionMaps[0].TryGetAction("action2");

        Assert.That(action1.bindings, Has.Count.EqualTo(2));
        Assert.That(action1.bindings[0].path, Is.EqualTo("/gamepad/leftStick"));
        Assert.That(action1.bindings[1].path, Is.EqualTo(""));
        Assert.That(action1.bindings[1].interactions, Is.EqualTo(""));
        Assert.That(action1.bindings[1].groups, Is.EqualTo(""));
        Assert.That(action2.bindings[0].path, Is.EqualTo("/gamepad/rightStick"));

        InputActionSerializationHelpers.RemoveBinding(action1Property, 1, mapProperty);
        obj.ApplyModifiedPropertiesWithoutUndo();

        action1 = asset.actionMaps[0].TryGetAction("action1");
        action2 = asset.actionMaps[0].TryGetAction("action2");

        Assert.That(action1.bindings, Has.Count.EqualTo(1));
        Assert.That(action1.bindings[0].path, Is.EqualTo("/gamepad/leftStick"));
        Assert.That(action2.bindings[0].path, Is.EqualTo("/gamepad/rightStick"));
    }
Beispiel #5
0
    public void Editor_RenamingAction_WillAutomaticallyEnsureUniqueNames()
    {
        var map = new InputActionMap("set1");

        map.AddAction("actionA", binding: "<Gamepad>/leftStick");
        map.AddAction("actionB");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(map);

        var obj             = new SerializedObject(asset);
        var mapProperty     = obj.FindProperty("m_ActionMaps").GetArrayElementAtIndex(0);
        var action1Property = mapProperty.FindPropertyRelative("m_Actions").GetArrayElementAtIndex(0);

        InputActionSerializationHelpers.RenameAction(action1Property, mapProperty, "actionB");
        obj.ApplyModifiedPropertiesWithoutUndo();

        Assert.That(map.actions[1].name, Is.EqualTo("actionB"));
        Assert.That(map.actions[0].name, Is.EqualTo("actionB1"));
        Assert.That(map.actions[0].bindings, Has.Count.EqualTo(1));
        Assert.That(map.actions[0].bindings[0].action, Is.EqualTo("actionB1"));
    }
Beispiel #6
0
    public void Editor_CanGenerateInputDeviceBasedOnSteamIGAFile()
    {
        // Create an InputActions setup and convert it to Steam IGA.
        var asset      = ScriptableObject.CreateInstance <InputActionAsset>();
        var actionMap1 = new InputActionMap("map1");
        var actionMap2 = new InputActionMap("map2");

        actionMap1.AddAction("buttonAction", expectedControlLayout: "Button");
        actionMap1.AddAction("axisAction", expectedControlLayout: "Axis");
        actionMap1.AddAction("stickAction", expectedControlLayout: "Stick");
        actionMap2.AddAction("vector2Action", expectedControlLayout: "Vector2");

        asset.AddActionMap(actionMap1);
        asset.AddActionMap(actionMap2);

        var vdf = SteamIGAConverter.ConvertInputActionsToSteamIGA(asset);

        // Generate a C# input device from the Steam IGA file.
        var generatedCode = SteamIGAConverter.GenerateInputDeviceFromSteamIGA(vdf, "My.Namespace.MySteamController");

        Assert.That(generatedCode, Does.StartWith("// THIS FILE HAS BEEN AUTO-GENERATED"));
        Assert.That(generatedCode, Contains.Substring("#if (UNITY_EDITOR || UNITY_STANDALONE) && UNITY_ENABLE_STEAM_CONTROLLER_SUPPORT"));
        Assert.That(generatedCode, Contains.Substring("namespace My.Namespace\n"));
        Assert.That(generatedCode, Contains.Substring("public class MySteamController : SteamController, IInputUpdateCallbackReceiver\n"));
        Assert.That(generatedCode, Contains.Substring("public unsafe struct MySteamControllerState : IInputStateTypeInfo\n"));
        Assert.That(generatedCode, Contains.Substring("[InitializeOnLoad]"));
        Assert.That(generatedCode, Contains.Substring("[RuntimeInitializeOnLoadMethod"));
        Assert.That(generatedCode, Contains.Substring("new FourCC('M', 'y', 'S', 't')"));
        Assert.That(generatedCode, Contains.Substring("protected override void FinishSetup(InputDeviceBuilder builder)"));
        Assert.That(generatedCode, Contains.Substring("base.FinishSetup(builder);"));
        Assert.That(generatedCode, Contains.Substring("new InputDeviceMatcher"));
        Assert.That(generatedCode, Contains.Substring("WithInterface(\"Steam\")"));
        Assert.That(generatedCode, Contains.Substring("public StickControl stickAction"));
        Assert.That(generatedCode, Contains.Substring("public ButtonControl buttonAction"));
        Assert.That(generatedCode, Contains.Substring("public AxisControl axisAction"));
        Assert.That(generatedCode, Contains.Substring("public Vector2Control vector2Action"));
        Assert.That(generatedCode, Contains.Substring("stickAction = builder.GetControl<StickControl>(\"stickAction\");"));
        Assert.That(generatedCode, Contains.Substring("buttonAction = builder.GetControl<ButtonControl>(\"buttonAction\");"));
        Assert.That(generatedCode, Contains.Substring("axisAction = builder.GetControl<AxisControl>(\"axisAction\");"));
        Assert.That(generatedCode, Contains.Substring("vector2Action = builder.GetControl<Vector2Control>(\"vector2Action\");"));

        /*
         * Assert.That(generatedCode, Contains.Substring("ulong m_SetHandle_map1"));
         * Assert.That(generatedCode, Contains.Substring("ulong m_SetHandle_map2"));
         * Assert.That(generatedCode, Contains.Substring("ulong m_ActionHandle_buttonAction"));
         * Assert.That(generatedCode, Contains.Substring("ulong m_ActionHandle_axisAction"));
         * Assert.That(generatedCode, Contains.Substring("ulong m_ActionHandle_stickAction"));
         * Assert.That(generatedCode, Contains.Substring("ulong m_ActionHandle_vector2Action"));
         */
    }
    public void Actions_CanRemoveBindingOverridesFromMaps()
    {
        var map     = new InputActionMap();
        var action1 = map.AddAction("action1", binding: "/<keyboard>/enter");
        var action2 = map.AddAction("action2", binding: "/<gamepad>/buttonSouth");

        var overrides = new List <InputBinding>
        {
            new InputBinding {
                action = "action2", overridePath = "/gamepad/rightTrigger"
            },
            new InputBinding {
                action = "action1", overridePath = "/gamepad/leftTrigger"
            }
        };

        map.ApplyBindingOverrides(overrides);
        overrides.RemoveAt(1); // Leave only override for action2.
        map.RemoveBindingOverrides(overrides);

        Assert.That(action1.bindings[0].overridePath, Is.EqualTo("/gamepad/leftTrigger"));
        Assert.That(action2.bindings[0].overridePath, Is.Null); // Should have been removed.
    }
    public void Actions_CannotApplyBindingOverridesToMap_WhenEnabled()
    {
        var map = new InputActionMap();

        map.AddAction("action1", binding: "/<keyboard>/enter").Enable();

        var overrides = new List <InputBinding>
        {
            new InputBinding {
                action = "action1", overridePath = "/gamepad/leftTrigger"
            }
        };

        Assert.That(() => map.ApplyBindingOverrides(overrides), Throws.InvalidOperationException);
    }
Beispiel #9
0
    public void Users_CanRestrictBindingToAssignedInputDevices()
    {
        var gamepad1 = InputSystem.AddDevice <Gamepad>();
        var gamepad2 = InputSystem.AddDevice <Gamepad>();
        var gamepad3 = InputSystem.AddDevice <Gamepad>();

        var map1 = new InputActionMap("map");

        map1.AddAction("action").AddBinding("<Gamepad>/buttonSouth", groups: "Gamepad");
        var map2 = map1.Clone();

        var user1 = new TestUser();
        var user2 = new TestUser();

        InputUser.Add(user1);
        InputUser.Add(user2);

        user1.AssignInputDevice(gamepad1);
        user2.AssignInputDevice(gamepad2);

        user1.AssignInputActions(map1);
        user2.AssignInputActions(map2);

        // Have bound to everything available globally.
        Assert.That(map1["action"].controls, Is.EquivalentTo(new[] { gamepad1.buttonSouth, gamepad2.buttonSouth, gamepad3.buttonSouth }));
        Assert.That(map2["action"].controls, Is.EquivalentTo(new[] { gamepad1.buttonSouth, gamepad2.buttonSouth, gamepad3.buttonSouth }));

        user2.BindOnlyToAssignedInputDevices();

        // Have bound only to currently assigned devices.
        Assert.That(map1["action"].controls, Is.EquivalentTo(new[] { gamepad1.buttonSouth, gamepad2.buttonSouth, gamepad3.buttonSouth }));
        Assert.That(map2["action"].controls, Is.EquivalentTo(new[] { gamepad2.buttonSouth }));

        user2.ClearAssignedInputDevices();
        user2.AssignInputDevice(gamepad3);

        // Have updated bindings to reflect change in assigned devices.
        Assert.That(map1["action"].controls, Is.EquivalentTo(new[] { gamepad1.buttonSouth, gamepad2.buttonSouth, gamepad3.buttonSouth }));
        Assert.That(map2["action"].controls, Is.EquivalentTo(new[] { gamepad3.buttonSouth }));

        user2.BindOnlyToAssignedInputDevices(false);

        // Have gone back to binding to everything.
        Assert.That(map1["action"].controls, Is.EquivalentTo(new[] { gamepad1.buttonSouth, gamepad2.buttonSouth, gamepad3.buttonSouth }));
        Assert.That(map2["action"].controls, Is.EquivalentTo(new[] { gamepad1.buttonSouth, gamepad2.buttonSouth, gamepad3.buttonSouth }));
    }
Beispiel #10
0
    public void Editor_InputAsset_CanAddBindingFromSavedProperties()
    {
        var map = new InputActionMap("set");

        map.AddAction(name: "action1");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(map);

        var obj             = new SerializedObject(asset);
        var mapProperty     = obj.FindProperty("m_ActionMaps").GetArrayElementAtIndex(0);
        var action1Property = mapProperty.FindPropertyRelative("m_Actions").GetArrayElementAtIndex(0);

        var pathName         = "/gamepad/leftStick";
        var name             = "some name";
        var interactionsName = "someinteractions";
        var sourceActionName = "some action";
        var groupName        = "group";
        var flags            = 10;

        var parameters = new Dictionary <string, string>();

        parameters.Add("path", pathName);
        parameters.Add("name", name);
        parameters.Add("groups", groupName);
        parameters.Add("interactions", interactionsName);
        parameters.Add("flags", "" + flags);
        parameters.Add("action", sourceActionName);

        InputActionSerializationHelpers.AddBindingFromSavedProperties(parameters, action1Property, mapProperty);

        obj.ApplyModifiedPropertiesWithoutUndo();

        var action1 = asset.actionMaps[0].TryGetAction("action1");

        Assert.That(action1.bindings, Has.Count.EqualTo(1));
        Assert.That(action1.bindings[0].path, Is.EqualTo(pathName));
        Assert.That(action1.bindings[0].action, Is.EqualTo("action1"));
        Assert.That(action1.bindings[0].groups, Is.EqualTo(groupName));
        Assert.That(action1.bindings[0].interactions, Is.EqualTo(interactionsName));
        Assert.That(action1.bindings[0].name, Is.EqualTo(name));
    }
    public void Editor_CanRenameAction()
    {
        var set1 = new InputActionMap("set1");

        set1.AddAction(name: "action", binding: "/gamepad/leftStick");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(set1);

        var obj             = new SerializedObject(asset);
        var mapProperty     = obj.FindProperty("m_ActionMaps").GetArrayElementAtIndex(0);
        var action1Property = mapProperty.FindPropertyRelative("m_Actions").GetArrayElementAtIndex(0);

        InputActionSerializationHelpers.RenameAction(action1Property, mapProperty, "newAction");
        obj.ApplyModifiedPropertiesWithoutUndo();

        Assert.That(set1.actions[0].name, Is.EqualTo("newAction"));
        Assert.That(set1.actions[0].bindings, Has.Count.EqualTo(1));
        Assert.That(set1.actions[0].bindings[0].action, Is.EqualTo("newAction"));
    }
Beispiel #12
0
 public GenericDevice(InputDevice device)
 {
     m_Device                   = device;
     m_Controls                 = m_Device.allControls.ToList();
     m_ControlTypes             = m_Controls.Select(x => x.GetType()).Distinct().ToList();
     m_UIType                   = UIType.Specialized;
     m_CaptureDetailedEventInfo = false;
     m_ActionMap                = new InputActionMap();
     m_ActionMap.Disable();
     m_ActionMap.devices = new[] { device };
     foreach (var c in m_Controls)
     {
         var action = m_ActionMap.AddAction(c.path, binding: c.path);
         action.performed += Action_performed;
         m_Actions[c]      = new ActionData()
         {
             action = action
         };
     }
     m_ActionMap.Enable();
 }
    public void Actions_CanApplyBindingOverridesToMap_WhenEnabled()
    {
        var keyboard = InputSystem.AddDevice <Keyboard>();
        var gamepad  = InputSystem.AddDevice <Gamepad>();

        var map    = new InputActionMap();
        var action = map.AddAction("action1", binding: "<Keyboard>/enter");

        map.Enable();

        Assert.That(action.controls, Is.EquivalentTo(new[] { keyboard.enterKey }));

        map.ApplyBindingOverrides(new List <InputBinding>
        {
            new InputBinding {
                action = "action1", overridePath = "<Gamepad>/leftTrigger"
            }
        });

        Assert.That(action.bindings[0].overridePath, Is.EqualTo("<Gamepad>/leftTrigger"));
        Assert.That(action.controls, Is.EquivalentTo(new[] { gamepad.leftTrigger }));
    }
    public void Actions_CanPerformPressInteraction_AndTriggerInteractionResetInCallback()
    {
        var keyboard = InputSystem.AddDevice <Keyboard>();

        var asset = ScriptableObject.CreateInstance <InputActionAsset>();
        var map1  = new InputActionMap("map1");
        var map2  = new InputActionMap("map2");

        asset.AddActionMap(map1);
        asset.AddActionMap(map2);

        var action1 = map1.AddAction("action1");
        var action2 = map2.AddAction("action2");

        // PressInteraction used to set some local state *after* trigger callbacks. This meant that if the
        // callback triggered a Reset() call, PressInteraction would then overwrite state from the reset.
        action1.AddBinding("<Keyboard>/a", interactions: "press(behavior=0)");
        action2.AddBinding("<Keyboard>/b", interactions: "press(behavior=0)");

        action1.performed += _ => { map1.Disable(); map2.Enable(); };
        action2.performed += _ => { map2.Disable(); map1.Enable(); };

        map1.Enable();

        PressAndRelease(keyboard.aKey);

        Assert.That(map1.enabled, Is.False);
        Assert.That(map2.enabled, Is.True);

        PressAndRelease(keyboard.bKey);

        Assert.That(map1.enabled, Is.True);
        Assert.That(map2.enabled, Is.False);

        PressAndRelease(keyboard.aKey);

        Assert.That(map1.enabled, Is.False);
        Assert.That(map2.enabled, Is.True);
    }
Beispiel #15
0
    public void Editor_CanPrettyPrintJSON()
    {
        var map = new InputActionMap("map");

        map.AddAction("action", binding: "<Gamepad>/leftStick");
        var json = InputActionMap.ToJson(new[] { map });

        var prettyJson = StringHelpers.PrettyPrintJSON(json);

        Assert.That(prettyJson, Does.StartWith(
                        @"{
    ""maps"" : [
        {
            ""name"" : ""map"",
            ""actions"" : [
                {
                    ""name"" : ""action"",
                    ""expectedControlLayout"" : """",
                    ""bindings"" : [
                    ]
"));

        // Doing it again should not result in a difference.
        prettyJson = StringHelpers.PrettyPrintJSON(prettyJson);

        Assert.That(prettyJson, Does.StartWith(
                        @"{
    ""maps"" : [
        {
            ""name"" : ""map"",
            ""actions"" : [
                {
                    ""name"" : ""action"",
                    ""expectedControlLayout"" : """",
                    ""bindings"" : [
                    ]
"));
    }
    public void Editor_InputAsset_CanAddActionMapFromObject()
    {
        var map     = new InputActionMap("set");
        var binding = new InputBinding();

        binding.path = "some path";
        var action = map.AddAction("action");

        action.AppendBinding(binding);

        var asset = ScriptableObject.CreateInstance <InputActionAsset>();
        var obj   = new SerializedObject(asset);

        Assert.That(asset.actionMaps, Has.Count.EqualTo(0));

        InputActionSerializationHelpers.AddActionMapFromObject(obj, map);
        obj.ApplyModifiedPropertiesWithoutUndo();

        Assert.That(asset.actionMaps, Has.Count.EqualTo(1));
        Assert.That(asset.actionMaps[0].name, Is.EqualTo("set"));
        Assert.That(asset.actionMaps[0].actions[0].name, Is.EqualTo("action"));
        Assert.That(asset.actionMaps[0].actions[0].bindings[0].path, Is.EqualTo("some path"));
    }
    public void Action_WithMultipleInteractions_DoesNotThrowWhenUsingMultipleMaps()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        var map1 = new InputActionMap("map1");
        var map2 = new InputActionMap("map2");

        map1.AddAction(name: "action1", type: InputActionType.Button, binding: "<Gamepad>/buttonSouth");
        map2.AddAction(name: "action2", type: InputActionType.Button, binding: "<Gamepad>/buttonNorth", interactions: "press,hold(duration=0.4)");

        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(map1);
        asset.AddActionMap(map2);

        map2.Enable();

        Assert.DoesNotThrow(() =>
        {
            Press(gamepad.buttonNorth);
            Release(gamepad.buttonNorth);
        });
    }
Beispiel #18
0
        void RegisterInputs()
        {
#if USE_INPUT_SYSTEM
            var map = new InputActionMap("Free Camera");

            lookAction  = map.AddAction("look", binding: "<Mouse>/delta");
            moveAction  = map.AddAction("move", binding: "<Gamepad>/leftStick");
            speedAction = map.AddAction("speed", binding: "<Gamepad>/dpad");
            yMoveAction = map.AddAction("yMove");

            lookAction.AddBinding("<Gamepad>/rightStick").WithProcessor("scaleVector2(x=15, y=15)");
            moveAction.AddCompositeBinding("Dpad")
            .With("Up", "<Keyboard>/w")
            .With("Up", "<Keyboard>/upArrow")
            .With("Down", "<Keyboard>/s")
            .With("Down", "<Keyboard>/downArrow")
            .With("Left", "<Keyboard>/a")
            .With("Left", "<Keyboard>/leftArrow")
            .With("Right", "<Keyboard>/d")
            .With("Right", "<Keyboard>/rightArrow");
            speedAction.AddCompositeBinding("Dpad")
            .With("Up", "<Keyboard>/home")
            .With("Down", "<Keyboard>/end");
            yMoveAction.AddCompositeBinding("Dpad")
            .With("Up", "<Keyboard>/pageUp")
            .With("Down", "<Keyboard>/pageDown")
            .With("Up", "<Keyboard>/e")
            .With("Down", "<Keyboard>/q")
            .With("Up", "<Gamepad>/rightshoulder")
            .With("Down", "<Gamepad>/leftshoulder");

            moveAction.Enable();
            lookAction.Enable();
            speedAction.Enable();
            fireAction.Enable();
            yMoveAction.Enable();
#endif

#if UNITY_EDITOR && !USE_INPUT_SYSTEM
            List <InputManagerEntry> inputEntries = new List <InputManagerEntry>();

            // Add new bindings
            inputEntries.Add(new InputManagerEntry {
                name = kRightStickX, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Fourth, sensitivity = 1.0f, gravity = 1.0f, deadZone = 0.2f
            });
            inputEntries.Add(new InputManagerEntry {
                name = kRightStickY, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Fifth, sensitivity = 1.0f, gravity = 1.0f, deadZone = 0.2f, invert = true
            });

            inputEntries.Add(new InputManagerEntry {
                name = kYAxis, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page up", altBtnPositive = "joystick button 5", btnNegative = "page down", altBtnNegative = "joystick button 4", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f
            });
            inputEntries.Add(new InputManagerEntry {
                name = kYAxis, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "q", btnNegative = "e", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f
            });

            inputEntries.Add(new InputManagerEntry {
                name = kSpeedAxis, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "home", btnNegative = "end", gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f
            });
            inputEntries.Add(new InputManagerEntry {
                name = kSpeedAxis, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Seventh, gravity = 1000.0f, deadZone = 0.001f, sensitivity = 1000.0f
            });

            InputRegistering.RegisterInputs(inputEntries);
#endif
        }
Beispiel #19
0
    public IEnumerator MouseActions_CanDriveUI()
    {
        // Create devices.
        var mouse = InputSystem.AddDevice <Mouse>();

        var objects             = CreateScene();
        var uiModule            = objects.uiModule;
        var eventSystem         = objects.eventSystem;
        var leftChildGameObject = objects.leftGameObject;
        var leftChildReceiver   = leftChildGameObject != null?leftChildGameObject.GetComponent <UICallbackReceiver>() : null;

        var rightChildGameObject = objects.rightGameObject;
        var rightChildReceiver   = rightChildGameObject != null?rightChildGameObject.GetComponent <UICallbackReceiver>() : null;

        // Create actions.
        var map               = new InputActionMap();
        var pointAction       = map.AddAction("point");
        var leftClickAction   = map.AddAction("leftClick");
        var rightClickAction  = map.AddAction("rightClick");
        var middleClickAction = map.AddAction("middleClick");
        var scrollAction      = map.AddAction("scroll");

        // Create bindings.
        pointAction.AddBinding(mouse.position);
        leftClickAction.AddBinding(mouse.leftButton);
        rightClickAction.AddBinding(mouse.rightButton);
        middleClickAction.AddBinding(mouse.middleButton);
        scrollAction.AddBinding(mouse.scroll);

        // Wire up actions.
        // NOTE: In a normal usage scenario, the user would wire these up in the inspector.
        uiModule.point       = new InputActionProperty(pointAction);
        uiModule.leftClick   = new InputActionProperty(leftClickAction);
        uiModule.middleClick = new InputActionProperty(middleClickAction);
        uiModule.rightClick  = new InputActionProperty(rightClickAction);
        uiModule.scrollWheel = new InputActionProperty(scrollAction);

        // Enable the whole thing.
        map.Enable();

        // We need to wait a frame to let the underlying canvas update and properly order the graphics images for raycasting.
        yield return(null);

        // Move mouse over left child.
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check basic down/up
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100), buttons = (ushort)(1 << (int)MouseButton.Left)
        });
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100), buttons = (ushort)0
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(4));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
        Assert.That(leftChildReceiver.events[2].type, Is.EqualTo(EventType.Up));
        Assert.That(leftChildReceiver.events[3].type, Is.EqualTo(EventType.Click));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check down and drag
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100), buttons = (ushort)(1 << (int)MouseButton.Right)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Move to new location on left child
        InputSystem.QueueDeltaStateEvent(mouse.position, new Vector2(100, 200));
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.BeginDrag));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Move children
        InputSystem.QueueDeltaStateEvent(mouse.position, new Vector2(400, 200));
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Exit));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
        rightChildReceiver.Reset();

        // Release button
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(400, 200), buttons = (ushort)0
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Up));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.EndDrag));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Drop));
        rightChildReceiver.Reset();

        // Check Scroll
        InputSystem.QueueDeltaStateEvent(mouse.scroll, Vector2.one);
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(0));
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Scroll));
        rightChildReceiver.Reset();
    }
Beispiel #20
0
    public IEnumerator JoystickActions_CanDriveUI()
    {
        // Create devices.
        var gamepad = InputSystem.AddDevice <Gamepad>();

        var objects             = CreateScene();
        var uiModule            = objects.uiModule;
        var eventSystem         = objects.eventSystem;
        var leftChildGameObject = objects.leftGameObject;
        var leftChildReceiver   = leftChildGameObject != null?leftChildGameObject.GetComponent <UICallbackReceiver>() : null;

        var rightChildGameObject = objects.rightGameObject;
        var rightChildReceiver   = rightChildGameObject != null?rightChildGameObject.GetComponent <UICallbackReceiver>() : null;

        // Create actions.
        var map          = new InputActionMap();
        var moveAction   = map.AddAction("move");
        var submitAction = map.AddAction("submit");
        var cancelAction = map.AddAction("cancel");

        // Create bindings.
        moveAction.AddBinding(gamepad.leftStick);
        submitAction.AddBinding(gamepad.buttonSouth);
        cancelAction.AddBinding(gamepad.buttonEast);

        // Wire up actions.
        // NOTE: In a normal usage scenario, the user would wire these up in the inspector.
        uiModule.move   = new InputActionProperty(moveAction);
        uiModule.submit = new InputActionProperty(submitAction);
        uiModule.cancel = new InputActionProperty(cancelAction);

        // Enable the whole thing.
        map.Enable();

        // We need to wait a frame to let the underlying canvas update and properly order the graphics images for raycasting.
        yield return(null);

        // Test Selection
        eventSystem.SetSelectedGameObject(leftChildGameObject);
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Select));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Move Axes
        InputSystem.QueueDeltaStateEvent(gamepad.leftStick, new Vector2(1.0f, 0.0f));
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Move));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Submit
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = (uint)(1 << (int)GamepadButton.South)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Submit));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Cancel
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = (uint)(1 << (int)GamepadButton.East)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Cancel));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Selection Swap
        eventSystem.SetSelectedGameObject(rightChildGameObject);
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Deselect));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Select));
        rightChildReceiver.Reset();

        // Check Deselect
        eventSystem.SetSelectedGameObject(null);
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(0));
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Deselect));
        rightChildReceiver.Reset();
    }
Beispiel #21
0
    public void Editor_CanConvertInputActionsToSteamIGAFormat()
    {
        var asset      = ScriptableObject.CreateInstance <InputActionAsset>();
        var actionMap1 = new InputActionMap("map1");
        var actionMap2 = new InputActionMap("map2");

        actionMap1.AddAction("buttonAction", expectedControlLayout: "Button");
        actionMap1.AddAction("axisAction", expectedControlLayout: "Axis");
        actionMap1.AddAction("stickAction", expectedControlLayout: "Stick");
        actionMap2.AddAction("vector2Action", expectedControlLayout: "Vector2");

        asset.AddActionMap(actionMap1);
        asset.AddActionMap(actionMap2);

        var vdf        = SteamIGAConverter.ConvertInputActionsToSteamIGA(asset);
        var dictionary = SteamIGAConverter.ParseVDF(vdf);

        // Top-level key "In Game Actions".
        Assert.That(dictionary.Count, Is.EqualTo(1));
        Assert.That(dictionary, Contains.Key("In Game Actions").With.TypeOf <Dictionary <string, object> >());

        // "actions" and "localization" inside "In Game Actions".
        var inGameActions = (Dictionary <string, object>)dictionary["In Game Actions"];

        Assert.That(inGameActions, Contains.Key("actions"));
        Assert.That(inGameActions["actions"], Is.TypeOf <Dictionary <string, object> >());
        Assert.That(inGameActions, Contains.Key("localization"));
        Assert.That(inGameActions["localization"], Is.TypeOf <Dictionary <string, object> >());
        Assert.That(inGameActions.Count, Is.EqualTo(2));

        // Two action maps inside "actions".
        var actions = (Dictionary <string, object>)inGameActions["actions"];

        Assert.That(actions, Contains.Key("map1"));
        Assert.That(actions["map1"], Is.TypeOf <Dictionary <string, object> >());
        Assert.That(actions, Contains.Key("map2"));
        Assert.That(actions["map2"], Is.TypeOf <Dictionary <string, object> >());
        Assert.That(actions.Count, Is.EqualTo(2));

        // Three actions inside "map1".
        var map1 = (Dictionary <string, object>)actions["map1"];

        Assert.That(map1, Contains.Key("title"));
        Assert.That(map1, Contains.Key("StickPadGyro"));
        Assert.That(map1, Contains.Key("AnalogTrigger"));
        Assert.That(map1, Contains.Key("Button"));
        Assert.That(map1.Count, Is.EqualTo(4));
        Assert.That(map1["title"], Is.EqualTo("#Set_map1"));
        Assert.That(map1["StickPadGyro"], Is.TypeOf <Dictionary <string, object> >());
        Assert.That(map1["AnalogTrigger"], Is.TypeOf <Dictionary <string, object> >());
        Assert.That(map1["Button"], Is.TypeOf <Dictionary <string, object> >());
        var stickPadGyro1 = (Dictionary <string, object>)map1["StickPadGyro"];

        Assert.That(stickPadGyro1, Has.Count.EqualTo(1));
        Assert.That(stickPadGyro1, Contains.Key("stickAction"));
        Assert.That(stickPadGyro1["stickAction"], Is.TypeOf <Dictionary <string, object> >());
        var stickAction = (Dictionary <string, object>)stickPadGyro1["stickAction"];

        Assert.That(stickAction, Contains.Key("title"));
        Assert.That(stickAction, Contains.Key("input_mode"));
        Assert.That(stickAction.Count, Is.EqualTo(2));
        Assert.That(stickAction["title"], Is.EqualTo("#Action_map1_stickAction"));
        Assert.That(stickAction["input_mode"], Is.EqualTo("joystick_move"));

        // One action inside "map2".
        var map2 = (Dictionary <string, object>)actions["map2"];

        Assert.That(map2, Contains.Key("title"));
        Assert.That(map2["title"], Is.EqualTo("#Set_map2"));

        // Localization strings.
        var localization = (Dictionary <string, object>)inGameActions["localization"];

        Assert.That(localization.Count, Is.EqualTo(1));
        Assert.That(localization, Contains.Key("english"));
        Assert.That(localization["english"], Is.TypeOf <Dictionary <string, object> >());
        var english = (Dictionary <string, object>)localization["english"];

        Assert.That(english, Contains.Key("Set_map1"));
        Assert.That(english, Contains.Key("Set_map2"));
        Assert.That(english, Contains.Key("Action_map1_buttonAction"));
        Assert.That(english, Contains.Key("Action_map1_axisAction"));
        Assert.That(english, Contains.Key("Action_map1_stickAction"));
        Assert.That(english, Contains.Key("Action_map2_vector2Action"));
        Assert.That(english["Set_map1"], Is.EqualTo("map1"));
        Assert.That(english["Set_map2"], Is.EqualTo("map2"));
        Assert.That(english["Action_map1_buttonAction"], Is.EqualTo("buttonAction"));
        Assert.That(english["Action_map1_axisAction"], Is.EqualTo("axisAction"));
        Assert.That(english["Action_map1_stickAction"], Is.EqualTo("stickAction"));
        Assert.That(english["Action_map2_vector2Action"], Is.EqualTo("vector2Action"));
        Assert.That(english.Count, Is.EqualTo(6));
    }
Beispiel #22
0
    public IEnumerator TODO_TrackedDeviceActions_CanDriveUI()
    {
        // Create device.
        InputSystem.RegisterLayout <TestTrackedDevice>();
        var trackedDevice = InputSystem.AddDevice <TestTrackedDevice>();

        var objects             = CreateScene();
        var uiModule            = objects.uiModule;
        var eventSystem         = objects.eventSystem;
        var leftChildGameObject = objects.leftGameObject;
        var leftChildReceiver   = leftChildGameObject != null?leftChildGameObject.GetComponent <UICallbackReceiver>() : null;

        var rightChildGameObject = objects.rightGameObject;
        var rightChildReceiver   = rightChildGameObject != null?rightChildGameObject.GetComponent <UICallbackReceiver>() : null;

        // Create actions.
        var map = new InputActionMap();
        var trackedPositionAction    = map.AddAction("position");
        var trackedOrientationAction = map.AddAction("orientation");
        var trackedSelectAction      = map.AddAction("selection");

        trackedPositionAction.AddBinding(trackedDevice.position);
        trackedOrientationAction.AddBinding(trackedDevice.orientation);
        trackedSelectAction.AddBinding(trackedDevice.select);

        // Wire up actions.
        // NOTE: In a normal usage scenario, the user would wire these up in the inspector.
        uiModule.AddTrackedDevice(new InputActionProperty(trackedPositionAction), new InputActionProperty(trackedOrientationAction), new InputActionProperty(trackedSelectAction));

        // Enable the whole thing.
        map.Enable();

        // We need to wait a frame to let the underlying canvas update and properly order the graphics images for raycasting.
        yield return(null);

        InputEventPtr stateEvent;

        using (StateEvent.From(trackedDevice, out stateEvent))
        {
            // Reset to Defaults
            trackedDevice.position.WriteValueIntoEvent(Vector3.zero, stateEvent);
            trackedDevice.orientation.WriteValueIntoEvent(Quaternion.Euler(0.0f, -90.0f, 0.0f), stateEvent);
            trackedDevice.select.WriteValueIntoEvent(0f, stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();

            leftChildReceiver.Reset();
            rightChildReceiver.Reset();

            // Move over left child.
            trackedDevice.orientation.WriteValueIntoEvent(Quaternion.Euler(0.0f, -30.0f, 0.0f), stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();
            eventSystem.InvokeUpdate();

            Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
            Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
            leftChildReceiver.Reset();
            Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

            // Check basic down/up
            trackedDevice.select.WriteValueIntoEvent(1f, stateEvent);
            InputSystem.QueueEvent(stateEvent);
            trackedDevice.select.WriteValueIntoEvent(0f, stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();
            eventSystem.InvokeUpdate();

            Assert.That(leftChildReceiver.events, Has.Count.EqualTo(4));
            Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
            Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
            Assert.That(leftChildReceiver.events[2].type, Is.EqualTo(EventType.Up));
            Assert.That(leftChildReceiver.events[3].type, Is.EqualTo(EventType.Click));
            leftChildReceiver.Reset();
            Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

            // Check down and drag
            trackedDevice.select.WriteValueIntoEvent(1f, stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();
            eventSystem.InvokeUpdate();

            Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
            Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
            Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
            leftChildReceiver.Reset();
            Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

            // Move to new location on left child
            trackedDevice.orientation.WriteValueIntoEvent(Quaternion.Euler(0.0f, -10.0f, 0.0f), stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();
            eventSystem.InvokeUpdate();

            Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
            Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.BeginDrag));
            Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
            leftChildReceiver.Reset();
            Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

            // Move children
            trackedDevice.orientation.WriteValueIntoEvent(Quaternion.Euler(0.0f, 30.0f, 0.0f), stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();
            eventSystem.InvokeUpdate();

            Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
            Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Exit));
            Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
            leftChildReceiver.Reset();
            Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
            Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
            rightChildReceiver.Reset();

            trackedDevice.select.WriteValueIntoEvent(0f, stateEvent);
            InputSystem.QueueEvent(stateEvent);
            InputSystem.Update();
            eventSystem.InvokeUpdate();

            Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
            Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Up));
            Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.EndDrag));
            leftChildReceiver.Reset();
            Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
            Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Drop));
            rightChildReceiver.Reset();
        }
    }
Beispiel #23
0
    public IEnumerator Actions_CanDriveUI()
    {
        // Create devices.
        var gamepad = InputSystem.AddDevice <Gamepad>();
        var mouse   = InputSystem.AddDevice <Mouse>();

        // Set up GameObject with EventSystem.
        var systemObject = new GameObject("System");
        var eventSystem  = systemObject.AddComponent <TestEventSystem>();
        var uiModule     = systemObject.AddComponent <UIActionInputModule>();

        eventSystem.UpdateModules();
        eventSystem.InvokeUpdate(); // Initial update only sets current module.

        // Set up canvas on which we can perform raycasts.
        var canvasObject = new GameObject("Canvas");
        var canvas       = canvasObject.AddComponent <Canvas>();

        canvas.renderMode = RenderMode.ScreenSpaceCamera;
        canvasObject.AddComponent <GraphicRaycaster>();
        var cameraObject = new GameObject("Camera");
        var camera       = cameraObject.AddComponent <Camera>();

        canvas.worldCamera = camera;
        camera.pixelRect   = new Rect(0, 0, 640, 480);

        // Set up a GameObject hierarchy that we send events to. In a real setup,
        // this would be a hierarchy involving UI components.
        var parentGameObject = new GameObject("Parent");
        var parentTransform  = parentGameObject.AddComponent <RectTransform>();

        parentGameObject.AddComponent <UICallbackReceiver>();
        var leftChildGameObject = new GameObject("Left Child");
        var leftChildTransform  = leftChildGameObject.AddComponent <RectTransform>();

        leftChildGameObject.AddComponent <Image>();
        var leftChildReceiver    = leftChildGameObject.AddComponent <UICallbackReceiver>();
        var rightChildGameObject = new GameObject("Right Child");
        var rightChildTransform  = rightChildGameObject.AddComponent <RectTransform>();

        rightChildGameObject.AddComponent <Image>();
        var rightChildReceiver = rightChildGameObject.AddComponent <UICallbackReceiver>();

        parentTransform.SetParent(canvas.transform, worldPositionStays: false);
        leftChildTransform.SetParent(parentTransform, worldPositionStays: false);
        rightChildTransform.SetParent(parentTransform, worldPositionStays: false);

        // Parent occupies full space of canvas.
        parentTransform.sizeDelta = new Vector2(640, 480);

        // Left child occupies left half of parent.
        leftChildTransform.anchoredPosition = new Vector2(-(640 / 4), 0);
        leftChildTransform.sizeDelta        = new Vector2(320, 480);

        // Right child occupies right half of parent.
        rightChildTransform.anchoredPosition = new Vector2(640 / 4, 0);
        rightChildTransform.sizeDelta        = new Vector2(320, 480);

        // Create actions.
        var map               = new InputActionMap();
        var pointAction       = map.AddAction("point");
        var moveAction        = map.AddAction("move");
        var submitAction      = map.AddAction("submit");
        var cancelAction      = map.AddAction("cancel");
        var leftClickAction   = map.AddAction("leftClick");
        var rightClickAction  = map.AddAction("rightClick");
        var middleClickAction = map.AddAction("middleClick");
        var scrollAction      = map.AddAction("scroll");

        // Create bindings.
        pointAction.AddBinding(mouse.position);
        leftClickAction.AddBinding(mouse.leftButton);
        rightClickAction.AddBinding(mouse.rightButton);
        middleClickAction.AddBinding(mouse.middleButton);
        scrollAction.AddBinding(mouse.scroll);
        moveAction.AddBinding(gamepad.leftStick);
        submitAction.AddBinding(gamepad.buttonSouth);
        cancelAction.AddBinding(gamepad.buttonEast);

        // Wire up actions.
        // NOTE: In a normal usage scenario, the user would wire these up in the inspector.
        uiModule.point       = new InputActionProperty(pointAction);
        uiModule.move        = new InputActionProperty(moveAction);
        uiModule.submit      = new InputActionProperty(submitAction);
        uiModule.cancel      = new InputActionProperty(cancelAction);
        uiModule.leftClick   = new InputActionProperty(leftClickAction);
        uiModule.middleClick = new InputActionProperty(middleClickAction);
        uiModule.rightClick  = new InputActionProperty(rightClickAction);
        uiModule.scrollWheel = new InputActionProperty(scrollAction);

        // Enable the whole thing.
        map.Enable();

        // We need to wait a frame to let the underlying canvas update and properly order the graphics images for raycasting.
        yield return(null);

        // Move mouse over left child.
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check basic down/up
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100), buttons = (ushort)(1 << (int)MouseState.Button.Left)
        });
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100), buttons = (ushort)0
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(4));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
        Assert.That(leftChildReceiver.events[2].type, Is.EqualTo(EventType.Up));
        Assert.That(leftChildReceiver.events[3].type, Is.EqualTo(EventType.Click));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check down and drag
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100), buttons = (ushort)(1 << (int)MouseState.Button.Right)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Move to new location on left child
        InputSystem.QueueDeltaStateEvent(mouse.position, new Vector2(100, 200));
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.BeginDrag));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Move children
        InputSystem.QueueDeltaStateEvent(mouse.position, new Vector2(400, 200));
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Exit));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
        rightChildReceiver.Reset();

        // Release button
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(400, 200), buttons = (ushort)0
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Up));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.EndDrag));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Drop));
        rightChildReceiver.Reset();

        // Check Scroll
        InputSystem.QueueDeltaStateEvent(mouse.scroll, Vector2.one);
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(0));
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Scroll));
        rightChildReceiver.Reset();

        // Reset Scroll
        InputSystem.QueueDeltaStateEvent(mouse.scroll, Vector2.zero);
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(0));
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Scroll));
        rightChildReceiver.Reset();

        // Test Selection
        eventSystem.SetSelectedGameObject(leftChildGameObject);
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Select));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Move Axes
        InputSystem.QueueDeltaStateEvent(gamepad.leftStick, new Vector2(1.0f, 0.0f));
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Move));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Submit
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = (uint)(1 << (int)GamepadState.Button.South)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Submit));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Cancel
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = (uint)(1 << (int)GamepadState.Button.East)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Cancel));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        // Check Selection Swap
        eventSystem.SetSelectedGameObject(rightChildGameObject);
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Deselect));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Select));
        rightChildReceiver.Reset();

        // Check Deselect
        eventSystem.SetSelectedGameObject(null);
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(0));
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Deselect));
        rightChildReceiver.Reset();
    }
Beispiel #24
0
    public IEnumerator TouchActions_CanDriveUI()
    {
        // Create devices.
        var touchDevice = InputSystem.AddDevice <TestTouchDevice>();

        var objects             = CreateScene();
        var uiModule            = objects.uiModule;
        var eventSystem         = objects.eventSystem;
        var leftChildGameObject = objects.leftGameObject;
        var leftChildReceiver   = leftChildGameObject != null?leftChildGameObject.GetComponent <UICallbackReceiver>() : null;

        var rightChildGameObject = objects.rightGameObject;
        var rightChildReceiver   = rightChildGameObject != null?rightChildGameObject.GetComponent <UICallbackReceiver>() : null;

        // Create actions.
        var map            = new InputActionMap();
        var positionAction = map.AddAction("position");
        var phaseAction    = map.AddAction("phase");

        // Create bindings.
        positionAction.AddBinding(touchDevice.touch.position);
        phaseAction.AddBinding(touchDevice.touch.phase);

        // Wire up actions.
        // NOTE: In a normal usage scenario, the user would wire these up in the inspector.
        uiModule.AddTouch(new InputActionProperty(positionAction), new InputActionProperty(phaseAction));

        // Enable the whole thing.
        map.Enable();

        // We need to wait a frame to let the underlying canvas update and properly order the graphics images for raycasting.
        yield return(null);

        // Move mouse over left child.
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(0, 0), phase = PointerPhase.Began
        });
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(100, 100), phase = PointerPhase.Moved
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(3));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
        Assert.That(leftChildReceiver.events[2].type, Is.EqualTo(EventType.Enter));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        //Drag to new location on left child
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(100, 200), phase = PointerPhase.Moved
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.BeginDrag));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(0));

        //Now move children
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(400, 200), phase = PointerPhase.Moved
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Exit));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.Dragging));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
        rightChildReceiver.Reset();


        //And now release
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(400, 200), phase = PointerPhase.Ended
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(2));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Up));
        Assert.That(leftChildReceiver.events[1].type, Is.EqualTo(EventType.EndDrag));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Drop));
        rightChildReceiver.Reset();

        //Now check for a quick click
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(400, 200), phase = PointerPhase.Began
        });
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(400, 200), phase = PointerPhase.Moved
        });
        InputSystem.QueueDeltaStateEvent(touchDevice.touch, new TouchState {
            position = new Vector2(400, 200), phase = PointerPhase.Ended
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(0));
        leftChildReceiver.Reset();
        Assert.That(rightChildReceiver.events, Has.Count.EqualTo(4));
        Assert.That(rightChildReceiver.events[0].type, Is.EqualTo(EventType.Down));
        Assert.That(rightChildReceiver.events[1].type, Is.EqualTo(EventType.PotentialDrag));
        Assert.That(rightChildReceiver.events[2].type, Is.EqualTo(EventType.Up));
        Assert.That(rightChildReceiver.events[3].type, Is.EqualTo(EventType.Click));
    }
    public void Editor_InputAsset_CanChangeCompositeType()
    {
        var map = new InputActionMap("map");

        map.AddAction(name: "action1");
        var asset = ScriptableObject.CreateInstance <InputActionAsset>();

        asset.AddActionMap(map);

        var obj             = new SerializedObject(asset);
        var mapProperty     = obj.FindProperty("m_ActionMaps").GetArrayElementAtIndex(0);
        var action1Property = mapProperty.FindPropertyRelative("m_Actions").GetArrayElementAtIndex(0);

        // Add an axis composite with a positive and negative binding in place.
        InputActionSerializationHelpers.AddCompositeBinding(action1Property, mapProperty, "Axis",
                                                            addPartBindings: false);
        InputActionSerializationHelpers.AddBinding(action1Property, mapProperty, path: "<Gamepad>/buttonWest",
                                                   name: "Negative", processors: "normalize", interactions: "tap", flags: InputBinding.Flags.PartOfComposite);
        InputActionSerializationHelpers.AddBinding(action1Property, mapProperty, path: "<Gamepad>/buttonEast",
                                                   name: "Positive", processors: "clamp", interactions: "slowtap", flags: InputBinding.Flags.PartOfComposite);

        // Noise.
        InputActionSerializationHelpers.AddBinding(action1Property, mapProperty, path: "foobar");

        // Change to vector2 composite and make sure that we've added two more bindings, changed the names
        // of bindings accordingly, and preserved the existing binding paths and such.
        InputActionSerializationHelpers.ChangeCompositeType(mapProperty.FindPropertyRelative("m_Bindings"), 0, "Dpad",
                                                            typeof(Vector2Composite), "action1");
        obj.ApplyModifiedPropertiesWithoutUndo();

        var action1 = asset.actionMaps[0].GetAction("action1");

        Assert.That(action1.bindings, Has.Count.EqualTo(6)); // Composite + 4 parts + noise added above.
        Assert.That(action1.bindings[0].path, Is.EqualTo("Dpad"));
        Assert.That(action1.bindings, Has.None.Matches((InputBinding x) =>
                                                       string.Equals(x.name, "positive", StringComparison.InvariantCultureIgnoreCase)));
        Assert.That(action1.bindings, Has.None.Matches((InputBinding x) =>
                                                       string.Equals(x.name, "negative", StringComparison.InvariantCultureIgnoreCase)));
        Assert.That(action1.bindings, Has.Exactly(1).Matches((InputBinding x) =>
                                                             string.Equals(x.name, "up", StringComparison.InvariantCultureIgnoreCase)));
        Assert.That(action1.bindings, Has.Exactly(1).Matches((InputBinding x) =>
                                                             string.Equals(x.name, "down", StringComparison.InvariantCultureIgnoreCase)));
        Assert.That(action1.bindings, Has.Exactly(1).Matches((InputBinding x) =>
                                                             string.Equals(x.name, "left", StringComparison.InvariantCultureIgnoreCase)));
        Assert.That(action1.bindings, Has.Exactly(1).Matches((InputBinding x) =>
                                                             string.Equals(x.name, "right", StringComparison.InvariantCultureIgnoreCase)));
        Assert.That(action1.bindings[0].isComposite, Is.True);
        Assert.That(action1.bindings[0].isPartOfComposite, Is.False);
        Assert.That(action1.bindings[1].isComposite, Is.False);
        Assert.That(action1.bindings[1].isPartOfComposite, Is.True);
        Assert.That(action1.bindings[2].isComposite, Is.False);
        Assert.That(action1.bindings[2].isPartOfComposite, Is.True);
        Assert.That(action1.bindings[3].isComposite, Is.False);
        Assert.That(action1.bindings[3].isPartOfComposite, Is.True);
        Assert.That(action1.bindings[4].isComposite, Is.False);
        Assert.That(action1.bindings[4].isPartOfComposite, Is.True);
        Assert.That(action1.bindings[1].path, Is.EqualTo("<Gamepad>/buttonWest"));
        Assert.That(action1.bindings[2].path, Is.EqualTo("<Gamepad>/buttonEast"));
        Assert.That(action1.bindings[1].interactions, Is.EqualTo("tap"));
        Assert.That(action1.bindings[2].interactions, Is.EqualTo("slowtap"));
        Assert.That(action1.bindings[1].processors, Is.EqualTo("normalize"));
        Assert.That(action1.bindings[2].processors, Is.EqualTo("clamp"));
        Assert.That(action1.bindings[3].path, Is.Empty);
        Assert.That(action1.bindings[4].path, Is.Empty);
        Assert.That(action1.bindings[3].interactions, Is.Empty);
        Assert.That(action1.bindings[4].interactions, Is.Empty);
        Assert.That(action1.bindings[3].processors, Is.Empty);
        Assert.That(action1.bindings[4].processors, Is.Empty);
        Assert.That(action1.bindings[5].path, Is.EqualTo("foobar"));
        Assert.That(action1.bindings[5].name, Is.Empty);
    }
Beispiel #26
0
    public void Users_CanDetectWhenUnassignedDeviceIsUsed()
    {
        var gamepad1 = InputSystem.AddDevice <Gamepad>();
        var gamepad2 = InputSystem.AddDevice <Gamepad>();
        var gamepad3 = InputSystem.AddDevice <Gamepad>();

        var asset = ScriptableObject.CreateInstance <InputActionAsset>();
        var map   = new InputActionMap("map");

        asset.AddActionMap(map);

        var actionAssignedToUser = map.AddAction("action", binding: "<Gamepad>/buttonSouth");

        actionAssignedToUser.Enable();

        var actionNotAssignedToUser = new InputAction(binding: "<Gamepad>/buttonNorth");

        actionNotAssignedToUser.Enable();

        var user = new TestUser();

        InputUser.Add(user);

        // Noise.
        InputUser.Add(new TestUser());
        InputUser.all[1].AssignInputDevice(gamepad3);

        IInputUser   receivedUser    = null;
        InputAction  receivedAction  = null;
        InputControl receivedControl = null;

        InputUser.onUnassignedDeviceUsed +=
            (u, a, c) =>
        {
            Assert.That(receivedUser, Is.Null);
            receivedUser    = u;
            receivedAction  = a;
            receivedControl = c;
        };

        user.AssignInputActions(asset);
        user.AssignInputDevice(gamepad1);

        // No callback if using gamepad1.
        InputSystem.QueueStateEvent(gamepad1, new GamepadState().WithButton(GamepadButton.South));
        InputSystem.Update();

        Assert.That(receivedUser, Is.Null);
        Assert.That(receivedAction, Is.Null);
        Assert.That(receivedControl, Is.Null);

        // Callback when using gamepad2.
        InputSystem.QueueStateEvent(gamepad2, new GamepadState().WithButton(GamepadButton.South));
        InputSystem.Update();

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedAction, Is.SameAs(actionAssignedToUser));
        Assert.That(receivedControl, Is.SameAs(gamepad2.buttonSouth));

        receivedUser    = null;
        receivedControl = null;
        receivedAction  = null;

        // No callback when triggering action not assigned to user.
        InputSystem.QueueStateEvent(gamepad1, new GamepadState().WithButton(GamepadButton.North));
        InputSystem.Update();

        Assert.That(receivedUser, Is.Null);
        Assert.That(receivedAction, Is.Null);
        Assert.That(receivedControl, Is.Null);
    }
        private void DoCreateActions()
        {
            if (actionAsset.objectReferenceValue == null)
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Create Actions", GUILayout.Width(140)))
                {
                    string fileName = EditorUtility.SaveFilePanel("Create Input Actions Asset", "Assets", Application.productName, InputActionAsset.Extension);
                    if (!string.IsNullOrEmpty(fileName))
                    {
                        if (!fileName.StartsWith(Application.dataPath))
                        {
                            Debug.LogError("Path must be located in Assets/ folder.");
                            EditorGUILayout.EndHorizontal();
                            return;
                        }

                        if (!fileName.EndsWith("." + InputActionAsset.Extension))
                        {
                            fileName += "." + InputActionAsset.Extension;
                        }

                        InputActionAsset actions = CreateInstance <InputActionAsset>();

                        actions.name = Path.GetFileNameWithoutExtension(fileName);

                        InputActionMap playerMap = new InputActionMap("Player");
                        actions.AddActionMap(playerMap);

                        playerMap.AddAction("Move", InputActionType.Value, expectedControlLayout: "Vector2");
                        playerMap.AddAction("Look", InputActionType.Value, expectedControlLayout: "Vector2");
                        playerMap.AddAction("Zoom", InputActionType.Button);
                        playerMap.AddAction("Jump", InputActionType.Button);
                        playerMap.AddAction("Crouch", InputActionType.Button);
                        playerMap.AddAction("Run", InputActionType.Button);
#if !GOLD_PLAYER_DISABLE_INTERACTION
                        playerMap.AddAction("Interact", InputActionType.Button);
#endif

                        playerMap.AddBinding(new InputBinding("2DVector", "Move", null, null, null, "WASD")
                        {
                            isComposite = true
                        });
                        playerMap.AddBinding(new InputBinding("<Keyboard>/w", "Move", "WASD", null, null, "up")
                        {
                            isPartOfComposite = true
                        });
                        playerMap.AddBinding(new InputBinding("<Keyboard>/s", "Move", "WASD", null, null, "down")
                        {
                            isPartOfComposite = true
                        });
                        playerMap.AddBinding(new InputBinding("<Keyboard>/a", "Move", "WASD", null, null, "left")
                        {
                            isPartOfComposite = true
                        });
                        playerMap.AddBinding(new InputBinding("<Keyboard>/d", "Move", "WASD", null, null, "right")
                        {
                            isPartOfComposite = true
                        });
                        playerMap.AddBinding(new InputBinding("<Gamepad>/leftStick", "Move", "Gamepad", null, null, null));

                        playerMap.AddBinding(new InputBinding("<Mouse>/delta", "Look", "Keyboard", "ScaleVector2(x=0.1,y=0.1)", null, null));
                        playerMap.AddBinding(new InputBinding("<Gamepad>/rightStick", "Look", "Keyboard", "ScaleVector2(x=2,y=2)", null, null));
                        playerMap.AddBinding(new InputBinding("<Keyboard>/z", "Zoom", "Keyboard"));
                        playerMap.AddBinding(new InputBinding("<Gamepad>/leftShoulder", "Zoom", "Gamepad"));

                        playerMap.AddBinding(new InputBinding("<Keyboard>/space", "Jump", "Keyboard", null, null, null));
                        playerMap.AddBinding(new InputBinding("<Gamepad>/buttonSouth", "Jump", "Gamepad", null, null, null));

                        playerMap.AddBinding(new InputBinding("<Keyboard>/c", "Crouch", "Keyboard", null, null, null));
                        playerMap.AddBinding(new InputBinding("<Gamepad>/leftStickPress", "Crouch", "Gamepad", null, null, null));

                        playerMap.AddBinding(new InputBinding("<Keyboard>/leftShift", "Run", "Keyboard", null, null, null));
                        playerMap.AddBinding(new InputBinding("<Gamepad>/rightTrigger", "Run", "Gamepad", null, null, null));

#if !GOLD_PLAYER_DISABLE_INTERACTION
                        playerMap.AddBinding(new InputBinding("<Keyboard>/e", "Interact", "Keyboard", null, null, null));
                        playerMap.AddBinding(new InputBinding("<Gamepad>/buttonWest", "Interact", "Gamepad", null, null, null));
#endif

#if GOLD_PLAYER_UGUI
                        InputActionMap uiMap = new InputActionMap("UI");
                        actions.AddActionMap(uiMap);

                        uiMap.AddAction("Navigate", InputActionType.Value, expectedControlLayout: "Vector2");
                        uiMap.AddAction("Submit", InputActionType.Button);
                        uiMap.AddAction("Cancel", InputActionType.Button);
                        uiMap.AddAction("Point", InputActionType.Button);
                        uiMap.AddAction("Click", InputActionType.Button);
                        uiMap.AddAction("ScrollWheel", InputActionType.Value, expectedControlLayout: "Vector2");
                        uiMap.AddAction("MiddleClick", InputActionType.Button);
                        uiMap.AddAction("RightClick", InputActionType.Button);

                        uiMap.AddBinding(new InputBinding("2DVector", "Navigate", null, null, null, "Gamepad")
                        {
                            isComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/leftStick/up", "Navigate", ";Gamepad", null, null, "up")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/rightStick/up", "Navigate", ";Gamepad", null, null, "up")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/leftStick/down", "Navigate", ";Gamepad", null, null, "down")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/rightStick/down", "Navigate", ";Gamepad", null, null, "down")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/leftStick/left", "Navigate", ";Gamepad", null, null, "left")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/rightStick/left", "Navigate", ";Gamepad", null, null, "left")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/leftStick/right", "Navigate", ";Gamepad", null, null, "right")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/rightStick/right", "Navigate", ";Gamepad", null, null, "right")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Gamepad>/dpad", "Navigate", ";Gamepad", null, null, null));
                        uiMap.AddBinding(new InputBinding("2DVector", "Navigate", null, null, null, "Joystick")
                        {
                            isComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Joystick>/stick/up", "Navigate", "Joystick", null, null, "up")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Joystick>/stick/down", "Navigate", "Joystick", null, null, "down")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Joystick>/stick/left", "Navigate", "Joystick", null, null, "left")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Joystick>/stick/right", "Navigate", "Joystick", null, null, "right")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("2DVector", "Navigate", null, null, null, "Keyboard")
                        {
                            isComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/w", "Navigate", "Keyboard", null, null, "up")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/s", "Navigate", "Keyboard", null, null, "down")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/a", "Navigate", "Keyboard", null, null, "left")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/d", "Navigate", "Keyboard", null, null, "right")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/upArrow", "Navigate", "Keyboard", null, null, "up")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/downArrow", "Navigate", "Keyboard", null, null, "down")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/leftArrow", "Navigate", "Keyboard", null, null, "left")
                        {
                            isPartOfComposite = true
                        });
                        uiMap.AddBinding(new InputBinding("<Keyboard>/rightArrow", "Navigate", "Keyboard", null, null, "right")
                        {
                            isPartOfComposite = true
                        });

                        uiMap.AddBinding(new InputBinding("*/{Submit}", "Submit"));

                        uiMap.AddBinding(new InputBinding("*/{Cancel}", "Cancel"));

                        uiMap.AddBinding(new InputBinding("<Mouse>/position", "Point", "Keyboard"));
                        uiMap.AddBinding(new InputBinding("<Pen>/position", "Point", "Keyboard"));
                        uiMap.AddBinding(new InputBinding("<Touchscreen>/touch*/position", "Point", "Touch"));

                        uiMap.AddBinding(new InputBinding("<Mouse>/leftButton", "Click", ";Keyboard"));
                        uiMap.AddBinding(new InputBinding("<Pen>/tip", "Click", ";Keyboard"));
                        uiMap.AddBinding(new InputBinding("<Touchscreen>/touch*/press", "Click", "Touch"));
                        uiMap.AddBinding(new InputBinding("<XRController>/trigger", "Click", "XR"));

                        uiMap.AddBinding(new InputBinding("<Mouse>/scroll", "ScrollWheel", ";Keyboard"));

                        uiMap.AddBinding(new InputBinding("<Mouse>/middleButton", "MiddleClick", ";Keyboard"));

                        uiMap.AddBinding(new InputBinding("<Mouse>/rightButton", "RightClick", ";Keyboard"));
#endif

                        InputControlScheme.DeviceRequirement[] keyboardDevice = new InputControlScheme.DeviceRequirement[]
                        {
                            new InputControlScheme.DeviceRequirement()
                            {
                                controlPath = "<Keyboard>",
                                isOptional  = false,
                                isOR        = false
                            },
                            new InputControlScheme.DeviceRequirement()
                            {
                                controlPath = "<Mouse>",
                                isOptional  = true,
                                isOR        = false
                            }
                        };
                        InputControlScheme.DeviceRequirement[] gamepadDevice = new InputControlScheme.DeviceRequirement[]
                        {
                            new InputControlScheme.DeviceRequirement()
                            {
                                controlPath = "<Gamepad>",
                                isOptional  = false,
                                isOR        = false
                            }
                        };
                        InputControlScheme.DeviceRequirement[] touchDevice = new InputControlScheme.DeviceRequirement[]
                        {
                            new InputControlScheme.DeviceRequirement()
                            {
                                controlPath = "<Touchscreen>",
                                isOptional  = false,
                                isOR        = false
                            }
                        };
                        InputControlScheme.DeviceRequirement[] joystickDevice = new InputControlScheme.DeviceRequirement[]
                        {
                            new InputControlScheme.DeviceRequirement()
                            {
                                controlPath = "<Joystick>",
                                isOptional  = false,
                                isOR        = false
                            }
                        };

                        actions.AddControlScheme(new InputControlScheme("Keyboard", keyboardDevice, "Keyboard"));
                        actions.AddControlScheme(new InputControlScheme("Gamepad", gamepadDevice, "Gamepad"));
                        actions.AddControlScheme(new InputControlScheme("Touch", touchDevice, "Touch"));
                        actions.AddControlScheme(new InputControlScheme("Joystick", joystickDevice, "Joystick"));

                        File.WriteAllText(fileName, actions.ToJson());
                        AssetDatabase.Refresh();

                        EditorApplication.delayCall += () =>
                        {
                            // Need to get the properties again or else we will get a "property is disposed" error.
                            GetProperties();

                            string           relativePath  = "Assets/" + fileName.Substring(Application.dataPath.Length + 1);
                            InputActionAsset loadedActions = AssetDatabase.LoadAssetAtPath <InputActionAsset>(relativePath);
                            actionAsset.objectReferenceValue = loadedActions;
                            serializedObject.ApplyModifiedProperties();
                            serializedObject.Update();
                            PopulateActions();
                            serializedObject.Update();
                            ReassignActions();
                        };
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
        }
Beispiel #28
0
    public void TDO_Actions_CanDriveUI()
    {
        // Create devices.
        var gamepad  = InputSystem.AddDevice <Gamepad>();
        var keyboard = InputSystem.AddDevice <Keyboard>();
        var mouse    = InputSystem.AddDevice <Mouse>();

        // Set up GameObject with EventSystem.
        var systemObject = new GameObject();
        var eventSystem  = systemObject.AddComponent <TestEventSystem>();
        var uiModule     = systemObject.AddComponent <UIActionInputModule>();

        eventSystem.UpdateModules();
        eventSystem.InvokeUpdate(); // Initial update only sets current module.

        // Set up canvas on which we can perform raycasts.
        var canvasObject = new GameObject();
        var canvas       = canvasObject.AddComponent <Canvas>();
        var cameraObject = new GameObject();
        var camera       = cameraObject.AddComponent <Camera>();

        canvas.worldCamera = camera;
        camera.pixelRect   = new Rect(0, 0, 640, 480);

        // Set up a GameObject hierarchy that we send events to. In a real setup,
        // this would be a hierarchy involving UI components.
        var parentGameObject     = new GameObject();
        var parentTransform      = parentGameObject.AddComponent <RectTransform>();
        var parentReceiver       = parentGameObject.AddComponent <UICallbackReceiver>();
        var leftChildGameObject  = new GameObject();
        var leftChildTransform   = leftChildGameObject.AddComponent <RectTransform>();
        var leftChildReceiver    = leftChildGameObject.AddComponent <UICallbackReceiver>();
        var rightChildGameObject = new GameObject();
        var rightChildTransform  = rightChildGameObject.AddComponent <RectTransform>();
        var rightChildReceiver   = rightChildGameObject.AddComponent <UICallbackReceiver>();

        parentTransform.SetParent(canvas.transform, worldPositionStays: false);
        leftChildTransform.SetParent(parentTransform, worldPositionStays: false);
        rightChildTransform.SetParent(parentTransform, worldPositionStays: false);

        // Parent occupies full space of canvas.
        parentTransform.sizeDelta = new Vector2(640, 480);

        // Left child occupies left half of parent.
        leftChildTransform.anchoredPosition = new Vector2(-(640 / 4), 0);
        leftChildTransform.sizeDelta        = new Vector2(320, 480);

        // Right child occupies right half of parent.
        rightChildTransform.anchoredPosition = new Vector2(640 / 4, 0);
        rightChildTransform.sizeDelta        = new Vector2(320, 480);

        // Create actions.
        var map               = new InputActionMap();
        var pointAction       = map.AddAction("point");
        var moveAction        = map.AddAction("move");
        var submitAction      = map.AddAction("submit");
        var cancelAction      = map.AddAction("cancel");
        var leftClickAction   = map.AddAction("leftClick");
        var rightClickAction  = map.AddAction("rightClick");
        var middleClickAction = map.AddAction("middleClick");

        // Create bindings.
        pointAction.AddBinding(mouse.position);
        moveAction.AddBinding(gamepad.leftStick);
        submitAction.AddBinding(gamepad.buttonSouth);
        cancelAction.AddBinding(gamepad.buttonEast);
        cancelAction.AddBinding(keyboard.escapeKey);

        // Wire up actions.
        // NOTE: In a normal usage scenario, the user would wire these up in the inspector.
        uiModule.point       = new InputActionProperty(pointAction);
        uiModule.move        = new InputActionProperty(moveAction);
        uiModule.submit      = new InputActionProperty(submitAction);
        uiModule.cancel      = new InputActionProperty(cancelAction);
        uiModule.leftClick   = new InputActionProperty(leftClickAction);
        uiModule.middleClick = new InputActionProperty(middleClickAction);
        uiModule.rightClick  = new InputActionProperty(rightClickAction);

        // Enable the whole thing.
        map.Enable();

        // Move mouse over left child.
        InputSystem.QueueStateEvent(mouse, new MouseState {
            position = new Vector2(100, 100)
        });
        InputSystem.Update();
        eventSystem.InvokeUpdate();

        Assert.That(leftChildReceiver.events, Has.Count.EqualTo(1));
        Assert.That(leftChildReceiver.events[0].type, Is.EqualTo(EventType.Enter));
    }
Beispiel #29
0
        void RegisterInputs()
        {
#if UNITY_EDITOR && !USE_INPUT_SYSTEM
            var inputEntries = new List <InputManagerEntry>
            {
                new InputManagerEntry {
                    name = kEnableDebugBtn1, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl", altBtnPositive = "joystick button 8"
                },
                new InputManagerEntry {
                    name = kEnableDebugBtn2, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "backspace", altBtnPositive = "joystick button 9"
                },
                new InputManagerEntry {
                    name = kResetBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left alt", altBtnPositive = "joystick button 1"
                },
                new InputManagerEntry {
                    name = kDebugNextBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page down", altBtnPositive = "joystick button 5"
                },
                new InputManagerEntry {
                    name = kDebugPreviousBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "page up", altBtnPositive = "joystick button 4"
                },
                new InputManagerEntry {
                    name = kValidateBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "return", altBtnPositive = "joystick button 0"
                },
                new InputManagerEntry {
                    name = kPersistentBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right shift", altBtnPositive = "joystick button 2"
                },
                new InputManagerEntry {
                    name = kMultiplierBtn, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left shift", altBtnPositive = "joystick button 3"
                },
                new InputManagerEntry {
                    name = kDPadHorizontal, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "right", btnNegative = "left", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f
                },
                new InputManagerEntry {
                    name = kDPadVertical, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "up", btnNegative = "down", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f
                },
                new InputManagerEntry {
                    name = kDPadVertical, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Seventh, btnPositive = "up", btnNegative = "down", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f
                },
                new InputManagerEntry {
                    name = kDPadHorizontal, kind = InputManagerEntry.Kind.Axis, axis = InputManagerEntry.Axis.Sixth, btnPositive = "right", btnNegative = "left", gravity = 1000f, deadZone = 0.001f, sensitivity = 1000f
                },
            };

            InputRegistering.RegisterInputs(inputEntries);
#endif

#if USE_INPUT_SYSTEM
            // Register input system actions
            var enableAction = debugActionMap.AddAction(kEnableDebug, type: InputActionType.Button);
            enableAction.AddCompositeBinding("ButtonWithOneModifier")
            .With("Modifier", "<Gamepad>/rightStickPress")
            .With("Button", "<Gamepad>/leftStickPress")
            .With("Modifier", "<Keyboard>/leftCtrl")
            .With("Button", "<Keyboard>/backspace");

            var resetAction = debugActionMap.AddAction(kResetBtn, type: InputActionType.Button);
            resetAction.AddCompositeBinding("ButtonWithOneModifier")
            .With("Modifier", "<Gamepad>/rightStickPress")
            .With("Button", "<Gamepad>/b")
            .With("Modifier", "<Keyboard>/leftAlt")
            .With("Button", "<Keyboard>/backspace");

            var next = debugActionMap.AddAction(kDebugNextBtn, type: InputActionType.Button);
            next.AddBinding("<Keyboard>/pageDown");
            next.AddBinding("<Gamepad>/rightShoulder");

            var previous = debugActionMap.AddAction(kDebugPreviousBtn, type: InputActionType.Button);
            previous.AddBinding("<Keyboard>/pageUp");
            previous.AddBinding("<Gamepad>/leftShoulder");

            var validateAction = debugActionMap.AddAction(kValidateBtn, type: InputActionType.Button);
            validateAction.AddBinding("<Keyboard>/enter");
            validateAction.AddBinding("<Gamepad>/a");

            var persistentAction = debugActionMap.AddAction(kPersistentBtn, type: InputActionType.Button);
            persistentAction.AddBinding("<Keyboard>/rightShift");
            persistentAction.AddBinding("<Gamepad>/x");

            var multiplierAction = debugActionMap.AddAction(kMultiplierBtn, type: InputActionType.Value);
            multiplierAction.AddBinding("<Keyboard>/leftShift");
            multiplierAction.AddBinding("<Gamepad>/y");

            var moveVerticalAction = debugActionMap.AddAction(kDPadVertical);
            moveVerticalAction.AddCompositeBinding("1DAxis")
            .With("Positive", "<Gamepad>/dpad/up")
            .With("Negative", "<Gamepad>/dpad/down")
            .With("Positive", "<Keyboard>/upArrow")
            .With("Negative", "<Keyboard>/downArrow");

            var moveHorizontalAction = debugActionMap.AddAction(kDPadHorizontal);
            moveHorizontalAction.AddCompositeBinding("1DAxis")
            .With("Positive", "<Gamepad>/dpad/right")
            .With("Negative", "<Gamepad>/dpad/left")
            .With("Positive", "<Keyboard>/rightArrow")
            .With("Negative", "<Keyboard>/leftArrow");
#endif
        }
Beispiel #30
0
    public void Users_CanDetectChangeInBindings()
    {
        var actions = new InputActionMap();
        var action  = actions.AddAction("action", binding: "<Gamepad>/leftTrigger");

        action.Enable();

        var gamepad1 = InputSystem.AddDevice <Gamepad>();
        var user     = InputUser.PerformPairingWithDevice(gamepad1);

        user.AssociateActionsWithUser(actions);

        InputUser?      receivedUser   = null;
        InputUserChange?receivedChange = null;
        InputDevice     receivedDevice = null;

        InputUser.onChange +=
            (u, c, d) =>
        {
            if (c != InputUserChange.ControlsChanged)
            {
                return;
            }

            Assert.That(receivedUser, Is.Null);
            Assert.That(receivedChange, Is.Null);
            Assert.That(receivedDevice, Is.Null);

            receivedUser   = u;
            receivedChange = c;
            receivedDevice = d;
        };

        // Rebind.
        action.ApplyBindingOverride("<Gamepad>/rightTrigger");

        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlsChanged));
        Assert.That(receivedUser, Is.EqualTo(user));
        Assert.That(receivedDevice, Is.Null);

        receivedChange = null;
        receivedUser   = null;
        receivedDevice = null;

        // Pair new device.
        var gamepad2 = InputSystem.AddDevice <Gamepad>();

        InputUser.PerformPairingWithDevice(gamepad2, user: user);

        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlsChanged));
        Assert.That(receivedUser, Is.EqualTo(user));
        Assert.That(receivedDevice, Is.Null);

        receivedChange = null;
        receivedUser   = null;
        receivedDevice = null;

        // Unpair device.
        user.UnpairDevice(gamepad1);

        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlsChanged));
        Assert.That(receivedUser, Is.EqualTo(user));
        Assert.That(receivedDevice, Is.Null);

        receivedChange = null;
        receivedUser   = null;
        receivedDevice = null;

        // Remove user and then add new one.
        var oldUser = user;

        user.UnpairDevicesAndRemoveUser();

        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlsChanged));
        Assert.That(receivedUser, Is.EqualTo(oldUser));
        Assert.That(receivedDevice, Is.Null);

        receivedChange = null;
        receivedUser   = null;
        receivedDevice = null;

        user = InputUser.PerformPairingWithDevice(gamepad1);
        user.AssociateActionsWithUser(actions);

        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlsChanged));
        Assert.That(receivedUser, Is.EqualTo(user));
        Assert.That(receivedDevice, Is.Null);

        receivedChange = null;
        receivedUser   = null;
        receivedDevice = null;

        action.ApplyBindingOverride("<Gamepad>/leftTrigger");

        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlsChanged));
        Assert.That(receivedUser, Is.EqualTo(user));
        Assert.That(receivedDevice, Is.Null);
    }