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 }));
    }
        /// <summary>
        /// Create an action map with the given name and add it to the asset.
        /// </summary>
        /// <param name="asset">Asset to add the action map to</param>
        /// <param name="name">Name to assign to the </param>
        /// <returns>The newly added action map.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="asset"/> is <c>null</c> or
        /// <exception cref="InvalidOperationException">An action map with the given <paramref name="name"/>
        /// already exists in <paramref name="asset"/>.</exception>
        /// <paramref name="name"/> is <c>null</c> or empty.</exception>
        public static InputActionMap AddActionMap(this InputActionAsset asset, string name)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(nameof(asset));
            }
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }
            if (asset.FindActionMap(name) != null)
            {
                throw new InvalidOperationException(
                          $"An action map called '{name}' already exists in the asset");
            }

            var map = new InputActionMap(name);

            map.GenerateId();
            asset.AddActionMap(map);
            return(map);
        }
示例#3
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"));
    }
        /// <summary>
        /// Apply the given binding override to all bindings in the map that are matched by the override.
        /// </summary>
        /// <param name="actionMap"></param>
        /// <param name="bindingOverride"></param>
        /// <returns>The number of bindings overridden in the given map.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="actionMap"/> is <c>null</c>.</exception>
        /// <exception cref="InvalidOperationException"><paramref name="actionMap"/> is currently enabled.</exception>
        /// <remarks>
        /// </remarks>
        public static int ApplyBindingOverride(this InputActionMap actionMap, InputBinding bindingOverride)
        {
            if (actionMap == null)
            {
                throw new ArgumentNullException(nameof(actionMap));
            }
            actionMap.ThrowIfModifyingBindingsIsNotAllowed();

            var bindings = actionMap.m_Bindings;

            if (bindings == null)
            {
                return(0);
            }

            // Go through all bindings in the map and match them to the override.
            var bindingCount = bindings.Length;
            var matchCount   = 0;

            for (var i = 0; i < bindingCount; ++i)
            {
                if (!bindingOverride.Matches(ref bindings[i]))
                {
                    continue;
                }

                // Set overrides on binding.
                bindings[i].overridePath         = bindingOverride.overridePath;
                bindings[i].overrideInteractions = bindingOverride.overrideInteractions;
                ++matchCount;
            }

            if (matchCount > 0)
            {
                actionMap.LazyResolveBindings();
            }

            return(matchCount);
        }
示例#5
0
    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"));
    }
    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);
    }
    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        else
        {
            Destroy(this);
        }

        _inputs       = GetComponent <PlayerInput>();
        playerActions = _inputs.actions.FindActionMap("Player", true);
        uiActions     = _inputs.actions.FindActionMap("UI", true);
        playerMove    = playerActions.FindAction("Move");
        playerLook    = playerActions.FindAction("Look");
        playerJump    = playerActions.FindAction("Jump");
        playerRoll    = playerActions.FindAction("Roll");
        playerDash    = playerActions.FindAction("Dash");
        cycleTarget   = playerActions.FindAction("CycleTarget");
        playerAttack  = playerActions.FindAction("Attack");
        mousePosition = uiActions.FindAction("MousePosition");
        playerActions.Disable();

        playerJump.performed += OnJump_Pressed;
        playerJump.canceled  += OnJump_Released;

        playerRoll.performed += OnRoll_Pressed;
        playerRoll.canceled  += OnRoll_Released;

        playerDash.performed += OnDash_Pressed;
        playerDash.canceled  += OnDash_Released;

        playerAttack.performed += OnAttack_Pressed;
        playerAttack.canceled  += OnAttack_Released;

        cycleTarget.performed += OnCycleTarget_Pressed;
    }
示例#8
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"" : [
                    ]
"));
    }
示例#9
0
        public static void AddActionMapFromObject(SerializedObject asset, InputActionMap map)
        {
            var mapArrayProperty = asset.FindProperty("m_ActionMaps");
            var mapCount         = mapArrayProperty.arraySize;
            var index            = mapCount;
            var name             = FindUniqueName(mapArrayProperty, map.name);

            mapArrayProperty.InsertArrayElementAtIndex(index);
            var mapProperty = mapArrayProperty.GetArrayElementAtIndex(index);

            mapProperty.FindPropertyRelative("m_Actions").ClearArray();
            mapProperty.FindPropertyRelative("m_Bindings").ClearArray();
            mapProperty.FindPropertyRelative("m_Name").stringValue = name;

            for (var i = 0; i < map.actions.Count; i++)
            {
                var newActionProperty = AddActionFromObject(map.actions[i], mapProperty);
                for (var j = 0; j < map.actions[i].bindings.Count; j++)
                {
                    AppendBindingFromObject(map.actions[i].bindings[j], newActionProperty, mapProperty);
                }
            }
        }
示例#10
0
    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 static int ApplyBindingOverridesOnMatchingControls(this InputActionMap actionMap, InputControl control)
        {
            if (actionMap == null)
            {
                throw new ArgumentNullException(nameof(actionMap));
            }
            if (control == null)
            {
                throw new ArgumentNullException(nameof(control));
            }

            var actions             = actionMap.actions;
            var actionCount         = actions.Count;
            var numMatchingControls = 0;

            for (var i = 0; i < actionCount; ++i)
            {
                var action = actions[i];
                numMatchingControls = action.ApplyBindingOverridesOnMatchingControls(control);
            }

            return(numMatchingControls);
        }
示例#12
0
 public void Init(string name, InputActionMap map)
 {
     if (hasInit)
     {
         return;
     }
     title.text = name;
     actionMap  = map;
     foreach (InputAction action in actionMap.actions)
     {
         if (action.name.StartsWith("+"))
         {
             continue;                              //Filter keybinds that should not be modified (Designated with + prefix)
         }
         //Spawn a copy of the keybind object, and init them with input action data.
         OptionsInputActionController keybind = Instantiate(keybindPrefab.gameObject, transform)
                                                .GetComponent <OptionsInputActionController>();
         keybind.Init(action);
     }
     keybindPrefab.gameObject.SetActive(false);
     layoutGroup.spacing = layoutGroup.spacing;
     hasInit             = true;
 }
    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.
    }
        internal static IActuator[] CreateActuatorsFromMap(InputActionMap inputActionMap,
                                                           BehaviorParameters behaviorParameters,
                                                           InputDevice inputDevice)
        {
            var actuators = new IActuator[inputActionMap.actions.Count];

            for (var i = 0; i < inputActionMap.actions.Count; i++)
            {
                var action       = inputActionMap.actions[i];
                var actionLayout = InputSystem.LoadLayout(action.expectedControlType);
                var adaptor      = (IRLActionInputAdaptor)Activator.CreateInstance(controlTypeToAdaptorType[actionLayout.type]);
                actuators[i] = new InputActionActuator(inputDevice, behaviorParameters, action, adaptor);

                // Reasonably, the input system starts adding numbers after the first none numbered name
                // is added.  So for device ID of 0, we use the empty string in the path.
                var path = $"{inputDevice?.path}{InputControlPath.Separator}{action.name}";
                action.AddBinding(path,
                                  action.interactions,
                                  action.processors,
                                  mlAgentsControlSchemeName);
            }
            return(actuators);
        }
    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);
        });
    }
示例#16
0
 // Start is called before the first frame update
 void Start()
 {
     das             = PlayerPrefs.GetInt("DAS");
     arr             = PlayerPrefs.GetInt("ARR");
     sdg             = PlayerPrefs.GetFloat("SDG");
     rotateDCD       = PlayerPrefs.GetInt("rotateDCD");
     harddropDCD     = PlayerPrefs.GetInt("harddropDCD");
     holdDCD         = PlayerPrefs.GetInt("holdDCD");
     DASinterruption = PlayerPrefs.GetInt("interruptDAS") == 1; //A somewhat odd way of typcasting an int to a bool...
     //Set player keybinds into a mapping. This mapping's actions aren't linked to any method calls; it's just used as a way to store bindings.
     map = ref_PlayerInput.actions.FindActionMap("BindStorage");
     map.FindAction("Shift left").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyLeft"));
     map.FindAction("Shift right").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyRight"));
     map.FindAction("Soft drop").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keySoftDrop"));
     map.FindAction("Hard drop").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyHardDrop"));
     map.FindAction("Rotate CW").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyCW"));
     map.FindAction("Rotate CCW").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyCCW"));
     map.FindAction("Rotate 180").ChangeBinding(0).WithPath(PlayerPrefs.GetString("key180"));
     map.FindAction("Hold").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyHold"));
     map.FindAction("Pause").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyPause"));
     map.FindAction("Reset").ChangeBinding(0).WithPath(PlayerPrefs.GetString("keyReset"));
     //Debug.Log(map.actions[0].bindings[0].path);
     totalBindings = map.actions.Count;
 }
示例#17
0
    void chagebind()
    {
        InputActionMap iam = input.input.Get();

        InputAction[] ia = iam.actions.ToArray();
        input.Disable();

        for (int i = 0; i < ia.Length; i++)
        {
            if (PlayerPrefs.HasKey(ia[i].name + "0"))
            {
                int pref0 = PlayerPrefs.GetInt(ia[i].name + "0");
                if (KeyCodes[pref0] == null)
                {
                    ia[i].ApplyBindingOverride(0, "<>/");
                }
                else
                {
                    string[] path = KeyCodes[pref0].path.Split('/');
                    ia[i].ApplyBindingOverride(0, "<" + path[1] + ">/" + path[2]);
                }

                int pref1 = PlayerPrefs.GetInt(ia[i].name + "1");
                if (KeyCodes[pref1] == null)
                {
                    ia[i].ApplyBindingOverride(1, "<>/");
                }
                else
                {
                    string[] path = KeyCodes[PlayerPrefs.GetInt(ia[i].name + "1")].path.Split('/');
                    ia[i].ApplyBindingOverride(1, "<" + path[1] + ">/" + path[2]);
                }
            }
        }
        input.Enable();
    }
示例#18
0
    private void LoadPlayerTwoBinds(InputActionMap inputMap)
    {
        List <UserData.BindingSerializable> playerTwoBindingList;

        if (userData.GetKeyboardBindingList(out playerTwoBindingList))
        {
            Dictionary <System.Guid, string> overrides = new Dictionary <System.Guid, string>();
            foreach (var item in playerTwoBindingList)
            {
                overrides.Add(new System.Guid(item.id), item.path);
            }

            var bindings = inputMap.bindings;
            for (int i = 0; i < bindings.Count; ++i)
            {
                if (overrides.TryGetValue(bindings[i].id, out string overridePath))
                {
                    inputMap.ApplyBindingOverride(i, new InputBinding {
                        overridePath = overridePath
                    });
                }
            }
        }
    }
        /// <summary>
        /// Remove the given action map from the asset.
        /// </summary>
        /// <param name="asset">Asset to add the action map to.</param>
        /// <param name="map">An action map. If the given map is not part of the asset, the method
        /// does nothing.</param>
        /// <exception cref="ArgumentNullException"><paramref name="asset"/> or <paramref name="map"/> is <c>null</c>.</exception>
        /// <exception cref="InvalidOperationException"><paramref name="map"/> is currently enabled (see <see
        /// cref="InputActionMap.enabled"/>).</exception>
        /// <seealso cref="RemoveActionMap(InputActionAsset,string)"/>
        /// <seealso cref="InputActionAsset.actionMaps"/>
        public static void RemoveActionMap(this InputActionAsset asset, InputActionMap map)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(nameof(asset));
            }
            if (map == null)
            {
                throw new ArgumentNullException(nameof(map));
            }
            if (map.enabled)
            {
                throw new InvalidOperationException("Cannot remove an action map from the asset while it is enabled");
            }

            // Ignore if not part of this asset.
            if (map.m_Asset != asset)
            {
                return;
            }

            ArrayHelpers.Erase(ref asset.m_ActionMaps, map);
            map.m_Asset = null;
        }
示例#20
0
    // Start is called before the first frame update


    void Start()
    {
        //  Pjum = JumpAmount;
        gravity = Physics.gravity;

        onFootMap = actionsAssests.FindActionMap("OnFoot");

        onFootMap.Enable();

        moveAction = onFootMap.FindAction("Move");

        jumpAction = onFootMap.FindAction("Jump");

        crouchAction = onFootMap.FindAction("Crouch");

        moveAction.performed += context => OnMove(context);
        moveAction.canceled  += ctx => OnMove(ctx);

        jumpAction.performed += context => OnJump(context);
        jumpAction.canceled  += ctx => OnJump(ctx);

        crouchAction.performed += context => OnCrouch(context);
        crouchAction.canceled  += ctx => OnCrouch(ctx);
    }
示例#21
0
 private void Awake()
 {
     mPlayerActionMap = mActionAsset.FindActionMap("Key");
     RegisterInputAction();
     mPlayerActionMap.Enable();
 }
 internal BindingSyntax(InputActionMap map, InputAction action, int bindingIndex)
 {
     m_ActionMap    = map;
     m_Action       = action;
     m_BindingIndex = bindingIndex;
 }
 internal CompositeSyntax(InputActionMap map, InputAction action, int compositeIndex)
 {
     m_Action         = action;
     m_ActionMap      = map;
     m_CompositeIndex = compositeIndex;
 }
示例#24
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
        }
示例#25
0
    public PlayerInputActions()
    {
        asset = InputActionAsset.FromJson(@"{
    ""name"": ""PlayerInputActions"",
    ""maps"": [
        {
            ""name"": ""Player"",
            ""id"": ""de43ca36-e2cd-4353-adc4-cfdfc8a92147"",
            ""actions"": [
                {
                    ""name"": ""FireAction"",
                    ""type"": ""Button"",
                    ""id"": ""ec20e427-03da-46bd-ad88-661d5c69f632"",
                    ""expectedControlType"": ""Button"",
                    ""processors"": """",
                    ""interactions"": """"
                },
                {
                    ""name"": ""SkillAction"",
                    ""type"": ""Button"",
                    ""id"": ""8fd1c5db-a516-4a29-8168-2dfa7fc7705f"",
                    ""expectedControlType"": ""Button"",
                    ""processors"": """",
                    ""interactions"": """"
                },
                {
                    ""name"": ""Horizontal"",
                    ""type"": ""Button"",
                    ""id"": ""aa60f257-41b9-4395-9936-0b2f2f0f3928"",
                    ""expectedControlType"": ""Button"",
                    ""processors"": """",
                    ""interactions"": """"
                },
                {
                    ""name"": ""MousePos"",
                    ""type"": ""Value"",
                    ""id"": ""84c74cb1-73d5-4238-a3c5-ec2fb6404ef6"",
                    ""expectedControlType"": ""Vector2"",
                    ""processors"": """",
                    ""interactions"": """"
                }
            ],
            ""bindings"": [
                {
                    ""name"": """",
                    ""id"": ""af8acf16-1664-4f60-af13-fbc605ec1e4a"",
                    ""path"": ""<Keyboard>/q"",
                    ""interactions"": """",
                    ""processors"": """",
                    ""groups"": """",
                    ""action"": ""FireAction"",
                    ""isComposite"": false,
                    ""isPartOfComposite"": false
                },
                {
                    ""name"": """",
                    ""id"": ""31743faa-f932-47d1-8ab0-4fb5d437f98b"",
                    ""path"": ""<Keyboard>/e"",
                    ""interactions"": """",
                    ""processors"": """",
                    ""groups"": """",
                    ""action"": ""SkillAction"",
                    ""isComposite"": false,
                    ""isPartOfComposite"": false
                },
                {
                    ""name"": ""1D Axis"",
                    ""id"": ""c94d57a3-675a-4e86-a90c-ed0da0977c09"",
                    ""path"": ""1DAxis"",
                    ""interactions"": ""Press(behavior=2)"",
                    ""processors"": """",
                    ""groups"": """",
                    ""action"": ""Horizontal"",
                    ""isComposite"": true,
                    ""isPartOfComposite"": false
                },
                {
                    ""name"": ""negative"",
                    ""id"": ""89596dc3-dce4-4e21-94dd-bbaf072fc604"",
                    ""path"": ""<Keyboard>/a"",
                    ""interactions"": """",
                    ""processors"": """",
                    ""groups"": """",
                    ""action"": ""Horizontal"",
                    ""isComposite"": false,
                    ""isPartOfComposite"": true
                },
                {
                    ""name"": ""positive"",
                    ""id"": ""ca8383a4-13c5-478e-87dd-bb95c680d7a1"",
                    ""path"": ""<Keyboard>/d"",
                    ""interactions"": """",
                    ""processors"": """",
                    ""groups"": """",
                    ""action"": ""Horizontal"",
                    ""isComposite"": false,
                    ""isPartOfComposite"": true
                },
                {
                    ""name"": """",
                    ""id"": ""fa7d9de7-c891-4967-9ff7-890b449019bb"",
                    ""path"": ""<Mouse>/position"",
                    ""interactions"": """",
                    ""processors"": """",
                    ""groups"": """",
                    ""action"": ""MousePos"",
                    ""isComposite"": false,
                    ""isPartOfComposite"": false
                }
            ]
        }
    ],
    ""controlSchemes"": []
}");
        // Player
        m_Player             = asset.FindActionMap("Player", true);
        m_Player_FireAction  = m_Player.FindAction("FireAction", true);
        m_Player_SkillAction = m_Player.FindAction("SkillAction", true);
        m_Player_Horizontal  = m_Player.FindAction("Horizontal", true);
        m_Player_MousePos    = m_Player.FindAction("MousePos", true);
    }
示例#26
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));
    }
示例#27
0
 public ActionMapTreeItem(InputActionMap actionMap, SerializedProperty actionMapProperty, int index) : base(actionMapProperty, index)
 {
     m_ActionMap = actionMap;
     displayName = elementProperty.FindPropertyRelative("m_Name").stringValue;
     id          = displayName.GetHashCode();
 }
示例#28
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();
    }
示例#29
0
        public unsafe void AddActionMap(InputActionMap map)
        {
            Debug.Assert(map != null, "Received null map");

            var actionsInThisMap      = map.m_Actions;
            var bindingsInThisMap     = map.m_Bindings;
            var bindingCountInThisMap = bindingsInThisMap?.Length ?? 0;
            var actionCountInThisMap  = actionsInThisMap?.Length ?? 0;
            var mapIndex = totalMapCount;

            // Keep track of indices for this map.
            var actionStartIndex      = totalActionCount;
            var bindingStartIndex     = totalBindingCount;
            var controlStartIndex     = totalControlCount;
            var interactionStartIndex = totalInteractionCount;
            var processorStartIndex   = totalProcessorCount;
            var compositeStartIndex   = totalCompositeCount;

            // Allocate an initial block of memory. We probably will have to re-allocate once
            // at the end to accommodate interactions and controls added from the map.
            var newMemory = new InputActionState.UnmanagedMemory();

            newMemory.Allocate(
                mapCount: totalMapCount + 1,
                actionCount: totalActionCount + actionCountInThisMap,
                bindingCount: totalBindingCount + bindingCountInThisMap,
                // We reallocate for the following once we know the final count.
                interactionCount: totalInteractionCount,
                compositeCount: totalCompositeCount,
                controlCount: totalControlCount);
            if (memory.isAllocated)
            {
                newMemory.CopyDataFrom(memory);
            }

            ////TODO: make sure composite objects get all the bindings they need
            ////TODO: handle case where we have bindings resolving to the same control
            ////      (not so clear cut what to do there; each binding may have a different interaction setup, for example)
            var         currentCompositeBindingIndex     = InputActionState.kInvalidIndex;
            var         currentCompositeIndex            = InputActionState.kInvalidIndex;
            var         currentCompositePartCount        = 0;
            var         currentCompositeActionIndexInMap = InputActionState.kInvalidIndex;
            InputAction currentCompositeAction           = null;
            var         bindingMaskOnThisMap             = map.m_BindingMask;
            var         devicesForThisMap = map.devices;

            // Can't use `using` as we need to use it with `ref`.
            var resolvedControls = new InputControlList <InputControl>(Allocator.Temp);

            // We gather all controls in temporary memory and then move them over into newMemory once
            // we're done resolving.
            try
            {
                for (var n = 0; n < bindingCountInThisMap; ++n)
                {
                    var     bindingStatesPtr  = newMemory.bindingStates;
                    ref var unresolvedBinding = ref bindingsInThisMap[n];
                    var     bindingIndex      = bindingStartIndex + n;
                    var     isComposite       = unresolvedBinding.isComposite;
                    var     isPartOfComposite = !isComposite && unresolvedBinding.isPartOfComposite;
                    var     bindingState      = &bindingStatesPtr[bindingIndex];

                    try
                    {
                        ////TODO: if it's a composite, check if any of the children matches our binding masks (if any) and skip composite if none do

                        var firstControlIndex     = 0; // numControls dictates whether this is a valid index or not.
                        var firstInteractionIndex = InputActionState.kInvalidIndex;
                        var firstProcessorIndex   = InputActionState.kInvalidIndex;
                        var actionIndexForBinding = InputActionState.kInvalidIndex;
                        var partIndex             = InputActionState.kInvalidIndex;

                        var numControls     = 0;
                        var numInteractions = 0;
                        var numProcessors   = 0;

                        // Make sure that if it's part of a composite, we are actually part of a composite.
                        if (isPartOfComposite && currentCompositeBindingIndex == InputActionState.kInvalidIndex)
                        {
                            throw new InvalidOperationException(
                                      $"Binding '{unresolvedBinding}' is marked as being part of a composite but the preceding binding is not a composite");
                        }

                        // Try to find action.
                        //
                        // NOTE: We ignore actions on bindings that are part of composites. We only allow
                        //       actions to be triggered from the composite itself.
                        var         actionIndexInMap = InputActionState.kInvalidIndex;
                        var         actionName       = unresolvedBinding.action;
                        InputAction action           = null;
                        if (!isPartOfComposite)
                        {
                            if (!string.IsNullOrEmpty(actionName))
                            {
                                ////REVIEW: should we fail here if we don't manage to find the action
                                actionIndexInMap = map.FindActionIndex(actionName);
                            }
                            else if (map.m_SingletonAction != null)
                            {
                                // Special-case for singleton actions that don't have names.
                                actionIndexInMap = 0;
                            }

                            if (actionIndexInMap != InputActionState.kInvalidIndex)
                            {
                                action = actionsInThisMap[actionIndexInMap];
                            }
                        }
                        else
                        {
                            actionIndexInMap = currentCompositeActionIndexInMap;
                            action           = currentCompositeAction;
                        }

                        // If it's a composite, start a chain.
                        if (isComposite)
                        {
                            currentCompositeBindingIndex     = bindingIndex;
                            currentCompositeAction           = action;
                            currentCompositeActionIndexInMap = actionIndexInMap;
                        }

                        // Determine if the binding is disabled.
                        // Disabled if path is empty.
                        var path = unresolvedBinding.effectivePath;
                        var bindingIsDisabled = string.IsNullOrEmpty(path)

                                                // Also, if we can't find the action to trigger for the binding, we just go and disable
                                                // the binding.
                                                || action == null

                                                // Also, disabled if binding doesn't match with our binding mask (might be empty).
                                                || (!isComposite && bindingMask != null &&
                                                    !bindingMask.Value.Matches(ref unresolvedBinding,
                                                                               InputBinding.MatchOptions.EmptyGroupMatchesAny))

                                                // Also, disabled if binding doesn't match the binding mask on the map (might be empty).
                                                || (!isComposite && bindingMaskOnThisMap != null &&
                                                    !bindingMaskOnThisMap.Value.Matches(ref unresolvedBinding,
                                                                                        InputBinding.MatchOptions.EmptyGroupMatchesAny))

                                                // Finally, also disabled if binding doesn't match the binding mask on the action (might be empty).
                                                || (!isComposite && action?.m_BindingMask != null &&
                                                    !action.m_BindingMask.Value.Matches(ref unresolvedBinding,
                                                                                        InputBinding.MatchOptions.EmptyGroupMatchesAny));


                        // If the binding isn't disabled, resolve its controls, processors, and interactions.
                        if (!bindingIsDisabled)
                        {
                            // Instantiate processors.
                            var processorString = unresolvedBinding.effectiveProcessors;
                            if (!string.IsNullOrEmpty(processorString))
                            {
                                // Add processors from binding.
                                firstProcessorIndex = ResolveProcessors(processorString);
                                if (firstProcessorIndex != InputActionState.kInvalidIndex)
                                {
                                    numProcessors = totalProcessorCount - firstProcessorIndex;
                                }
                            }
                            if (!string.IsNullOrEmpty(action.m_Processors))
                            {
                                // Add processors from action.
                                var index = ResolveProcessors(action.m_Processors);
                                if (index != InputActionState.kInvalidIndex)
                                {
                                    if (firstProcessorIndex == InputActionState.kInvalidIndex)
                                    {
                                        firstProcessorIndex = index;
                                    }
                                    numProcessors += totalProcessorCount - index;
                                }
                            }

                            // Instantiate interactions.
                            var interactionString = unresolvedBinding.effectiveInteractions;
                            if (!string.IsNullOrEmpty(interactionString))
                            {
                                // Add interactions from binding.
                                firstInteractionIndex = ResolveInteractions(interactionString);
                                if (firstInteractionIndex != InputActionState.kInvalidIndex)
                                {
                                    numInteractions = totalInteractionCount - firstInteractionIndex;
                                }
                            }
                            if (!string.IsNullOrEmpty(action.m_Interactions))
                            {
                                // Add interactions from action.
                                var index = ResolveInteractions(action.m_Interactions);
                                if (index != InputActionState.kInvalidIndex)
                                {
                                    if (firstInteractionIndex == InputActionState.kInvalidIndex)
                                    {
                                        firstInteractionIndex = index;
                                    }
                                    numInteractions += totalInteractionCount - index;
                                }
                            }

                            // If it's the start of a composite chain, create the composite. Otherwise, go and
                            // resolve controls for the binding.
                            if (isComposite)
                            {
                                // The composite binding entry itself does not resolve to any controls.
                                // It creates a composite binding object which is then populated from
                                // subsequent bindings.

                                // Instantiate. For composites, the path is the name of the composite.
                                var composite = InstantiateBindingComposite(unresolvedBinding.path);
                                currentCompositeIndex =
                                    ArrayHelpers.AppendWithCapacity(ref composites, ref totalCompositeCount, composite);

                                // Record where the controls for parts of the composite start.
                                firstControlIndex = memory.controlCount + resolvedControls.Count;
                            }
                            else
                            {
                                // If we've reached the end of a composite chain, finish
                                // off the current composite.
                                if (!isPartOfComposite && currentCompositeBindingIndex != InputActionState.kInvalidIndex)
                                {
                                    currentCompositePartCount        = 0;
                                    currentCompositeBindingIndex     = InputActionState.kInvalidIndex;
                                    currentCompositeIndex            = InputActionState.kInvalidIndex;
                                    currentCompositeAction           = null;
                                    currentCompositeActionIndexInMap = InputActionState.kInvalidIndex;
                                }

                                // Look up controls.
                                //
                                // NOTE: We continuously add controls here to `resolvedControls`. Once we've completed our
                                //       pass over the bindings in the map, `resolvedControls` will have all the controls for
                                //       the current map.
                                firstControlIndex = memory.controlCount + resolvedControls.Count;
                                if (devicesForThisMap != null)
                                {
                                    // Search in devices for only this map.
                                    var list = devicesForThisMap.Value;
                                    for (var i = 0; i < list.Count; ++i)
                                    {
                                        var device = list[i];
                                        if (!device.added)
                                        {
                                            continue; // Skip devices that have been removed.
                                        }
                                        numControls += InputControlPath.TryFindControls(device, path, 0, ref resolvedControls);
                                    }
                                }
                                else
                                {
                                    // Search globally.
                                    numControls = InputSystem.FindControls(path, ref resolvedControls);
                                }
                            }
                        }

                        // If the binding is part of a composite, pass the resolved controls
                        // on to the composite.
                        if (isPartOfComposite && currentCompositeBindingIndex != InputActionState.kInvalidIndex && numControls > 0)
                        {
                            // Make sure the binding is named. The name determines what in the composite
                            // to bind to.
                            if (string.IsNullOrEmpty(unresolvedBinding.name))
                            {
                                throw new InvalidOperationException(
                                          $"Binding '{unresolvedBinding}' that is part of composite '{composites[currentCompositeIndex]}' is missing a name");
                            }

                            // Give a part index for the
                            partIndex = AssignCompositePartIndex(composites[currentCompositeIndex], unresolvedBinding.name,
                                                                 ref currentCompositePartCount);

                            // Keep track of total number of controls bound in the composite.
                            bindingStatesPtr[currentCompositeBindingIndex].controlCount += numControls;

                            // Force action index on part binding to be same as that of composite.
                            actionIndexForBinding = bindingStatesPtr[currentCompositeBindingIndex].actionIndex;
                        }
                        else if (actionIndexInMap != InputActionState.kInvalidIndex)
                        {
                            actionIndexForBinding = actionStartIndex + actionIndexInMap;
                        }

                        // Store resolved binding.
                        *bindingState = new InputActionState.BindingState
                        {
                            controlStartIndex = firstControlIndex,
                            // For composites, this will be adjusted as we add each part.
                            controlCount                     = numControls,
                            interactionStartIndex            = firstInteractionIndex,
                            interactionCount                 = numInteractions,
                            processorStartIndex              = firstProcessorIndex,
                            processorCount                   = numProcessors,
                            isComposite                      = isComposite,
                            isPartOfComposite                = unresolvedBinding.isPartOfComposite,
                            partIndex                        = partIndex,
                            actionIndex                      = actionIndexForBinding,
                            compositeOrCompositeBindingIndex = isComposite ? currentCompositeIndex : currentCompositeBindingIndex,
                            mapIndex = totalMapCount,
                            wantsInitialStateCheck = action?.wantsInitialStateCheck ?? false
                        };
                    }
                    catch (Exception exception)
                    {
                        Debug.LogError(
                            $"{exception.GetType().Name} while resolving binding '{unresolvedBinding}' in action map '{map}'");
                        Debug.LogException(exception);

                        // Don't swallow exceptions that indicate something is wrong in the code rather than
                        // in the data.
                        if (exception.IsExceptionIndicatingBugInCode())
                        {
                            throw;
                        }
                    }
                }

                // Re-allocate memory to accommodate controls and interaction states. The count for those
                // we only know once we've completed all resolution.
                var controlCountInThisMap = resolvedControls.Count;
                var newTotalControlCount  = memory.controlCount + controlCountInThisMap;
                if (newMemory.interactionCount != totalInteractionCount ||
                    newMemory.compositeCount != totalCompositeCount ||
                    newMemory.controlCount != newTotalControlCount)
                {
                    var finalMemory = new InputActionState.UnmanagedMemory();

                    finalMemory.Allocate(
                        mapCount: newMemory.mapCount,
                        actionCount: newMemory.actionCount,
                        bindingCount: newMemory.bindingCount,
                        controlCount: newTotalControlCount,
                        interactionCount: totalInteractionCount,
                        compositeCount: totalCompositeCount);

                    finalMemory.CopyDataFrom(newMemory);

                    newMemory.Dispose();
                    newMemory = finalMemory;
                }

                // Add controls to array.
                var controlCountInArray = memory.controlCount;
                ArrayHelpers.AppendListWithCapacity(ref controls, ref controlCountInArray, resolvedControls);
                Debug.Assert(controlCountInArray == newTotalControlCount,
                             "Control array should have combined count of old and new controls");

                // Set up control to binding index mapping.
                for (var i = 0; i < bindingCountInThisMap; ++i)
                {
                    var bindingStatesPtr = newMemory.bindingStates;
                    var bindingState     = &bindingStatesPtr[bindingStartIndex + i];
                    var numControls      = bindingState->controlCount;
                    var startIndex       = bindingState->controlStartIndex;
                    for (var n = 0; n < numControls; ++n)
                    {
                        newMemory.controlIndexToBindingIndex[startIndex + n] = bindingStartIndex + i;
                    }
                }

                // Initialize initial interaction states.
                for (var i = memory.interactionCount; i < newMemory.interactionCount; ++i)
                {
                    newMemory.interactionStates[i].phase = InputActionPhase.Waiting;
                }

                // Initialize action data.
                var runningIndexInBindingIndices = memory.bindingCount;
                for (var i = 0; i < actionCountInThisMap; ++i)
                {
                    var action      = actionsInThisMap[i];
                    var actionIndex = actionStartIndex + i;

                    // Correlate action with its trigger state.
                    action.m_ActionIndexInState = actionIndex;

                    // Collect bindings for action.
                    var bindingStartIndexForAction      = runningIndexInBindingIndices;
                    var bindingCountForAction           = 0;
                    var numPossibleConcurrentActuations = 0;

                    for (var n = 0; n < bindingCountInThisMap; ++n)
                    {
                        var bindingIndex = bindingStartIndex + n;
                        var bindingState = &newMemory.bindingStates[bindingIndex];
                        if (bindingState->actionIndex != actionIndex)
                        {
                            continue;
                        }
                        if (bindingState->isPartOfComposite)
                        {
                            continue;
                        }

                        Debug.Assert(bindingIndex <= ushort.MaxValue, "Binding index exceeds limit");
                        newMemory.actionBindingIndices[runningIndexInBindingIndices] = (ushort)bindingIndex;
                        ++runningIndexInBindingIndices;
                        ++bindingCountForAction;

                        // Keep track of how many concurrent actuations we may be seeing on the action so that
                        // we know whether we need to enable conflict resolution or not.
                        if (bindingState->isComposite)
                        {
                            // Composite binding. Actuates as a whole. Check if the composite has successfully
                            // resolved any controls. If so, it adds one possible actuation.
                            if (bindingState->controlCount > 0)
                            {
                                ++numPossibleConcurrentActuations;
                            }
                        }
                        else
                        {
                            // Normal binding. Every successfully resolved control results in one possible actuation.
                            numPossibleConcurrentActuations += bindingState->controlCount;
                        }
                    }
                    Debug.Assert(bindingStartIndexForAction < ushort.MaxValue, "Binding start index on action exceeds limit");
                    Debug.Assert(bindingCountForAction < ushort.MaxValue, "Binding count on action exceeds limit");
                    newMemory.actionBindingIndicesAndCounts[actionIndex * 2]     = (ushort)bindingStartIndexForAction;
                    newMemory.actionBindingIndicesAndCounts[actionIndex * 2 + 1] = (ushort)bindingCountForAction;

                    // See if we may need conflict resolution on this action. Never needed for pass-through actions.
                    // Otherwise, if we have more than one bound control or have several bindings and one of them
                    // is a composite, we enable it.
                    var isPassThroughAction       = action.type == InputActionType.PassThrough;
                    var isButtonAction            = action.type == InputActionType.Button;
                    var mayNeedConflictResolution = !isPassThroughAction && numPossibleConcurrentActuations > 1;

                    // Initialize initial trigger state.
                    newMemory.actionStates[actionIndex] =
                        new InputActionState.TriggerState
                    {
                        phase                     = InputActionPhase.Disabled,
                        mapIndex                  = mapIndex,
                        controlIndex              = InputActionState.kInvalidIndex,
                        interactionIndex          = InputActionState.kInvalidIndex,
                        isPassThrough             = isPassThroughAction,
                        isButton                  = isButtonAction,
                        mayNeedConflictResolution = mayNeedConflictResolution,
                    };
                }

                // Store indices for map.
                newMemory.mapIndices[mapIndex] =
                    new InputActionState.ActionMapIndices
                {
                    actionStartIndex      = actionStartIndex,
                    actionCount           = actionCountInThisMap,
                    controlStartIndex     = controlStartIndex,
                    controlCount          = controlCountInThisMap,
                    bindingStartIndex     = bindingStartIndex,
                    bindingCount          = bindingCountInThisMap,
                    interactionStartIndex = interactionStartIndex,
                    interactionCount      = totalInteractionCount - interactionStartIndex,
                    processorStartIndex   = processorStartIndex,
                    processorCount        = totalProcessorCount - processorStartIndex,
                    compositeStartIndex   = compositeStartIndex,
                    compositeCount        = totalCompositeCount - compositeStartIndex,
                };
                map.m_MapIndexInState = mapIndex;
                var finalActionMapCount = memory.mapCount;
                ArrayHelpers.AppendWithCapacity(ref maps, ref finalActionMapCount, map, capacityIncrement: 4);
                Debug.Assert(finalActionMapCount == newMemory.mapCount,
                             "Final action map count should match old action map count plus one");

                // As a final act, swap the new memory in.
                memory.Dispose();
                memory = newMemory;
            }
示例#30
0
 public bool UsesActionMap(InputActionMap actionMap)
 {
     return(actionMap == mouseActionMap || actionMap == keyboardActionMap);
 }