public static SerializedProperty AddBindingToBindingArray(SerializedProperty bindingsArrayProperty, int bindingIndex = -1,
                                                                  string actionName        = "", string groups = "", string path = "", string name = "", string interactions = "", string processors = "",
                                                                  InputBinding.Flags flags = InputBinding.Flags.None)
        {
            Debug.Assert(bindingsArrayProperty != null);
            Debug.Assert(bindingsArrayProperty.isArray, "SerializedProperty is not an array of bindings");
            Debug.Assert(bindingIndex == -1 || (bindingIndex >= 0 && bindingIndex <= bindingsArrayProperty.arraySize));

            if (bindingIndex == -1)
            {
                bindingIndex = bindingsArrayProperty.arraySize;
            }

            bindingsArrayProperty.InsertArrayElementAtIndex(bindingIndex);

            var newBindingProperty = bindingsArrayProperty.GetArrayElementAtIndex(bindingIndex);

            newBindingProperty.FindPropertyRelative("m_Path").stringValue         = path;
            newBindingProperty.FindPropertyRelative("m_Groups").stringValue       = groups;
            newBindingProperty.FindPropertyRelative("m_Interactions").stringValue = interactions;
            newBindingProperty.FindPropertyRelative("m_Processors").stringValue   = processors;
            newBindingProperty.FindPropertyRelative("m_Flags").intValue           = (int)flags;
            newBindingProperty.FindPropertyRelative("m_Action").stringValue       = actionName;
            newBindingProperty.FindPropertyRelative("m_Name").stringValue         = name;
            newBindingProperty.FindPropertyRelative("m_Id").stringValue           = Guid.NewGuid().ToString();

            ////FIXME: this likely leaves m_Bindings in the map for singleton actions unsync'd in some cases

            return(newBindingProperty);
        }
示例#2
0
        ////TODO: move this out into a general routine that can take a path and construct a display name
        private GUIContent GetContentForPath(string path, string modifiers, InputBinding.Flags flags)
        {
            if (s_UsageRegex == null)
            {
                s_UsageRegex = new Regex("\\*/{([A-Za-z0-9]+)}");
            }
            if (s_ControlRegex == null)
            {
                s_ControlRegex = new Regex("<([A-Za-z0-9]+)>/([A-Za-z0-9]+(/[A-Za-z0-9]+)*)");
            }

            var text = path;

            ////TODO: make this less GC heavy
            ////TODO: prettify control names (e.g. "rightTrigger" should read "Right Trigger"); have explicit display names?

            ////REVIEW: This stuff here should really be based on general display functionality for controls
            ////        which should be available to game code in just the same way for on-screen display
            ////        purposes

            var usageMatch = s_UsageRegex.Match(path);

            if (usageMatch.Success)
            {
                text = usageMatch.Groups[1].Value;
            }
            else
            {
                var controlMatch = s_ControlRegex.Match(path);
                if (controlMatch.Success)
                {
                    var device  = controlMatch.Groups[1].Value;
                    var control = controlMatch.Groups[2].Value;

                    ////TODO: would be nice to include template name to print something like "Gamepad A Button" instead of "Gamepad A" (or whatever)

                    text = string.Format("{0} {1}", device, control);
                }
            }

            ////REVIEW: would be nice to have icons for these

            // Show modifiers.
            if (!string.IsNullOrEmpty(modifiers))
            {
                var modifierList   = InputTemplate.ParseNameAndParameterList(modifiers);
                var modifierString = string.Join(" OR ", modifierList.Select(x => x.name).ToArray());
                text = string.Format("{0} {1}", modifierString, text);
            }

            ////TODO: this looks ugly and not very obvious; find a better way
            // Show if linked with previous binding.
            if ((flags & InputBinding.Flags.ThisAndPreviousCombine) == InputBinding.Flags.ThisAndPreviousCombine)
            {
                text = "AND " + text;
            }

            return(new GUIContent(text));
        }
        // Equivalent to InputAction.AddBinding().
        public static SerializedProperty AddBinding(SerializedProperty actionProperty,
                                                    SerializedProperty actionMapProperty = null, SerializedProperty afterBinding = null,
                                                    string groups            = "", string path       = "", string name = "",
                                                    string interactions      = "", string processors = "",
                                                    InputBinding.Flags flags = InputBinding.Flags.None)
        {
            var bindingsArrayProperty = actionMapProperty != null
                ? actionMapProperty.FindPropertyRelative("m_Bindings")
                : actionProperty.FindPropertyRelative("m_SingletonActionBindings");

            var bindingsCount = bindingsArrayProperty.arraySize;
            var actionName    = actionProperty.FindPropertyRelative("m_Name").stringValue;

            int bindingIndex;

            if (afterBinding != null)
            {
                // If we're supposed to put the binding right after another binding, find the
                // binding's index. Also, if it's a composite, skip past all its parts.
                bindingIndex = GetIndex(bindingsArrayProperty, afterBinding);
                if (IsCompositeBinding(afterBinding))
                {
                    bindingIndex += GetCompositePartCount(bindingsArrayProperty, bindingIndex);
                }
                ++bindingIndex; // Put it *after* the binding.
            }
            else
            {
                // Find the index of the last binding for the action in the array.
                var indexOfLastBindingForAction = -1;
                for (var i = 0; i < bindingsCount; ++i)
                {
                    var bindingProperty   = bindingsArrayProperty.GetArrayElementAtIndex(i);
                    var bindingActionName = bindingProperty.FindPropertyRelative("m_Action").stringValue;
                    if (actionName.Equals(bindingActionName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        indexOfLastBindingForAction = i;
                    }
                }

                // Insert after last binding or at end of array.
                bindingIndex = indexOfLastBindingForAction != -1 ? indexOfLastBindingForAction + 1 : bindingsCount;
            }

            ////TODO: bind using {id} rather than action name
            return(AddBindingToBindingArray(bindingsArrayProperty,
                                            bindingIndex: bindingIndex,
                                            actionName: actionName,
                                            groups: groups,
                                            path: path,
                                            name: name,
                                            interactions: interactions,
                                            processors: processors,
                                            flags: flags));
        }
            ////TODO: close with escape

            public override void OnGUI(Rect rect)
            {
                m_ScrollPosition = GUI.BeginScrollView(rect, m_ScrollPosition, rect);

                // Interactions section.
                var interactionListRect = rect;

                interactionListRect.x     += kPaddingLeftRight;
                interactionListRect.y     += kPaddingTop;
                interactionListRect.width -= kPaddingLeftRight * 2;
                interactionListRect.height = m_InteractionListView.GetHeight();
                m_InteractionListView.DoList(interactionListRect);

                ////TODO: draw box around following section

                // Chaining toggle.
                var chainingToggleRect = interactionListRect;

                chainingToggleRect.y     += interactionListRect.height + 5;
                chainingToggleRect.height = kCombineToggleHeight;

                ////TODO: disable toggle if property is first in list (bit tricky to find out from the SerializedProperty)

                var currentCombineSetting = (m_Flags & InputBinding.Flags.ThisAndPreviousCombine) ==
                                            InputBinding.Flags.ThisAndPreviousCombine;
                var newCombineSetting = EditorGUI.ToggleLeft(chainingToggleRect, Contents.chain, currentCombineSetting);

                if (currentCombineSetting != newCombineSetting)
                {
                    if (newCombineSetting)
                    {
                        m_Flags |= InputBinding.Flags.ThisAndPreviousCombine;
                    }
                    else
                    {
                        m_Flags &= ~InputBinding.Flags.ThisAndPreviousCombine;
                    }

                    m_FlagsProperty.intValue = (int)m_Flags;
                    m_FlagsProperty.serializedObject.ApplyModifiedProperties();

                    if (onApplyCallback != null)
                    {
                        onApplyCallback(m_FlagsProperty);
                    }
                }

                GUI.EndScrollView();
            }
示例#5
0
            public ModifyPopupWindow(SerializedProperty bindingProperty)
            {
                m_FlagsProperty     = bindingProperty.FindPropertyRelative("flags");
                m_ModifiersProperty = bindingProperty.FindPropertyRelative("modifiers");
                m_Flags             = (InputBinding.Flags)m_FlagsProperty.intValue;

                var modifiers = InputSystem.ListModifiers().ToList();

                modifiers.Sort();
                m_ModifierChoices = modifiers.Select(x => new GUIContent(x)).ToArray();

                var modifierString = m_ModifiersProperty.stringValue;

                if (!string.IsNullOrEmpty(modifierString))
                {
                    m_Modifiers = InputTemplate.ParseNameAndParameterList(modifierString);
                }
                else
                {
                    m_Modifiers = new InputTemplate.NameAndParameters[0]; //Array.Empty<InputTemplate.NameAndParameters>();
                }
                InitializeModifierListView();
            }
        // Equivalent to InputAction.AddBinding().
        public static SerializedProperty AddBinding(SerializedProperty actionProperty,
                                                    SerializedProperty actionMapProperty = null, string groups = "", string path = "", string name = "",
                                                    string interactions      = "", string processors = "",
                                                    InputBinding.Flags flags = InputBinding.Flags.None)
        {
            var bindingsArrayProperty = actionMapProperty != null
                ? actionMapProperty.FindPropertyRelative("m_Bindings")
                : actionProperty.FindPropertyRelative("m_SingletonActionBindings");

            var bindingsCount = bindingsArrayProperty.arraySize;

            // Find the index of the last binding for the action in the array.
            var actionName = actionProperty.FindPropertyRelative("m_Name").stringValue;
            var indexOfLastBindingForAction = -1;

            for (var i = 0; i < bindingsCount; ++i)
            {
                var bindingProperty   = bindingsArrayProperty.GetArrayElementAtIndex(i);
                var bindingActionName = bindingProperty.FindPropertyRelative("m_Action").stringValue;
                if (string.Compare(actionName, bindingActionName, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    indexOfLastBindingForAction = i;
                }
            }

            // Insert after last binding or at end of array.
            var bindingIndex = indexOfLastBindingForAction != -1 ? indexOfLastBindingForAction + 1 : bindingsCount;

            return(AddBindingToBindingArray(bindingsArrayProperty, bindingIndex,
                                            actionName: actionName,
                                            groups: groups,
                                            path: path,
                                            name: name,
                                            interactions: interactions,
                                            processors: processors,
                                            flags: flags));
        }
            public ModifyPopupWindow(SerializedProperty bindingProperty)
            {
                m_FlagsProperty        = bindingProperty.FindPropertyRelative("m_Flags");
                m_InteractionsProperty = bindingProperty.FindPropertyRelative("m_Interactions");
                m_Flags = (InputBinding.Flags)m_FlagsProperty.intValue;

                var interactions = InputSystem.ListInteractions().ToList();

                interactions.Sort();
                m_InteractionChoices = interactions.Select(x => new GUIContent(x)).ToArray();

                var interactionString = m_InteractionsProperty.stringValue;

                if (!string.IsNullOrEmpty(interactionString))
                {
                    m_Interactions = InputControlLayout.ParseNameAndParameterList(interactionString);
                }
                else
                {
                    m_Interactions = new InputControlLayout.NameAndParameters[0];
                }

                InitializeInteractionListView();
            }
        ////TODO: move this out into a general routine that can take a path and construct a display name
        private static GUIContent GetContentForPath(string path, string interactions, InputBinding.Flags flags)
        {
            const int kUsageNameGroup   = 1;
            const int kDeviceNameGroup  = 1;
            const int kDeviceUsageGroup = 3;
            const int kControlPathGroup = 4;

            ////TODO: nuke the regex stuff in here

            if (s_UsageRegex == null)
            {
                s_UsageRegex = new Regex("\\*/{([A-Za-z0-9]+)}");
            }
            if (s_ControlRegex == null)
            {
                s_ControlRegex = new Regex("<([A-Za-z0-9:\\-]+)>({([A-Za-z0-9]+)})?/([A-Za-z0-9]+(/[A-Za-z0-9]+)*)");
            }

            var text = path;

            var usageMatch = s_UsageRegex.Match(path);

            if (usageMatch.Success)
            {
                text = usageMatch.Groups[kUsageNameGroup].Value;
            }
            else
            {
                var controlMatch = s_ControlRegex.Match(path);
                if (controlMatch.Success)
                {
                    var device      = controlMatch.Groups[kDeviceNameGroup].Value;
                    var deviceUsage = controlMatch.Groups[kDeviceUsageGroup].Value;
                    var control     = controlMatch.Groups[kControlPathGroup].Value;

                    ////TODO: would be nice to include layout name to print something like "Gamepad A Button" instead of "Gamepad A" (or whatever)

                    if (!string.IsNullOrEmpty(deviceUsage))
                    {
                        text = string.Format("{0} {1} {2}", deviceUsage, device, control);
                    }
                    else
                    {
                        text = string.Format("{0} {1}", device, control);
                    }
                }
            }

            ////REVIEW: would be nice to have icons for these

            // Show interactions.
            if (!string.IsNullOrEmpty(interactions))
            {
                var interactionList   = InputControlLayout.ParseNameAndParameterList(interactions);
                var interactionString = string.Join(" OR ", interactionList.Select(x => x.name).ToArray());
                text = string.Format("{0} {1}", interactionString, text);
            }

            ////TODO: this looks ugly and not very obvious; find a better way
            // Show if linked with previous binding.
            if ((flags & InputBinding.Flags.ThisAndPreviousCombine) == InputBinding.Flags.ThisAndPreviousCombine)
            {
                text = "AND " + text;
            }

            return(new GUIContent(text));
        }