예제 #1
0
        private int ResolveProcessors(string processorString)
        {
            var firstProcessorIndex = totalProcessorCount;

            if (!InputControlLayout.ParseNameAndParameterList(processorString, ref m_Parameters))
            {
                return(firstProcessorIndex);
            }

            for (var i = 0; i < m_Parameters.Count; ++i)
            {
                // Look up processor.
                var type = InputControlProcessor.s_Processors.LookupTypeRegistration(m_Parameters[i].name);
                if (type == null)
                {
                    throw new Exception(string.Format(
                                            "No processor with name '{0}' (mentioned in '{1}') has been registered", m_Parameters[i].name,
                                            processorString));
                }

                // Instantiate it.
                var processor = Activator.CreateInstance(type);

                // Pass parameters to it.
                InputDeviceBuilder.SetParameters(processor, m_Parameters[i].parameters);

                // Add to list.
                ArrayHelpers.AppendWithCapacity(ref processors, ref totalProcessorCount, processor);
            }

            return(firstProcessorIndex);
        }
예제 #2
0
 void OnSelection(ReorderableList list)
 {
     if (list.index < 0)
     {
         m_SelectedRow = null;
         return;
     }
     m_SelectedRow           = (string)list.list[list.index];
     m_NamesAndParams        = InputControlLayout.ParseNameAndParameterList(m_Property.stringValue);
     m_SelectedParameterList = GetFieldsFromClass();
 }
예제 #3
0
        protected PropertiesReorderableList(SerializedProperty property, Action applyAction)
        {
            m_Property    = property;
            m_Apply       = applyAction;
            m_ListItems   = new List <string>();
            m_ListOptions = GetOptions();
            m_EditableParametersForSelectedItem = new ParameterListView {
                onChange = OnParametersChanged
            };
            m_ParametersForEachListItem = InputControlLayout.ParseNameAndParameterList(m_Property.stringValue)
                                          ?? new InputControlLayout.NameAndParameters[0];

            foreach (var nameAndParams in m_ParametersForEachListItem)
            {
                m_ListItems.Add(nameAndParams.name);
            }

            m_ListView = new ReorderableList(m_ListItems, typeof(string))
            {
                headerHeight          = 3,
                onAddDropdownCallback = (rect, list) =>
                {
                    var menu = new GenericMenu();
                    foreach (var name in m_ListOptions.names)
                    {
                        menu.AddItem(new GUIContent(name), false, OnAddElement, name);
                    }
                    menu.ShowAsContext();
                },
                onRemoveCallback = list =>
                {
                    var index = list.index;
                    list.list.RemoveAt(index);
                    ArrayHelpers.EraseAt(ref m_ParametersForEachListItem, index);
                    m_EditableParametersForSelectedItem.Clear();
                    m_Apply();
                    list.index = -1;
                },
                onReorderCallbackWithDetails = (list, oldIndex, newIndex) =>
                {
                    MemoryHelpers.Swap(ref m_ParametersForEachListItem[oldIndex],
                                       ref m_ParametersForEachListItem[newIndex]);
                    OnSelection(list);
                    m_Apply();
                },
                onSelectCallback = OnSelection
            };
        }
예제 #4
0
        private int ResolveInteractions(string interactionString)
        {
            ////REVIEW: We're piggybacking off the processor parsing here as the two syntaxes are identical. Might consider
            ////        moving the logic to a shared place.
            ////        Alternatively, may split the paths. May help in getting rid of unnecessary allocations.

            var firstInteractionIndex = totalInteractionCount;

            if (!InputControlLayout.ParseNameAndParameterList(interactionString, ref m_Parameters))
            {
                return(firstInteractionIndex);
            }

            for (var i = 0; i < m_Parameters.Count; ++i)
            {
                // Look up interaction.
                var type = InputInteraction.s_Interactions.LookupTypeRegistration(m_Parameters[i].name);
                if (type == null)
                {
                    throw new Exception(string.Format(
                                            "No interaction with name '{0}' (mentioned in '{1}') has been registered", m_Parameters[i].name,
                                            interactionString));
                }

                // Instantiate it.
                var interaction = Activator.CreateInstance(type) as IInputInteraction;
                if (interaction == null)
                {
                    throw new Exception(string.Format("Interaction '{0}' is not an IInputInteraction", m_Parameters[i].name));
                }

                // Pass parameters to it.
                InputDeviceBuilder.SetParameters(interaction, m_Parameters[i].parameters);

                // Add to list.
                var interactionStateCount = totalInteractionCount;
                ArrayHelpers.AppendWithCapacity(ref interactionStates, ref interactionStateCount,
                                                new InputActionMapState.InteractionState
                {
                    phase = InputActionPhase.Waiting
                });
                ArrayHelpers.AppendWithCapacity(ref interactions, ref totalInteractionCount, interaction);
                Debug.Assert(interactionStateCount == totalInteractionCount);
            }

            return(firstInteractionIndex);
        }
예제 #5
0
        public PropertiesReorderableList(SerializedProperty property, Action applyAction)
        {
            m_Property    = property;
            m_Apply       = applyAction;
            m_ListOptions = GetOptions();
            m_ListView    = new ReorderableList(new List <string>(), typeof(string));

            m_NamesAndParams = InputControlLayout.ParseNameAndParameterList(m_Property.stringValue);
            if (m_NamesAndParams == null)
            {
                m_NamesAndParams = new InputControlLayout.NameAndParameters[0];
            }
            foreach (var nameAndParams in m_NamesAndParams)
            {
                m_ListView.list.Add(nameAndParams.name);
            }

            m_ListView.headerHeight          = 3;
            m_ListView.onAddDropdownCallback =
                (rect, list) =>
            {
                var menu = new GenericMenu();
                for (var i = 0; i < m_ListOptions.names.Count(); ++i)
                {
                    menu.AddItem(new GUIContent(m_ListOptions.names.ElementAt(i)), false, AddElement, m_ListOptions.names.ElementAt(i));
                }
                menu.ShowAsContext();
            };
            m_ListView.onRemoveCallback =
                (list) =>
            {
                list.list.RemoveAt(list.index);
                m_Apply();
                list.index = -1;
            };
            m_ListView.onReorderCallback = list => { m_Apply(); };
            m_ListView.onSelectCallback  = OnSelection;
        }
예제 #6
0
            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();
            }
예제 #7
0
        ////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));
        }
예제 #8
0
        protected PropertiesReorderableList(SerializedProperty property, Action applyAction, string expectedControlLayout)
        {
            m_Property    = property;
            m_Apply       = applyAction;
            m_ListItems   = new List <string>();
            m_ListOptions = GetOptions();
            m_EditableParametersForSelectedItem = new ParameterListView {
                onChange = OnParametersChanged
            };
            m_ParametersForEachListItem = InputControlLayout.ParseNameAndParameterList(m_Property.stringValue)
                                          ?? new InputControlLayout.NameAndParameters[0];
            m_ExpectedControlLayout = expectedControlLayout;

            foreach (var nameAndParams in m_ParametersForEachListItem)
            {
                var name = ObjectNames.NicifyVariableName(nameAndParams.name);

                ////REVIEW: finding this kind of stuff should probably have better support globally on the asset; e.g. some
                ////        notification that pops up and allows fixing all occurrences in one click
                // Find out if we still support this option and indicate it in the list, if we don't.
                if (m_ListOptions.LookupTypeRegistration(new InternedString(nameAndParams.name)) == null)
                {
                    name += " (Obsolete)";
                }

                m_ListItems.Add(name);
            }

            m_ListView = new ReorderableList(m_ListItems, typeof(string))
            {
                headerHeight          = 3,
                onAddDropdownCallback = (rect, list) =>
                {
                    Type expectedValueType = null;
                    if (!string.IsNullOrEmpty(m_ExpectedControlLayout))
                    {
                        expectedValueType = EditorInputControlLayoutCache.GetValueType(m_ExpectedControlLayout);
                    }

                    // Add only original names to the menu and not aliases.
                    var menu = new GenericMenu();
                    foreach (var name in m_ListOptions.internedNames.Where(x => !m_ListOptions.aliases.Contains(x)).OrderBy(x => x.ToString()))
                    {
                        // Skip if not compatible with value type.
                        if (expectedValueType != null)
                        {
                            var type      = m_ListOptions.LookupTypeRegistration(name);
                            var valueType = GetValueType(type);
                            if (valueType != null && !expectedValueType.IsAssignableFrom(valueType))
                            {
                                continue;
                            }
                        }

                        var niceName = ObjectNames.NicifyVariableName(name);
                        menu.AddItem(new GUIContent(niceName), false, OnAddElement, name.ToString());
                    }
                    menu.ShowAsContext();
                },
                onRemoveCallback = list =>
                {
                    var index = list.index;
                    list.list.RemoveAt(index);
                    ArrayHelpers.EraseAt(ref m_ParametersForEachListItem, index);
                    m_EditableParametersForSelectedItem.Clear();
                    m_Apply();
                    list.index = -1;
                },
                onReorderCallbackWithDetails = (list, oldIndex, newIndex) =>
                {
                    MemoryHelpers.Swap(ref m_ParametersForEachListItem[oldIndex],
                                       ref m_ParametersForEachListItem[newIndex]);
                    OnSelection(list);
                    m_Apply();
                },
                onSelectCallback = OnSelection
            };
        }
        ////TODO: move this out into a general routine that can take a path and construct a display name
        private 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;

            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;

            ////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[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));
        }