Example #1
0
        public override bool GetDropLocation(Type itemType, int?childIndex, ref SerializedProperty array, ref int arrayIndex)
        {
            // Drop bindings into binding array.
            if (typeof(BindingTreeItem).IsAssignableFrom(itemType))
            {
                array = bindingsArrayProperty;

                // Indexing by tree items is relative to each action but indexing in
                // binding array is global for all actions in a map. Adjust index accordingly.
                // NOTE: Bindings for any one action need not be stored contiguously in the binding array
                //       so we can't just add something to the index of the first binding to the action.
                arrayIndex =
                    InputActionSerializationHelpers.ConvertBindingIndexOnActionToBindingIndexInArray(
                        array, name, childIndex ?? -1);

                return(true);
            }

            // Drop other actions next to us.
            if (itemType == typeof(ActionTreeItem))
            {
                array      = arrayProperty;
                arrayIndex = this.arrayIndex + 1;
                return(true);
            }

            return(false);
        }
        public InputBindingPropertiesView(
            SerializedProperty bindingProperty,
            Action <FourCC> onChange = null,
            InputControlPickerState controlPickerState = null,
            string expectedControlLayout = null,
            ReadOnlyArray <InputControlScheme> controlSchemes = new ReadOnlyArray <InputControlScheme>(),
            IEnumerable <string> controlPathsToMatch          = null)
            : base(InputActionSerializationHelpers.IsCompositeBinding(bindingProperty) ? "Composite" : "Binding",
                   bindingProperty, onChange, expectedControlLayout)
        {
            m_BindingProperty       = bindingProperty;
            m_GroupsProperty        = bindingProperty.FindPropertyRelative("m_Groups");
            m_PathProperty          = bindingProperty.FindPropertyRelative("m_Path");
            m_BindingGroups         = m_GroupsProperty.stringValue.Split(InputBinding.Separator).ToList();
            m_ExpectedControlLayout = expectedControlLayout;
            m_ControlSchemes        = controlSchemes;

            var flags = (InputBinding.Flags)bindingProperty.FindPropertyRelative("m_Flags").intValue;

            m_IsPartOfComposite = (flags & InputBinding.Flags.PartOfComposite) != 0;
            m_IsComposite       = (flags & InputBinding.Flags.Composite) != 0;

            // Set up control picker for m_Path. Not needed if the binding is a composite.
            if (!m_IsComposite)
            {
                m_ControlPickerState = controlPickerState ?? new InputControlPickerState();
                m_ControlPathEditor  = new InputControlPathEditor(m_PathProperty, m_ControlPickerState, OnPathChanged);
                m_ControlPathEditor.SetExpectedControlLayout(m_ExpectedControlLayout);
                if (controlPathsToMatch != null)
                {
                    m_ControlPathEditor.SetControlPathsToMatch(controlPathsToMatch);
                }
            }
        }
Example #3
0
        private void OnControlSchemeDeleted(string name, string bindingGroup)
        {
            Debug.Assert(!string.IsNullOrEmpty(name), "Control scheme name should not be empty");
            Debug.Assert(!string.IsNullOrEmpty(bindingGroup), "Binding group should not be empty");

            var asset = m_ActionAssetManager.m_AssetObjectForEditing;

            var bindingMask       = InputBinding.MaskByGroup(bindingGroup);
            var schemeHasBindings = asset.actionMaps.Any(m => m.bindings.Any(b => bindingMask.Matches(ref b)));

            if (!schemeHasBindings)
            {
                return;
            }

            ////FIXME: this does not delete composites that have bindings in only one control scheme
            ////REVIEW: offer to do nothing and leave all bindings as is?
            var deleteBindings =
                EditorUtility.DisplayDialog("Delete Bindings?",
                                            $"Delete bindings for '{name}' as well? If you select 'No', the bindings will only "
                                            + $"be unassigned from the '{name}' control scheme but otherwise left as is. Note that bindings "
                                            + $"that are assigned to '{name}' but also to other control schemes will be left in place either way.",
                                            "Yes", "No");

            InputActionSerializationHelpers.ReplaceBindingGroup(m_ActionAssetManager.serializedObject, bindingGroup, "",
                                                                deleteOrphanedBindings: deleteBindings);

            ApplyAndReloadTrees();
        }
Example #4
0
        public override bool GetDropLocation(Type itemType, int?childIndex, ref SerializedProperty array, ref int arrayIndex)
        {
            // Drop part binding into composite.
            if (itemType == typeof(PartOfCompositeBindingTreeItem))
            {
                array = arrayProperty;

                // Adjust child index by index of composite item itself.
                arrayIndex = childIndex != null
                    ? this.arrayIndex + 1 + childIndex.Value // Dropping at #0 should put as our index plus one.
                    : this.arrayIndex + 1 + InputActionSerializationHelpers.GetCompositePartCount(array, this.arrayIndex);

                return(true);
            }

            // Drop other bindings next to us.
            if (typeof(BindingTreeItem).IsAssignableFrom(itemType))
            {
                array      = arrayProperty;
                arrayIndex = this.arrayIndex + 1 +
                             InputActionSerializationHelpers.GetCompositePartCount(array, this.arrayIndex);
                return(true);
            }

            return(false);
        }
        public override void DeleteData()
        {
            var currentActionItem = actionItem;

            Debug.Assert(currentActionItem != null, "BindingTreeItem should always have a parent action");
            var bindingsArrayProperty = currentActionItem.bindingsArrayProperty;

            InputActionSerializationHelpers.DeleteBinding(bindingsArrayProperty, guid);
        }
Example #6
0
        public override void DeleteData()
        {
            var assetObject = property.serializedObject;

            if (!(assetObject.targetObject is InputActionAsset))
            {
                throw new InvalidOperationException(
                          $"Action map must be part of InputActionAsset but is in {assetObject.targetObject} instead");
            }

            InputActionSerializationHelpers.DeleteActionMap(assetObject, guid);
        }
        private void OnCompositeTypeChanged()
        {
            var nameAndParameters = new NameAndParameters
            {
                name       = m_CompositeTypes[m_SelectedCompositeType],
                parameters = m_CompositeParameters.GetParameters()
            };

            InputActionSerializationHelpers.ChangeCompositeBindingType(m_BindingProperty, nameAndParameters);
            m_PathProperty.serializedObject.ApplyModifiedProperties();

            onChange?.Invoke(k_CompositeTypeChanged);
        }
        private void InitializeCompositePartProperties()
        {
            var currentCompositePart = m_BindingProperty.FindPropertyRelative("m_Name").stringValue;

            ////REVIEW: this makes a lot of assumptions about the serialized data based on the one property we've been given in the ctor
            // Determine the name of the current composite type that the part belongs to.
            var bindingArrayProperty  = m_BindingProperty.GetArrayPropertyFromElement();
            var partBindingIndex      = InputActionSerializationHelpers.GetIndex(bindingArrayProperty, m_BindingProperty);
            var compositeBindingIndex =
                InputActionSerializationHelpers.GetCompositeStartIndex(bindingArrayProperty, partBindingIndex);

            if (compositeBindingIndex == -1)
            {
                return;
            }
            var compositeBindingProperty   = bindingArrayProperty.GetArrayElementAtIndex(compositeBindingIndex);
            var compositePath              = compositeBindingProperty.FindPropertyRelative("m_Path").stringValue;
            var compositeNameAndParameters = NameAndParameters.Parse(compositePath);

            // Initialize option list from all parts available for the composite.
            var optionList            = new List <GUIContent>();
            var nameList              = new List <string>();
            var currentIndex          = 0;
            var selectedPartNameIndex = -1;

            foreach (var partName in InputBindingComposite.GetPartNames(compositeNameAndParameters.name))
            {
                if (partName.Equals(currentCompositePart, StringComparison.InvariantCultureIgnoreCase))
                {
                    selectedPartNameIndex = currentIndex;
                }
                var niceName = ObjectNames.NicifyVariableName(partName);
                optionList.Add(new GUIContent(niceName));
                nameList.Add(partName);
                ++currentIndex;
            }

            // If currently selected part is not in list, add it as an option.
            if (selectedPartNameIndex == -1)
            {
                selectedPartNameIndex = nameList.Count;
                optionList.Add(new GUIContent(ObjectNames.NicifyVariableName(currentCompositePart)));
                nameList.Add(currentCompositePart);
            }

            m_CompositeParts        = nameList.ToArray();
            m_CompositePartOptions  = optionList.ToArray();
            m_SelectedCompositePart = selectedPartNameIndex;
        }
        private void InitializeTrees()
        {
            // We persist tree view states (most importantly, they contain our selection states),
            // so only create those if we don't have any yet.
            if (m_ActionMapsTreeState == null)
            {
                m_ActionMapsTreeState = new TreeViewState();
            }
            if (m_ActionsTreeState == null)
            {
                m_ActionsTreeState = new TreeViewState();
            }

            // Create tree in middle pane showing actions and bindings. We initially
            // leave this tree empty and populate it by selecting an action map in the
            // left pane tree.
            m_ActionsTree = new InputActionTreeView(m_ActionAssetManager.serializedObject, m_ActionsTreeState)
            {
                onSelectionChanged         = OnActionTreeSelectionChanged,
                onSerializedObjectModified = ApplyAndReloadTrees,
                onBindingAdded             = p => InputActionSerializationHelpers.RemoveUnusedBindingGroups(p, m_Toolbar.controlSchemes),
                drawMinusButton            = false,
                title = ("Actions", "A list of InputActions in the InputActionMap selected in the left pane. Also, for each InputAction, the list "
                         + "of bindings that determine the controls that can trigger the action.\n\nThe name of each action must be unique within its InputActionMap."),
            };

            // Create tree in left pane showing action maps.
            m_ActionMapsTree = new InputActionTreeView(m_ActionAssetManager.serializedObject, m_ActionMapsTreeState)
            {
                onBuildTree = () =>
                              InputActionTreeView.BuildWithJustActionMapsFromAsset(m_ActionAssetManager.serializedObject),
                onSelectionChanged         = OnActionMapTreeSelectionChanged,
                onSerializedObjectModified = ApplyAndReloadTrees,
                onHandleAddNewAction       = m_ActionsTree.AddNewAction,
                drawMinusButton            = false,
                title = ("Action Maps", "A list of InputActionMaps in the asset. Each map can be enabled and disabled separately at runtime and holds "
                         + "its own collection of InputActions which are listed in the middle pane (along with their InputBindings).")
            };
            m_ActionMapsTree.Reload();
            m_ActionMapsTree.ExpandAll();

            RebuildActionTree();
            LoadPropertiesForSelection();

            // Sync current search status in toolbar.
            OnToolbarSearchChanged();
        }
Example #10
0
 private void OnControlSchemeRenamed(string oldBindingGroup, string newBindingGroup)
 {
     InputActionSerializationHelpers.ReplaceBindingGroup(m_ActionAssetManager.serializedObject,
                                                         oldBindingGroup, newBindingGroup);
     ApplyAndReloadTrees();
 }
Example #11
0
 public override void Rename(string newName)
 {
     InputActionSerializationHelpers.RenameComposite(property, newName);
 }
Example #12
0
        public override void DeleteData()
        {
            var bindingsArrayProperty = property.GetParentProperty();

            InputActionSerializationHelpers.DeleteBinding(bindingsArrayProperty, guid);
        }
Example #13
0
 public override void DeleteData()
 {
     InputActionSerializationHelpers.DeleteActionAndBindings(actionMapProperty, guid);
 }
Example #14
0
 public override void Rename(string newName)
 {
     InputActionSerializationHelpers.RenameAction(property, actionMapProperty, newName);
 }