public static BindingSyntax ChangeBinding(this InputAction action, int index)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var indexOnMap = action.BindingIndexOnActionToBindingIndexOnMap(index);

            return(new BindingSyntax(action.GetOrCreateActionMap(), action, indexOnMap));
        }
        public static void ApplyBindingOverride(this InputAction action, int bindingIndex, InputBinding bindingOverride)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var indexOnMap = action.BindingIndexOnActionToBindingIndexOnMap(bindingIndex);

            bindingOverride.action = action.name;
            ApplyBindingOverride(action.GetOrCreateActionMap(), indexOnMap, bindingOverride);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="action"></param>
        /// <param name="bindingOverride"></param>
        /// <remarks>
        /// Binding overrides are non-destructive. They do not change the bindings set up for an action
        /// but rather apply non-destructive modifications that change the paths of existing bindings.
        /// However, this also means that for overrides to work, there have to be existing bindings that
        /// can be modified.
        /// </remarks>
        public static void ApplyBindingOverride(this InputAction action, InputBinding bindingOverride)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            bindingOverride.action = action.name;
            var actionMap = action.GetOrCreateActionMap();

            ApplyBindingOverride(actionMap, bindingOverride);
        }
        /// <summary>
        /// Add a new binding to the action.
        /// </summary>
        /// <param name="action">An action to add the binding to.</param>
        /// <param name="binding">Binding to add to the action or default. Binding can be further configured via
        /// the struct returned by the method.</param>
        /// <returns>
        /// Returns a fluent-style syntax structure that allows performing additional modifications
        /// based on the new binding.
        /// </returns>
        /// <remarks>
        /// This works both with actions that are part of an action set as well as with actions that aren't.
        ///
        /// Note that actions must be disabled while altering their binding sets. Also, if the action belongs
        /// to a set, all actions in the set must be disabled.
        ///
        /// <example>
        /// <code>
        /// fireAction.AddBinding()
        ///     .WithPath("&lt;Gamepad&gt;/buttonSouth")
        ///     .WithGroup("Gamepad");
        /// </code>
        /// </example>
        /// </remarks>
        public static BindingSyntax AddBinding(this InputAction action, InputBinding binding = default)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            ////REVIEW: should this reference actions by ID?
            Debug.Assert(action.m_Name != null || action.isSingletonAction);
            binding.action = action.name;

            var actionMap    = action.GetOrCreateActionMap();
            var bindingIndex = AddBindingInternal(actionMap, binding);

            return(new BindingSyntax(actionMap, action, bindingIndex));
        }
        public static BindingSyntax ChangeBinding(this InputAction action, InputBinding match)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var actionMap    = action.GetOrCreateActionMap();
            var bindingIndex = actionMap.FindBinding(match);

            if (bindingIndex == -1)
            {
                throw new ArgumentException($"Cannot find binding matching '{match}' in '{action}'", nameof(match));
            }

            return(new BindingSyntax(actionMap, action, bindingIndex));
        }
        ////TODO: update binding mask if necessary
        /// <summary>
        /// Rename an existing action.
        /// </summary>
        /// <param name="action">Action to assign a new name to. Can be singleton action or action that
        /// is part of a map.</param>
        /// <param name="newName">New name to assign to action. Cannot be empty.</param>
        /// <exception cref="ArgumentNullException"><paramref name="action"/> is null or <paramref name="newName"/> is
        /// null or empty.</exception>
        /// <exception cref="InvalidOperationException"><see cref="InputAction.actionMap"/> of <paramref name="action"/>
        /// already contains an action called <paramref name="newName"/>.</exception>
        /// <remarks>
        /// Renaming an action will also update the bindings that refer to the action.
        /// </remarks>
        public static void Rename(this InputAction action, string newName)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }
            if (string.IsNullOrEmpty(newName))
            {
                throw new ArgumentNullException(nameof(newName));
            }

            if (action.name == newName)
            {
                return;
            }

            // Make sure name isn't already taken in map.
            var actionMap = action.actionMap;

            if (actionMap?.FindAction(newName) != null)
            {
                throw new InvalidOperationException(
                          $"Cannot rename '{action}' to '{newName}' in map '{actionMap}' as the map already contains an action with that name");
            }

            var oldName = action.m_Name;

            action.m_Name = newName;

            // Update bindings.
            var bindings     = action.GetOrCreateActionMap().m_Bindings;
            var bindingCount = bindings.LengthSafe();

            for (var i = 0; i < bindingCount; ++i)
            {
                if (string.Compare(bindings[i].action, oldName, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    bindings[i].action = newName;
                }
            }
        }
        public static CompositeSyntax AddCompositeBinding(this InputAction action, string composite, string interactions = null)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }
            if (string.IsNullOrEmpty(composite))
            {
                throw new ArgumentException("Composite name cannot be null or empty", nameof(composite));
            }

            var actionMap = action.GetOrCreateActionMap();

            ////REVIEW: use 'name' instead of 'path' field here?
            var binding = new InputBinding {
                path = composite, interactions = interactions, isComposite = true, action = action.name
            };
            var bindingIndex = AddBindingInternal(actionMap, binding);

            return(new CompositeSyntax(actionMap, action, bindingIndex));
        }
        /// <summary>
        /// Add a new binding to the action.
        /// </summary>
        /// <param name="action">A disabled action to add the binding to.</param>
        /// <param name="binding"></param>
        /// <returns>
        /// Returns a fluent-style syntax structure that allows performing additional modifications
        /// based on the new binding.
        /// </returns>
        /// <remarks>
        /// This works both with actions that are part of an action set as well as with actions that aren't.
        ///
        /// Note that actions must be disabled while altering their binding sets. Also, if the action belongs
        /// to a set, all actions in the set must be disabled.
        /// </remarks>
        public static BindingSyntax AddBinding(this InputAction action, InputBinding binding)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }
            if (binding.path == null)
            {
                throw new ArgumentException("Binding path cannot be null", nameof(binding));
            }
            action.ThrowIfModifyingBindingsIsNotAllowed();

            ////REVIEW: should this reference actions by ID?
            Debug.Assert(action.m_Name != null || action.isSingletonAction);
            binding.action = action.name;

            var actionMap = action.GetOrCreateActionMap();

            actionMap.ThrowIfModifyingBindingsIsNotAllowed();
            var bindingIndex = AddBindingInternal(actionMap, binding);

            return(new BindingSyntax(actionMap, action, bindingIndex));
        }