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); } } }
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(); }
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); }
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(); }
private void OnControlSchemeRenamed(string oldBindingGroup, string newBindingGroup) { InputActionSerializationHelpers.ReplaceBindingGroup(m_ActionAssetManager.serializedObject, oldBindingGroup, newBindingGroup); ApplyAndReloadTrees(); }
public override void Rename(string newName) { InputActionSerializationHelpers.RenameComposite(property, newName); }
public override void DeleteData() { var bindingsArrayProperty = property.GetParentProperty(); InputActionSerializationHelpers.DeleteBinding(bindingsArrayProperty, guid); }
public override void DeleteData() { InputActionSerializationHelpers.DeleteActionAndBindings(actionMapProperty, guid); }
public override void Rename(string newName) { InputActionSerializationHelpers.RenameAction(property, actionMapProperty, newName); }