Ejemplo n.º 1
0
        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.kSeparator).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);
                }
            }
        }
Ejemplo n.º 2
0
        private void OnItemDoubleClicked(ActionTreeItemBase item)
        {
            // Double-clicking on binding or action item opens property popup.
            PropertiesViewBase propertyView = null;

            if (item is BindingTreeItem)
            {
                if (m_ControlPickerState == null)
                {
                    m_ControlPickerState = new InputControlPickerState();
                }
                propertyView = new InputBindingPropertiesView(item.property,
                                                              controlPickerState: m_ControlPickerState,
                                                              expectedControlLayout: item.expectedControlLayout,
                                                              onChange:
                                                              change => m_TreeView.Reload());
            }
            else if (item is ActionTreeItem)
            {
                propertyView = new InputActionPropertiesView(item.property,
                                                             onChange: change => m_TreeView.Reload());
            }

            if (propertyView != null)
            {
                var rect = new Rect(GUIUtility.GUIToScreenPoint(Event.current.mousePosition), Vector2.zero);
                PropertiesViewPopup.Show(rect, propertyView);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="pathProperty"><see cref="string"/> type property that will receive the picked input control path.</param>
        /// <param name="pickerState">Persistent editing state of the </param>
        /// <param name="onModified"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public InputControlPathEditor(SerializedProperty pathProperty, InputControlPickerState pickerState, Action onModified)
        {
            if (pathProperty == null)
            {
                throw new ArgumentNullException(nameof(pathProperty));
            }

            this.pathProperty = pathProperty;

            this.onModified = onModified;
            m_PickerState   = pickerState ?? new InputControlPickerState();
        }
Ejemplo n.º 4
0
        public InputControlPickerPopup(SerializedProperty pathProperty, InputControlPickerState pickerState, Action onModified, Action <Rect, SerializedProperty, Action> drawInteractivePickButton)
        {
            if (pathProperty == null)
            {
                throw new ArgumentNullException("pathProperty");
            }
            m_PathProperty = pathProperty;

            m_DrawInteractivePickButton = drawInteractivePickButton;
            m_OnModified  = onModified;
            m_PickerState = pickerState;
        }
Ejemplo n.º 5
0
        public InputControlPickerDropdown(
            InputControlPickerState state,
            Action <string> onPickCallback,
            InputControlPicker.Mode mode = InputControlPicker.Mode.PickControl)
            : base(state.advancedDropdownState)
        {
            m_Gui = new InputControlPickerGUI(this);

            minimumSize = new Vector2(275, 300);
            maximumSize = new Vector2(0, 300);

            m_OnPickCallback = onPickCallback;
            m_Mode           = mode;
        }
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (m_PickerState == null)
            {
                m_PickerState = new InputControlPickerState();
            }
            if (m_Editor == null)
            {
                m_Editor = new InputControlPathEditor(property, m_PickerState,
                                                      () => property.serializedObject.ApplyModifiedProperties());
                m_Editor.SetExpectedControlLayoutFromAttribute();
            }

            EditorGUI.BeginProperty(position, label, property);
            m_Editor.OnGUI(position);
            EditorGUI.EndProperty();
        }
 public InputBindingPropertiesView(SerializedProperty bindingProperty, Action <FourCC> onChange,
                                   InputControlPickerState controlPickerState, InputActionWindowToolbar toolbar,
                                   bool isCompositeBinding      = false,
                                   string expectedControlLayout = null)
     : base(isCompositeBinding ? "Composite" : "Binding", bindingProperty, onChange, expectedControlLayout)
 {
     m_ControlPickerState = controlPickerState;
     m_BindingProperty    = bindingProperty;
     m_GroupsProperty     = bindingProperty.FindPropertyRelative("m_Groups");
     m_PathProperty       = bindingProperty.FindPropertyRelative("m_Path");
     m_Toolbar            = toolbar;
     if (m_Toolbar != null)
     {
         m_ControlSchemes = toolbar.controlSchemes;
     }
     m_BindingGroups         = m_GroupsProperty.stringValue.Split(InputBinding.kSeparator).ToList();
     m_ExpectedControlLayout = expectedControlLayout;
     m_IsComposite           = isCompositeBinding;
 }
 public InputBindingPropertiesView(SerializedProperty bindingProperty, Action <Change> onChange,
                                   InputControlPickerState controlPickerState, InputActionWindowToolbar toolbar,
                                   string expectedControlLayout = null)
 {
     m_ControlPickerState   = controlPickerState;
     m_BindingProperty      = bindingProperty;
     m_OnChange             = onChange;
     m_InteractionsProperty = bindingProperty.FindPropertyRelative("m_Interactions");
     m_ProcessorsProperty   = bindingProperty.FindPropertyRelative("m_Processors");
     m_GroupsProperty       = bindingProperty.FindPropertyRelative("m_Groups");
     m_PathProperty         = bindingProperty.FindPropertyRelative("m_Path");
     m_InteractionsList     = new InteractionsReorderableReorderableList(m_InteractionsProperty, OnInteractionsModified);
     m_ProcessorsList       = new ProcessorsReorderableReorderableList(m_ProcessorsProperty, OnProcessorsModified);
     m_Toolbar = toolbar;
     if (m_Toolbar != null)
     {
         m_ControlSchemes = toolbar.controlSchemes;
     }
     m_BindingGroups         = m_GroupsProperty.stringValue.Split(InputBinding.kSeparator).ToList();
     m_ExpectedControlLayout = expectedControlLayout;
 }
        private void InitializeTrees()
        {
            m_ActionMapsTree = ActionMapsTree.CreateFromSerializedObject(ApplyAndReload, m_ActionAssetManager.serializedObject, ref m_ActionMapsTreeState);
            m_ActionMapsTree.OnSelectionChanged = OnActionMapSelection;
            m_ActionMapsTree.OnContextClick     = m_ContextMenu.OnActionMapContextClick;

            m_ActionsTree = ActionsTree.CreateFromSerializedObject(ApplyAndReload, ref m_ActionsTreeState);
            m_ActionsTree.OnSelectionChanged           = OnActionSelection;
            m_ActionsTree.OnContextClick               = m_ContextMenu.OnActionsContextClick;
            m_ActionsTree.OnRowGUI                     = OnActionRowGUI;
            m_InputActionWindowToolbar.OnSearchChanged = m_ActionsTree.SetNameFilter;
            m_InputActionWindowToolbar.OnSchemeChanged = a =>
            {
                if (a == null)
                {
                    m_ActionsTree.SetSchemeBindingGroupFilter(null);
                    return;
                }
                var group = m_ActionAssetManager.m_AssetObjectForEditing.GetControlScheme(a).bindingGroup;
                m_ActionsTree.SetSchemeBindingGroupFilter(group);
            };
            m_InputActionWindowToolbar.OnDeviceChanged = m_ActionsTree.SetDeviceFilter;

            m_ActionsTree.SetNameFilter(m_InputActionWindowToolbar.nameFilter);
            if (m_InputActionWindowToolbar.selectedControlSchemeName != null)
            {
                var group = m_ActionAssetManager.m_AssetObjectForEditing.GetControlScheme(m_InputActionWindowToolbar.selectedControlSchemeName).bindingGroup;
                m_ActionsTree.SetSchemeBindingGroupFilter(group);
            }
            m_ActionsTree.SetDeviceFilter(m_InputActionWindowToolbar.selectedDevice);

            m_CopyPasteUtility = new InputActionCopyPasteUtility(ApplyAndReload, m_ActionMapsTree, m_ActionsTree, m_ActionAssetManager.serializedObject);
            if (m_PickerTreeViewState == null)
            {
                m_PickerTreeViewState = new InputControlPickerState();
            }
        }
        private void LoadPropertiesForSelection()
        {
            m_BindingPropertyView = null;
            m_ActionPropertyView  = null;

            ////TODO: preserve interaction/processor selection when reloading

            // Nothing else to do if we don't have a selection in the middle pane or if
            // multiple items are selected (we don't currently have the ability to multi-edit).
            if (!m_ActionsTree.HasSelection() || m_ActionsTree.GetSelection().Count != 1)
            {
                return;
            }

            var item = m_ActionsTree.GetSelectedItems().FirstOrDefault();

            if (item is BindingTreeItem)
            {
                // Grab the action for the binding and see if we have an expected control layout
                // set on it. Pass that on to the control picking machinery.
                var isCompositePartBinding = item is PartOfCompositeBindingTreeItem;
                var isCompositeBinding     = item is CompositeBindingTreeItem;
                var actionItem             = (isCompositePartBinding ? item.parent.parent : item.parent) as ActionTreeItem;
                Debug.Assert(actionItem != null);

                if (m_ControlPickerViewState == null)
                {
                    m_ControlPickerViewState = new InputControlPickerState();
                }

                // The toolbar may constrain the set of devices we're currently interested in by either
                // having one specific device selected from the current scheme or having at least a control
                // scheme selected.
                var controlPathsToMatch = (IEnumerable <string>)null;
                if (m_Toolbar.selectedDeviceRequirement != null)
                {
                    // Single device selected from set of devices in control scheme.
                    controlPathsToMatch = new[] { m_Toolbar.selectedDeviceRequirement.Value.controlPath };
                }
                else if (m_Toolbar.selectedControlScheme != null)
                {
                    // Constrain to devices from current control scheme.
                    controlPathsToMatch =
                        m_Toolbar.selectedControlScheme.Value.deviceRequirements.Select(x => x.controlPath);
                }
                else
                {
                    // If there's no device filter coming from a control scheme, filter by supported
                    // devices as given by settings.
                    controlPathsToMatch = InputSystem.settings.supportedDevices;
                }

                // Show properties for binding.
                m_BindingPropertyView =
                    new InputBindingPropertiesView(
                        item.property,
                        change =>
                {
                    if (change == InputBindingPropertiesView.k_PathChanged ||
                        change == InputBindingPropertiesView.k_CompositePartAssignmentChanged ||
                        change == InputBindingPropertiesView.k_CompositeTypeChanged)
                    {
                        ApplyAndReloadTrees();
                    }
                    else
                    {
                        // Simple property change that doesn't affect the rest of the UI.
                        Apply();
                    }
                },
                        m_ControlPickerViewState,
                        expectedControlLayout: item.expectedControlLayout,
                        controlSchemes: m_Toolbar.controlSchemes,
                        controlPathsToMatch: controlPathsToMatch);
            }
            else if (item is ActionTreeItem actionItem)
            {
                // Show properties for action.
                m_ActionPropertyView =
                    new InputActionPropertiesView(
                        actionItem.property,
                        // Apply without reload is enough here as modifying the properties of an action will
                        // never change the structure of the data.
                        change => Apply());
            }
        }
Ejemplo n.º 11
0
 public InputControlPicker(Mode mode, Action <string> onPick, InputControlPickerState state)
 {
     m_State    = state ?? new InputControlPickerState();
     m_Dropdown = new InputControlPickerDropdown(state, onPick, mode: mode);
 }
        private void ShowInputControlPicker(Rect rect, SerializedProperty pathProperty, InputControlPickerState pickerState,
                                            Action onPickCallback)
        {
            if (m_InputControlPickerDropdown == null)
            {
                m_InputControlPickerDropdown = new InputControlPickerDropdown(pickerState.state,
                                                                              path =>
                {
                    pathProperty.stringValue = path;
                    onPickCallback();
                });
            }

            var haveDeviceFilterFromControlScheme = false;

            if (m_Toolbar != null)
            {
                if (m_Toolbar.selectedDevice != null)
                {
                    // Single device selected from set of devices in control scheme.
                    m_InputControlPickerDropdown.SetDeviceFilter(new[] { m_Toolbar.selectedDevice });
                    haveDeviceFilterFromControlScheme = true;
                }
                else
                {
                    var allDevices = m_Toolbar.allDevices;
                    if (allDevices.Length > 0)
                    {
                        // Filter by all devices in current control scheme.
                        m_InputControlPickerDropdown.SetDeviceFilter(allDevices);
                        haveDeviceFilterFromControlScheme = true;
                    }
                }
                if (m_ExpectedControlLayout != null)
                {
                    m_InputControlPickerDropdown.SetExpectedControlLayoutFilter(m_ExpectedControlLayout);
                }
            }

            // If there's no device filter coming from a control scheme, filter by supported
            // devices as given by settings .
            if (!haveDeviceFilterFromControlScheme)
            {
                m_InputControlPickerDropdown.SetDeviceFilter(InputSystem.settings.supportedDevices.ToArray());
            }

            m_InputControlPickerDropdown.Show(rect);
        }
        ////TODO: interactive picker; if more than one control makes it through the filters, present list of
        ////      candidates for user to choose from

        ////REVIEW: refactor this out of here; this should be a public API that allows anyone to have an inspector field to select a control binding
        internal void DrawBindingGUI(SerializedProperty pathProperty, ref bool manualPathEditMode, InputControlPickerState pickerState, Action onModified)
        {
            EditorGUILayout.BeginHorizontal();

            var lineRect  = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight);
            var labelRect = lineRect;

            labelRect.width = 60;
            EditorGUI.LabelField(labelRect, s_PathLabel);
            lineRect.x     += 65;
            lineRect.width -= 65;

            var bindingTextRect           = lineRect;
            var editButtonRect            = lineRect;
            var interactivePickButtonRect = lineRect;

            bindingTextRect.width           -= 42;
            editButtonRect.x                += bindingTextRect.width + 21;
            editButtonRect.width             = 21;
            editButtonRect.height            = 15;
            interactivePickButtonRect.x     += bindingTextRect.width;
            interactivePickButtonRect.width  = 21;
            interactivePickButtonRect.height = 15;

            var path = pathProperty.stringValue;
            ////TODO: this should be cached; generates needless GC churn
            var displayName = InputControlPath.ToHumanReadableString(path);

            if (manualPathEditMode || (!string.IsNullOrEmpty(path) && string.IsNullOrEmpty(displayName)))
            {
                EditorGUI.BeginChangeCheck();
                path = EditorGUI.DelayedTextField(bindingTextRect, path);
                if (EditorGUI.EndChangeCheck())
                {
                    pathProperty.stringValue = path;
                    pathProperty.serializedObject.ApplyModifiedProperties();
                    onModified();
                }
                DrawInteractivePickButton(interactivePickButtonRect, pathProperty, onModified);
                if (GUI.Button(editButtonRect, "˅"))
                {
                    bindingTextRect.x += editButtonRect.width;
                    ShowInputControlPicker(bindingTextRect, pathProperty, pickerState, onModified);
                }
            }
            else
            {
                // Dropdown that shows binding text and allows opening control picker.
                if (EditorGUI.DropdownButton(bindingTextRect, new GUIContent(displayName), FocusType.Keyboard))
                {
                    ////TODO: pass expectedControlLayout filter on to control picker
                    ////TODO: for bindings that are part of composites, use the layout information from the [InputControl] attribute on the field
                    ShowInputControlPicker(bindingTextRect, pathProperty, pickerState, onModified);
                }

                // Button to bind interactively.
                DrawInteractivePickButton(interactivePickButtonRect, pathProperty, onModified);

                // Button that switches binding into text edit mode.
                if (GUI.Button(editButtonRect, "...", EditorStyles.miniButton))
                {
                    manualPathEditMode = true;
                }
            }

            EditorGUILayout.EndHorizontal();
        }