private static void AddPhysicalKeyBindingsTo(AdvancedDropdownItem parent, Keyboard keyboard, bool searchable)
        {
            foreach (var key in keyboard.children.OfType <KeyControl>())
            {
                // If the key has a display name that differs from the key name, show it in the UI.
                var displayName    = key.m_DisplayNameFromLayout;
                var keyDisplayName = key.displayName;
                if (keyDisplayName.All(x => x.IsPrintable()) && string.Compare(keyDisplayName, displayName,
                                                                               StringComparison.InvariantCultureIgnoreCase) != 0)
                {
                    displayName = $"{displayName} (Current Layout: {key.displayName})";
                }

                var item = new ControlDropdownItem(null, key.name, displayName,
                                                   keyboard.layout, "", searchable);

                parent.AddChild(item);
            }
        }
        protected virtual AdvancedDropdownItem Search(string searchString)
        {
            if (m_SearchableElements == null)
            {
                BuildSearchableElements();
            }
            if (string.IsNullOrEmpty(searchString))
            {
                return(null);
            }

            var searchTree = PerformCustomSearch(searchString);

            if (searchTree == null)
            {
                // Support multiple search words separated by spaces.
                var searchWords = searchString.ToLower().Split(' ');

                // We keep two lists. Matches that matches the start of an item always get first priority.
                var matchesStart  = new List <AdvancedDropdownItem>();
                var matchesWithin = new List <AdvancedDropdownItem>();

                foreach (var e in m_SearchableElements)
                {
                    var name = e.searchableName.ToLower().Replace(" ", "");
                    AddMatchItem(e, name, searchWords, matchesStart, matchesWithin);
                }

                searchTree = new AdvancedDropdownItem(kSearchHeader);
                matchesStart.Sort();
                foreach (var element in matchesStart)
                {
                    searchTree.AddChild(element);
                }
                matchesWithin.Sort();
                foreach (var element in matchesWithin)
                {
                    searchTree.AddChild(element);
                }
            }

            return(searchTree);
        }
 private AdvancedDropdownItemState GetStateForItem(AdvancedDropdownItem item)
 {
     if (m_LastSelectedState != null && m_LastSelectedState.itemId == item.id)
     {
         return(m_LastSelectedState);
     }
     for (int i = 0; i < states.Length; i++)
     {
         if (states[i].itemId == item.id)
         {
             m_LastSelectedState = states[i];
             return(m_LastSelectedState);
         }
     }
     Array.Resize(ref states, states.Length + 1);
     states[states.Length - 1] = new AdvancedDropdownItemState(item);
     m_LastSelectedState       = states[states.Length - 1];
     return(states[states.Length - 1]);
 }
        internal void MoveUpSelection(AdvancedDropdownItem item)
        {
            var state         = GetStateForItem(item);
            var selectedIndex = state.selectedIndex;

            do
            {
                --selectedIndex;
            }while (selectedIndex >= 0 && item.children.ElementAt(selectedIndex).IsSeparator());

            if (selectedIndex < 0)
            {
                selectedIndex = item.children.Count() - 1;
            }

            if (selectedIndex >= 0)
            {
                SetSelectionOnItem(item, selectedIndex);
            }
        }
Beispiel #5
0
        protected override AdvancedDropdownItem BuildRoot()
        {
            var root = new AdvancedDropdownItem(string.Empty);

            // Usages.
            if (m_Mode != InputControlPicker.Mode.PickDevice)
            {
                var usages = BuildTreeForUsages();
                if (usages.children.Any())
                {
                    root.AddChild(usages);
                    root.AddSeparator();
                }
            }

            // Devices.
            AddItemsForDevices(root);

            return(root);
        }
        protected override AdvancedDropdownItem FetchData()
        {
            var rootGroup = new AdvancedDropdownItem(m_Label);

            m_SearchableElements = new List <AdvancedDropdownItem>();

            for (int i = 0; i < m_DisplayedOptions.Length; i++)
            {
                var menuPath = m_DisplayedOptions[i];
                var paths    = menuPath.Split('/');

                AdvancedDropdownItem parent = rootGroup;
                for (var j = 0; j < paths.Length; j++)
                {
                    var path = paths[j];
                    if (j == paths.Length - 1)
                    {
                        var element = new MultiLevelItem(path, menuPath);
                        element.elementIndex = i;
                        parent.AddChild(element);
                        m_SearchableElements.Add(element);
                        continue;
                    }

                    var groupPathId = paths[0];
                    for (int k = 1; k <= j; k++)
                    {
                        groupPathId += "/" + paths[k];
                    }

                    var group = parent.children.SingleOrDefault(c => ((MultiLevelItem)c).stringId == groupPathId);
                    if (group == null)
                    {
                        group = new MultiLevelItem(path, groupPathId);
                        parent.AddChild(group);
                    }
                    parent = group;
                }
            }
            return(rootGroup);
        }
        protected bool AddMatchItem(AdvancedDropdownItem e, string name, string[] searchWords, List <AdvancedDropdownItem> matchesStart, List <AdvancedDropdownItem> matchesWithin)
        {
            var didMatchAll   = true;
            var didMatchStart = false;

            // See if we match ALL the search words.
            for (var w = 0; w < searchWords.Length; w++)
            {
                var search = searchWords[w];
                if (name.Contains(search))
                {
                    // If the start of the item matches the first search word, make a note of that.
                    if (w == 0 && name.StartsWith(search))
                    {
                        didMatchStart = true;
                    }
                }
                else
                {
                    // As soon as any word is not matched, we disregard this item.
                    didMatchAll = false;
                    break;
                }
            }
            // We always need to match all search words.
            // If we ALSO matched the start, this item gets priority.
            if (didMatchAll)
            {
                if (didMatchStart)
                {
                    matchesStart.Add(e);
                }
                else
                {
                    matchesWithin.Add(e);
                }
            }
            return(didMatchAll);
        }
Beispiel #8
0
        private static void AddPhysicalKeyBindingsTo(AdvancedDropdownItem parent, Keyboard keyboard, bool searchable)
        {
            foreach (var key in keyboard.children.OfType <KeyControl>())
            {
                // If the key has a display name that differs from the key name, show it in the UI.
                var displayName    = key.m_DisplayNameFromLayout;
                var keyDisplayName = key.displayName;
                if (keyDisplayName.All(x => x.IsPrintable()) && string.Compare(keyDisplayName, displayName,
                                                                               StringComparison.InvariantCultureIgnoreCase) != 0)
                {
                    displayName = $"{displayName} (Current Layout: {key.displayName})";
                }

                // For left/right modifier keys, prepend artificial combined version.
                ButtonControl combinedVersion = null;
                if (key == keyboard.leftShiftKey)
                {
                    combinedVersion = keyboard.shiftKey;
                }
                else if (key == keyboard.leftAltKey)
                {
                    combinedVersion = keyboard.altKey;
                }
                else if (key == keyboard.leftCtrlKey)
                {
                    combinedVersion = keyboard.ctrlKey;
                }
                if (combinedVersion != null)
                {
                    parent.AddChild(new ControlDropdownItem(null, combinedVersion.name, combinedVersion.displayName, keyboard.layout,
                                                            "", searchable));
                }

                var item = new ControlDropdownItem(null, key.name, displayName,
                                                   keyboard.layout, "", searchable);

                parent.AddChild(item);
            }
        }
 internal Vector2 GetScrollState(AdvancedDropdownItem item)
 {
     return(GetStateForItem(item).scroll);
 }
 internal virtual void DrawFooter(AdvancedDropdownItem selectedItem)
 {
 }
Beispiel #11
0
        protected override void ItemSelected(AdvancedDropdownItem item)
        {
            var path = ((InputControlDropdownItem)item).controlPathWithDevice;

            m_OnPickCallback(path);
        }
 internal void ClearSelectionOnItem(AdvancedDropdownItem item)
 {
     GetStateForItem(item).selectedIndex = -1;
 }
 public void AddChild(AdvancedDropdownItem child)
 {
     m_Children.Add(child);
 }
 internal int GetSelectedIndex(AdvancedDropdownItem item)
 {
     return(GetStateForItem(item).selectedIndex);
 }
 internal void SetSelectedIndex(AdvancedDropdownItem item, int index)
 {
     GetStateForItem(item).selectedIndex = index;
 }
Beispiel #16
0
 public int GetIndexOfChild(AdvancedDropdownItem child)
 {
     return(m_Children.IndexOf(child));
 }
Beispiel #17
0
        private void AddDeviceTreeItemRecursive(InputControlLayout layout, AdvancedDropdownItem parent, bool searchable = true)
        {
            // Find all layouts directly based on this one.
            var childLayouts = EditorInputControlLayoutCache.allLayouts
                               .Where(x => x.isDeviceLayout && !x.hideInUI && x.baseLayouts.Contains(layout.name)).OrderBy(x => x.displayName);

            // See if the entire tree should be excluded.
            var shouldIncludeDeviceLayout          = ShouldIncludeDeviceLayout(layout);
            var shouldIncludeAtLeastOneChildLayout = childLayouts.Any(ShouldIncludeDeviceLayout);

            if (!shouldIncludeDeviceLayout && !shouldIncludeAtLeastOneChildLayout)
            {
                return;
            }

            // Add toplevel item for device.
            var deviceItem = new DeviceDropdownItem(layout, searchable: searchable);

            parent.AddChild(deviceItem);

            // Add common usage variants.
            if (m_Mode != InputControlPicker.Mode.PickDevice && layout.commonUsages.Count > 0)
            {
                foreach (var usage in layout.commonUsages)
                {
                    var usageItem = new DeviceDropdownItem(layout, usage);
                    AddControlTreeItemsRecursive(layout, usageItem, layout.name, usage, searchable);
                    deviceItem.AddChild(usageItem);
                }
                deviceItem.AddSeparator();
            }

            // Add controls.
            var haveControls = false;

            if (shouldIncludeDeviceLayout && m_Mode != InputControlPicker.Mode.PickDevice)
            {
                var childCountBefore = deviceItem.children.Count();

                // The keyboard is special in that we want to allow binding by display name (i.e. character
                // generated by a key) instead of only by physical key location. Also, we want to give an indication
                // of which specific key an entry refers to by taking the current keyboard layout into account.
                //
                // So what we do is add an extra level to the keyboard where key's can be bound by character
                // according to the current layout. And in the top level of the keyboard we display keys with
                // both physical and logical names.
                if (layout.type == typeof(Keyboard) && Keyboard.current != null)
                {
                    var byLocationGroup  = new AdvancedDropdownItem("By Location of Key (Using US Layout)");
                    var byCharacterGroup = new AdvancedDropdownItem("By Character Mapped to Key");

                    deviceItem.AddChild(byLocationGroup);
                    deviceItem.AddChild(byCharacterGroup);

                    var keyboard = Keyboard.current;

                    AddCharacterKeyBindingsTo(byCharacterGroup, keyboard);
                    AddPhysicalKeyBindingsTo(byLocationGroup, keyboard, searchable);
                }
                else
                {
                    AddControlTreeItemsRecursive(layout, deviceItem, layout.name, null, searchable);
                }

                haveControls = deviceItem.children.Count() != childCountBefore;
            }

            // Add child items.
            var isFirstChild = true;

            foreach (var childLayout in childLayouts)
            {
                if (!ShouldIncludeDeviceLayout(childLayout))
                {
                    continue;
                }

                if (isFirstChild && haveControls)
                {
                    deviceItem.AddSeparator("More Specific " + deviceItem.name.GetPlural());
                }
                isFirstChild = false;

                AddDeviceTreeItemRecursive(childLayout, deviceItem, searchable && !childLayout.isGenericTypeOfDevice);
            }

            // When picking devices, it must be possible to select a device that itself has more specific types
            // of devices underneath it. However in the dropdown, such a device will be a foldout and not itself
            // be selectable. We solve this problem by adding an entry for the device underneath the device
            // itself (e.g. "Gamepad >> Gamepad").
            if (m_Mode == InputControlPicker.Mode.PickDevice && deviceItem.m_Children.Count > 0)
            {
                var item = new DeviceDropdownItem(layout);
                deviceItem.m_Children.Insert(0, item);
            }
        }
 public AdvancedDropdownItemState(AdvancedDropdownItem item)
 {
     itemId = item.id;
 }
 internal void SetScrollState(AdvancedDropdownItem item, Vector2 scrollState)
 {
     GetStateForItem(item).scroll = scrollState;
 }
Beispiel #20
0
 protected virtual void ItemSelected(AdvancedDropdownItem item)
 {
 }