123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- #if UNITY_EDITOR
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using UnityEditor;
- using UnityEngine.InputSystem.Controls;
- using UnityEngine.InputSystem.Layouts;
- using UnityEngine.InputSystem.Utilities;
-
- ////TODO: have tooltips on each entry in the picker
-
- ////TODO: find better way to present controls when filtering to specific devices
-
- ////REVIEW: if there's only a single device in the picker, automatically go into it?
-
- namespace UnityEngine.InputSystem.Editor
- {
- internal class InputControlPickerDropdown : AdvancedDropdown, IDisposable
- {
- 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 void SetControlPathsToMatch(string[] controlPathsToMatch)
- {
- m_ControlPathsToMatch = controlPathsToMatch;
- Reload();
- }
-
- public void SetExpectedControlLayout(string expectedControlLayout)
- {
- m_ExpectedControlLayout = expectedControlLayout;
-
- if (string.Equals(expectedControlLayout, "InputDevice", StringComparison.InvariantCultureIgnoreCase))
- m_ExpectedControlType = typeof(InputDevice);
- else
- m_ExpectedControlType = !string.IsNullOrEmpty(expectedControlLayout)
- ? InputSystem.s_Manager.m_Layouts.GetControlTypeForLayout(new InternedString(expectedControlLayout))
- : null;
-
- // If the layout is for a device, automatically switch to device
- // picking mode.
- if (m_ExpectedControlType != null && typeof(InputDevice).IsAssignableFrom(m_ExpectedControlType))
- m_Mode = InputControlPicker.Mode.PickDevice;
-
- Reload();
- }
-
- public void SetPickedCallback(Action<string> action)
- {
- m_OnPickCallback = action;
- }
-
- protected override void OnDestroy()
- {
- #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
- InputActionsEditorSettingsProvider.SetIMGUIDropdownVisible(false, false);
- #endif
- m_RebindingOperation?.Dispose();
- m_RebindingOperation = null;
- }
-
- public void Dispose()
- {
- m_RebindingOperation?.Dispose();
- }
-
- protected override AdvancedDropdownItem BuildRoot()
- {
- var root = new AdvancedDropdownItem(string.Empty);
-
- // Usages.
- if (m_Mode != InputControlPicker.Mode.PickDevice)
- {
- var usages = BuildTreeForControlUsages();
- if (usages.children.Any())
- {
- root.AddChild(usages);
- root.AddSeparator();
- }
- }
-
- // Devices.
- AddItemsForDevices(root);
-
- return root;
- }
-
- protected override AdvancedDropdownItem BuildCustomSearch(string searchString,
- IEnumerable<AdvancedDropdownItem> elements)
- {
- if (!isListening)
- return null;
-
- var root = new AdvancedDropdownItem(!string.IsNullOrEmpty(m_ExpectedControlLayout)
- ? $"Listening for {m_ExpectedControlLayout}..."
- : "Listening for input...");
-
- if (searchString == "\u0017")
- return root;
-
- var paths = searchString.Substring(1).Split('\u0017');
- foreach (var element in elements)
- {
- if (element is ControlDropdownItem controlItem && paths.Any(x => controlItem.controlPathWithDevice == x))
- root.AddChild(element);
- }
-
- return root;
- }
-
- protected override void ItemSelected(AdvancedDropdownItem item)
- {
- #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
- InputActionsEditorSettingsProvider.SetIMGUIDropdownVisible(false, true);
- #endif
- var path = ((InputControlDropdownItem)item).controlPathWithDevice;
- m_OnPickCallback(path);
- }
-
- private AdvancedDropdownItem BuildTreeForControlUsages(string device = "", string usage = "")
- {
- var usageRoot = new AdvancedDropdownItem("Usages");
- foreach (var usageAndLayouts in EditorInputControlLayoutCache.allUsages)
- {
- if (usageAndLayouts.Item2.Any(LayoutMatchesExpectedControlLayoutFilter))
- {
- var child = new ControlUsageDropdownItem(device, usage, usageAndLayouts.Item1);
- usageRoot.AddChild(child);
- }
- }
- return usageRoot;
- }
-
- private void AddItemsForDevices(AdvancedDropdownItem parent)
- {
- // Add devices that are marked as generic types of devices directly to the parent.
- // E.g. adds "Gamepad" and then underneath all the more specific types of gamepads.
- foreach (var deviceLayout in EditorInputControlLayoutCache.allLayouts
- .Where(x => x.isDeviceLayout && !x.isOverride && x.isGenericTypeOfDevice && !x.hideInUI)
- .OrderBy(a => a.displayName))
- {
- AddDeviceTreeItemRecursive(deviceLayout, parent);
- }
-
- // We have devices that are based directly on InputDevice but are not marked as generic types
- // of devices (e.g. Vive Lighthouses). We do not want them to clutter the list at the root so we
- // put all of them in a group called "Other" at the end of the list.
- var otherGroup = new AdvancedDropdownItem("Other");
- foreach (var deviceLayout in EditorInputControlLayoutCache.allLayouts
- .Where(x => x.isDeviceLayout && !x.isOverride && !x.isGenericTypeOfDevice &&
- (x.type.BaseType == typeof(InputDevice) || x.type == typeof(InputDevice)) &&
- !x.hideInUI && !x.baseLayouts.Any()).OrderBy(a => a.displayName))
- {
- AddDeviceTreeItemRecursive(deviceLayout, otherGroup);
- }
-
- if (otherGroup.children.Any())
- parent.AddChild(otherGroup);
- }
-
- private void AddDeviceTreeItemRecursive(InputControlLayout layout, AdvancedDropdownItem parent, bool searchable = true)
- {
- // Find all layouts directly based on this one (ignoring overrides).
- var childLayouts = EditorInputControlLayoutCache.allLayouts
- .Where(x => x.isDeviceLayout && !x.isOverride && !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);
-
- var defaultControlPickerLayout = new DefaultInputControlPickerLayout();
-
- // Add common usage variants of the device
- if (layout.commonUsages.Count > 0)
- {
- foreach (var usage in layout.commonUsages)
- {
- var usageItem = new DeviceDropdownItem(layout, usage);
-
- // Add control usages to the device variants
- var deviceVariantControlUsages = BuildTreeForControlUsages(layout.name, usage);
- if (deviceVariantControlUsages.children.Any())
- {
- usageItem.AddChild(deviceVariantControlUsages);
- usageItem.AddSeparator();
- }
-
- if (m_Mode == InputControlPicker.Mode.PickControl)
- AddControlTreeItemsRecursive(defaultControlPickerLayout, layout, usageItem, layout.name, usage, searchable);
- deviceItem.AddChild(usageItem);
- }
- deviceItem.AddSeparator();
- }
-
- // Add control usages
- var deviceControlUsages = BuildTreeForControlUsages(layout.name);
- if (deviceControlUsages.children.Any())
- {
- deviceItem.AddChild(deviceControlUsages);
- deviceItem.AddSeparator();
- }
-
- // Add controls.
- if (m_Mode != InputControlPicker.Mode.PickDevice)
- {
- // 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) && InputSystem.GetDevice<Keyboard>() != 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 = InputSystem.GetDevice<Keyboard>();
-
- AddCharacterKeyBindingsTo(byCharacterGroup, keyboard);
- AddPhysicalKeyBindingsTo(byLocationGroup, keyboard, searchable);
-
- // AnyKey won't appear in either group. Add it explicitly.
- AddControlItem(defaultControlPickerLayout, deviceItem, null,
- layout.FindControl(new InternedString("anyKey")).Value, layout.name, null, searchable);
- }
- else if (layout.type == typeof(Touchscreen))
- {
- AddControlTreeItemsRecursive(new TouchscreenControlPickerLayout(), layout, deviceItem, layout.name, null, searchable);
- }
- else
- {
- AddControlTreeItemsRecursive(defaultControlPickerLayout, layout, deviceItem, layout.name, null, searchable);
- }
- }
-
- // Add child items.
- var isFirstChild = true;
- foreach (var childLayout in childLayouts)
- {
- if (!ShouldIncludeDeviceLayout(childLayout))
- continue;
-
- if (isFirstChild)
- 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);
- }
-
- if (deviceItem.m_Children.Count > 0 || m_Mode == InputControlPicker.Mode.PickDevice)
- parent.AddChild(deviceItem);
- }
-
- private void AddControlTreeItemsRecursive(IInputControlPickerLayout controlPickerLayout, InputControlLayout layout,
- DeviceDropdownItem parent, string device, string usage, bool searchable, ControlDropdownItem parentControl = null)
- {
- foreach (var control in layout.controls.OrderBy(a => a.name))
- {
- if (control.isModifyingExistingControl)
- continue;
-
- // Skip variants except the default variant and variants dictated by the layout itself.
- if (!control.variants.IsEmpty() && control.variants != InputControlLayout.DefaultVariant
- && (layout.variants.IsEmpty() || !InputControlLayout.VariantsMatch(layout.variants, control.variants)))
- {
- continue;
- }
-
- controlPickerLayout.AddControlItem(this, parent, parentControl, control, device, usage, searchable);
- }
-
- // Add optional controls for devices.
- var optionalControls = EditorInputControlLayoutCache.GetOptionalControlsForLayout(layout.name);
- if (optionalControls.Any() && layout.isDeviceLayout)
- {
- var optionalGroup = new AdvancedDropdownItem("Optional Controls");
- foreach (var optionalControl in optionalControls)
- {
- ////FIXME: this should list children, too
- ////FIXME: this should handle arrays, too
- if (LayoutMatchesExpectedControlLayoutFilter(optionalControl.layout))
- {
- var child = new OptionalControlDropdownItem(optionalControl, device, usage);
- child.icon = EditorInputControlLayoutCache.GetIconForLayout(optionalControl.layout);
- optionalGroup.AddChild(child);
- }
- }
-
- if (optionalGroup.children.Any())
- {
- var deviceName = EditorInputControlLayoutCache.TryGetLayout(device).m_DisplayName ??
- ObjectNames.NicifyVariableName(device);
- parent.AddSeparator("Controls Present on More Specific " + deviceName.GetPlural());
- parent.AddChild(optionalGroup);
- }
- }
- }
-
- internal void AddControlItem(IInputControlPickerLayout controlPickerLayout,
- DeviceDropdownItem parent, ControlDropdownItem parentControl,
- InputControlLayout.ControlItem control, string device, string usage, bool searchable,
- string controlNameOverride = default)
- {
- var controlName = controlNameOverride ?? control.name;
-
- // If it's an array, generate a control entry for each array element.
- for (var i = 0; i < (control.isArray ? control.arraySize : 1); ++i)
- {
- var name = control.isArray ? controlName + i : controlName;
- var displayName = !string.IsNullOrEmpty(control.displayName)
- ? (control.isArray ? $"{control.displayName} #{i}" : control.displayName)
- : name;
-
- var child = new ControlDropdownItem(parentControl, name, displayName,
- device, usage, searchable);
- child.icon = EditorInputControlLayoutCache.GetIconForLayout(control.layout);
- var controlLayout = EditorInputControlLayoutCache.TryGetLayout(control.layout);
-
- if (LayoutMatchesExpectedControlLayoutFilter(control.layout))
- parent.AddChild(child);
- else if (controlLayout.controls.Any(x => LayoutMatchesExpectedControlLayoutFilter(x.layout)))
- {
- child.enabled = false;
- parent.AddChild(child);
- }
- // Add children.
- if (controlLayout != null)
- AddControlTreeItemsRecursive(controlPickerLayout, controlLayout, parent, device, usage,
- searchable, child);
- }
- }
-
- 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);
- }
- }
-
- private static void AddCharacterKeyBindingsTo(AdvancedDropdownItem parent, Keyboard keyboard)
- {
- foreach (var key in keyboard.children.OfType<KeyControl>())
- {
- if (!key.keyCode.IsTextInputKey())
- continue;
-
- // We can only bind to characters that can be printed.
- var displayName = key.displayName;
- if (!displayName.All(x => x.IsPrintable()))
- continue;
-
- if (displayName.Contains(')'))
- displayName = string.Join("", displayName.Select(x => "\\" + x));
-
- ////TODO: should be searchable; when searching, needs different display name
- var item = new ControlDropdownItem(null, $"#({displayName})", "", keyboard.layout, "", false);
- item.name = key.displayName;
-
- parent.AddChild(item);
- }
- }
-
- private bool LayoutMatchesExpectedControlLayoutFilter(string layout)
- {
- if (m_ExpectedControlType == null)
- return true;
-
- var layoutType = InputSystem.s_Manager.m_Layouts.GetControlTypeForLayout(new InternedString(layout));
- return m_ExpectedControlType.IsAssignableFrom(layoutType);
- }
-
- private bool ShouldIncludeDeviceLayout(InputControlLayout layout)
- {
- if (layout.hideInUI)
- return false;
-
- // By default, if a device has no (usable) controls, we don't want it listed in the control picker
- // except if we're picking devices.
- if (!layout.controls.Any(x => LayoutMatchesExpectedControlLayoutFilter(x.layout)) && layout.controls.Any(x => true) &&
- m_Mode != InputControlPicker.Mode.PickDevice)
- return false;
-
- // If we have a device filter, see if we should ignore the device.
- if (m_ControlPathsToMatch != null && m_ControlPathsToMatch.Length > 0)
- {
- var matchesAnyInDeviceFilter = false;
- foreach (var entry in m_ControlPathsToMatch)
- {
- // Include the layout if it's in the inheritance hierarchy of the layout we expect (either below
- // or above it or, well, just right on it).
- var expectedLayout = InputControlPath.TryGetDeviceLayout(entry);
- if (!string.IsNullOrEmpty(expectedLayout) &&
- (expectedLayout == layout.name ||
- InputControlLayout.s_Layouts.IsBasedOn(layout.name, new InternedString(expectedLayout)) ||
- InputControlLayout.s_Layouts.IsBasedOn(new InternedString(expectedLayout), layout.name)))
- {
- matchesAnyInDeviceFilter = true;
- break;
- }
- }
-
- if (!matchesAnyInDeviceFilter)
- return false;
- }
-
- return true;
- }
-
- private void StartListening()
- {
- if (m_RebindingOperation == null)
- m_RebindingOperation = new InputActionRebindingExtensions.RebindingOperation();
-
- ////TODO: for keyboard, generate both possible paths (physical and by display name)
-
- m_RebindingOperation.Reset();
- m_RebindingOperation
- .WithExpectedControlType(m_ExpectedControlLayout)
- // Require minimum actuation of 0.15f. This is after deadzoning has been applied.
- .WithMagnitudeHavingToBeGreaterThan(0.15f)
- ////REVIEW: should we exclude only the system's active pointing device?
- // With the mouse operating the UI, its cursor control is too fickle a thing to
- // bind to. Ignore mouse position and delta and clicks.
- // NOTE: We go for all types of pointers here, not just mice.
- .WithControlsExcluding("<Pointer>/position")
- .WithControlsExcluding("<Pointer>/delta")
- .WithControlsExcluding("<Pointer>/press")
- .WithControlsExcluding("<Pointer>/clickCount")
- .WithControlsExcluding("<Pointer>/{PrimaryAction}")
- .WithControlsExcluding("<Mouse>/scroll")
- .OnPotentialMatch(
- operation =>
- {
- // We never really complete the pick but keep listening for as long as the "Interactive"
- // button is toggled on.
-
- Repaint();
- })
- .OnCancel(
- operation =>
- {
- Repaint();
- })
- .OnApplyBinding(
- (operation, newPath) =>
- {
- // This is never invoked (because we don't complete the pick) but we need it nevertheless
- // as RebindingOperation requires the callback if we don't supply an action to apply the binding to.
- });
-
- // If we have control paths to match, pass them on.
- if (m_ControlPathsToMatch.LengthSafe() > 0)
- m_ControlPathsToMatch.Select(x => m_RebindingOperation.WithControlsHavingToMatchPath(x));
-
- m_RebindingOperation.Start();
- }
-
- private void StopListening()
- {
- m_RebindingOperation?.Cancel();
- }
-
- // This differs from RebindingOperation.GeneratePathForControl in that it cycles through all
- // layouts in the inheritance chain and generates a path for each one that contains the given control.
- private static IEnumerable<string> GeneratePossiblePathsForControl(InputControl control)
- {
- var builder = new StringBuilder();
- var deviceLayoutName = control.device.m_Layout;
- do
- {
- // Skip layout if it is supposed to be hidden in the UI.
- var layout = EditorInputControlLayoutCache.TryGetLayout(deviceLayoutName);
- if (layout.hideInUI)
- continue;
-
- builder.Length = 0;
- yield return control.BuildPath(deviceLayoutName, builder);
- }
- while (InputControlLayout.s_Layouts.baseLayoutTable.TryGetValue(deviceLayoutName, out deviceLayoutName));
- }
-
- private Action<string> m_OnPickCallback;
- private InputControlPicker.Mode m_Mode;
- private string[] m_ControlPathsToMatch;
- private string m_ExpectedControlLayout;
- private Type m_ExpectedControlType;
- private InputActionRebindingExtensions.RebindingOperation m_RebindingOperation;
-
- private bool isListening => m_RebindingOperation != null && m_RebindingOperation.started;
-
- private class InputControlPickerGUI : AdvancedDropdownGUI
- {
- private readonly InputControlPickerDropdown m_Owner;
-
- public InputControlPickerGUI(InputControlPickerDropdown owner)
- {
- m_Owner = owner;
- }
-
- internal override void BeginDraw(EditorWindow window)
- {
- if (Event.current.isKey && Event.current.keyCode == KeyCode.Escape)
- {
- window.Close();
- return;
- }
-
- if (m_Owner.isListening)
- {
- // Eat key events to suppress the editor from passing them to the OS
- // (causing beeps or menu commands being triggered).
- if (Event.current.isKey)
- Event.current.Use();
- }
- }
-
- internal override string DrawSearchFieldControl(string searchString)
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- var isListening = false;
-
- // When picking controls, have a "Listen" button that allows listening for input.
- if (m_Owner.m_Mode == InputControlPicker.Mode.PickControl)
- {
- using (new EditorGUILayout.VerticalScope(GUILayout.MaxWidth(50)))
- {
- GUILayout.Space(4);
- var isListeningOld = m_Owner.isListening;
- var isListeningNew = GUILayout.Toggle(isListeningOld, "Listen",
- EditorStyles.miniButton, GUILayout.MaxWidth(50));
-
- if (isListeningOld != isListeningNew)
- {
- if (isListeningNew)
- {
- m_Owner.StartListening();
- }
- else
- {
- m_Owner.StopListening();
- searchString = string.Empty;
- }
- }
-
- isListening = isListeningNew;
- }
- }
-
- ////FIXME: the search box doesn't clear out when listening; no idea why the new string isn't taking effect
- EditorGUI.BeginDisabledGroup(isListening);
- var newSearchString = base.DrawSearchFieldControl(isListening ? string.Empty : searchString);
- EditorGUI.EndDisabledGroup();
-
- if (isListening)
- {
- var rebind = m_Owner.m_RebindingOperation;
- return "\u0017" + string.Join("\u0017",
- rebind.candidates.SelectMany(x => GeneratePossiblePathsForControl(x).Reverse()));
- }
-
- return newSearchString;
- }
- }
-
- internal override void DrawItem(AdvancedDropdownItem item, string name, Texture2D icon, bool enabled,
- bool drawArrow, bool selected, bool hasSearch, bool richText = false)
- {
- if (hasSearch && item is InputControlDropdownItem viewItem)
- name = viewItem.searchableName;
-
- base.DrawItem(item, name, icon, enabled, drawArrow, selected, hasSearch);
- }
-
- internal override void DrawFooter(AdvancedDropdownItem selectedItem)
- {
- //dun work because there is no selection
- if (selectedItem is ControlDropdownItem controlItem)
- {
- var content = new GUIContent(controlItem.controlPath);
- var rect = GUILayoutUtility.GetRect(content, headerStyle, GUILayout.ExpandWidth(true));
- EditorGUI.TextField(rect, controlItem.controlPath, headerStyle);
- }
- }
- }
-
- private static class Styles
- {
- public static readonly GUIStyle waitingForInputLabel = new GUIStyle("WhiteBoldLabel").WithFontSize(22);
- }
- }
- }
- #endif // UNITY_EDITOR
|