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); } }
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); }
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) { }
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; }
public int GetIndexOfChild(AdvancedDropdownItem child) { return(m_Children.IndexOf(child)); }
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; }
protected virtual void ItemSelected(AdvancedDropdownItem item) { }