{"id":31578389,"url":"https://github.com/b3x206/bxsearchdropdown","last_synced_at":"2026-05-17T00:32:19.447Z","repository":{"id":317580465,"uuid":"1066664231","full_name":"b3x206/BXSearchDropdown","owner":"b3x206","description":"A faster alternative to AdvancedDropdown for Unity IMGUI","archived":false,"fork":false,"pushed_at":"2025-10-01T18:44:28.000Z","size":1446,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-01T20:38:17.045Z","etag":null,"topics":["ui","unity","unity3d-editor"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b3x206.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-29T19:46:12.000Z","updated_at":"2025-10-01T18:44:31.000Z","dependencies_parsed_at":"2025-10-01T20:38:18.481Z","dependency_job_id":null,"html_url":"https://github.com/b3x206/BXSearchDropdown","commit_stats":null,"previous_names":["b3x206/bxsearchdropdown"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/b3x206/BXSearchDropdown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3x206%2FBXSearchDropdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3x206%2FBXSearchDropdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3x206%2FBXSearchDropdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3x206%2FBXSearchDropdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b3x206","download_url":"https://codeload.github.com/b3x206/BXSearchDropdown/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3x206%2FBXSearchDropdown/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278510917,"owners_count":25998997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ui","unity","unity3d-editor"],"created_at":"2025-10-05T19:57:33.072Z","updated_at":"2025-10-05T19:57:35.358Z","avatar_url":"https://github.com/b3x206.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BXSearchDropdown\n\nThis is an unity engine extension that adds an IMGUI utility, which is an alternative to `UnityEditor.IMGUI.Controls.AdvancedDropdown`\n\nFeatures:\n* Async searching, typing a query doesn't block the main editor thread.\n* Basic string normalization and result sorting.\n* Override GUI behavior and bind extra data per `SearchDropdownElement`\n* Faster and more modular\n\n### Compatibility\nWorks with Unity Version **\u003e=2021.3**. \u003cbr/\u003e\nPlease note that some versions of **Unity 6** may have bugs related to IMGUI (such as **0.52f**). If you encounter this, please downgrade or upgrade to a version that works.\n\n## Demo\n\n**TypeSelectorDropdown** \u003cbr/\u003e\n![](https://github.com/b3x206/BXSearchDropdown/blob/resource/Resources/typeselector.png?raw=true)\n\n**KeyCodeSelectorDropdown** (with a query showing the sorting) \u003cbr/\u003e\n![](https://github.com/b3x206/BXSearchDropdown/blob/resource/Resources/keycodeselector.png?raw=true)\n\n**Compared to normal dropdown** \u003cbr/\u003e\n![](https://github.com/b3x206/BXSearchDropdown/blob/resource/Resources/vsnormal.gif?raw=true)\n\n**Compared to `AdvancedDropdown`** (on many elements/items) \u003cbr/\u003e\n\u003csub\u003ethe delay on the `BXSearchDropdown` at start is me thinking what to query\u003c/sub\u003e\n![](https://github.com/b3x206/BXSearchDropdown/blob/resource/Resources/vsadvanced.gif?raw=true)\n\n**Ease Selector^** \u003cbr/\u003e\n![](https://github.com/b3x206/BXSearchDropdown/blob/resource/Resources/easeselector.gif?raw=true)\n^ to get the plotting GUI for the ease selector, you can use this gist: https://gist.github.com/b3x206/9f2373d080353ea03d178afaac639cac\n\n## Basic Usage\nYou can replicate or inspect these code snippets to get started:\n\n### ./Scripts/Editor/ExampleDropdown.cs\n```cs\n// Assembly-CSharp-Editor\nusing BX.Editor;\nusing System;\n\npublic class ExampleDropdown\u003cT\u003e : SearchDropdown\u003cT\u003e where T : ISearchDropdownWindow, new()\n{\n    // Alternatively, you can create your own inheriting class to bind extra data to your Element\n    public class Item : SearchDropdownElement\n    {\n        // Though a constructor definition (to call any of the base constructor with string) is necessary.\n        public readonly float extraData;\n\n        public Item(float extraData) : base($\"{extraData} \u003ccolor=#a8d799\u003e | {(BitConverter.SingleToInt32Bits(extraData)):X}\u003c/color\u003e\")\n        {\n            this.extraData = extraData;\n        }\n        public Item(float extraData, string label) : base(label)\n        {\n            this.extraData = extraData;\n        }\n    }\n\n    public override bool AllowRichText =\u003e true;\n\n    protected override SearchDropdownElement BuildRoot()\n    {\n        // Create a root element to return\n        // Other elements are to be attached to this root\n        SearchDropdownElement root = new SearchDropdownElement(\"Root Element\")\n        {\n            // Any element can be started as a c# collection\n            new SearchDropdownElement(\"Child 1\"),\n            new SearchDropdownElement(\"Child 2\")\n            {\n                new Item(9f + 10f, \"21\"),\n                new Item(float.MaxValue)\n            },\n            new SearchDropdownElement(\"Child 3\")\n            {\n                // Every child can have it's own values and so on...\n                new SearchDropdownElement(\"Child Of Child 1\"),\n                new SearchDropdownElement(\"Child Of Child 2\")\n                {\n                    new Item(42.0f, \"Value of 42\"),\n                    new Item(float.Epsilon)\n                }\n            }\n        };\n        // The children can be also systematically be added using SearchDropdownElement.Add()\n        // Basically a 'SearchDropdownElement' is an ICollection of 'SearchDropdownElement'\n        // Which technically is a tree data type. (or not, you are reading the sample written by the guy who failed DSA after all)\n\n        // Return the root after creating it, this is required as a part of the abstract class 'SearchDropdown'.\n        return root;\n    }\n}\n```\n\n### ./Scripts/SampleClass.cs\n```cs\n// Assembly-CSharp\nusing UnityEngine;\n\npublic class SampleClass : MonoBehaviour\n{\n    public string dropdownSettingString;\n}\n```\n\n### ./Scripts/Editor/SampleClassEditor.cs\n```cs\n// Assembly-CSharp-Editor\nusing UnityEngine;\nusing UnityEditor;\nusing BX.Editor;\n\n[CustomEditor(typeof(SampleClass))]\npublic class SampleClassEditor : Editor\n{\n    // Unity gives a dummy rect on the Event.current.type == EventType.Layout\n    private Rect lastRepaintDropdownParentRect;\n\n    public override void OnInspectorGUI()\n    {\n        var target = base.target as SampleClass;    \n\n        // Draw the private 'm_Script' field (optional)\n        using (EditorGUI.DisabledScope scope = new EditorGUI.DisabledScope(true))\n        {\n            EditorGUILayout.PropertyField(serializedObject.FindProperty(\"m_Script\"));\n        }\n        \n        // Draw the dropdown button\n        EditorGUILayout.BeginHorizontal();\n        EditorGUILayout.LabelField(\"Dropdown Setting String\", GUILayout.Width(EditorGUIUtility.labelWidth));\n        if (GUILayout.Button($\"Value : {target.dropdownSettingString}\", EditorStyles.popup))\n        {\n            ExampleDropdown\u003cUGUISearchDropdownWindow\u003e dropdown = new();\n            dropdown.Show(lastRepaintDropdownParentRect);\n            dropdown.OnElementSelected += (SearchDropdownElement element) =\u003e\n            {\n                // Will not take a 'SerializedProperty' inside a delegate\n                // Because SerializedObject and SerializedProperty disposes automatically after the OnGUI call\n                // But you can clone the entire SerializedObject and SerializedProperty just for this delegate, \n                // then apply changed values and dispose of it inside this delegate when done (manually managing it's lifetime)\n                // -- \n                // For this example, a basic undo with direct access to the object is used\n                Undo.RecordObject(target, \"set value from dropdown\");\n                // You can create custom Element/Item classes that inherit from 'SearchDropdownElement' and type test it to get it's values.\n                // With this, you can test/unbox the type like `if (element is ExampleDropdown\u003cUGUISearchDropdownWindow\u003e.Item item)` and get the extra data.\n                // For now we are just assigning the content text set to the element for simplicity.\n                target.dropdownSettingString = element.content.Text;\n            };\n        }\n        // Get the last rect for getting the proper value\n        // This is only needed on automatically layouted GUI's, with the GUI's\n        // that you know the rect to you can use that rect instead.\n        // (as the rect of GetLastRect() becomes `Rect.kDummyRect` during certain events that trigger the dropdown)\n        if (Event.current.type == EventType.Repaint)\n        {\n            lastRepaintDropdownParentRect = GUILayoutUtility.GetLastRect();\n        }\n        EditorGUILayout.EndHorizontal();\n    }\n}\n```\n\n---\nYou can also optionally create an attribute + `CustomPropertyDrawer` for the dropdown:\n\n### ./Scripts/SampleTargetAttribute.cs\n```cs\nusing System;\nusing UnityEngine;\n\n[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]\npublic class SampleTargetAttribute : PropertyAttribute { }\n```\n\n### ./Scripts/Editor/SampleTargetPropertyDrawer.cs\n```cs\nusing UnityEditor;\nusing UnityEngine;\nusing BX.Editor;\n\n[CustomPropertyDrawer(typeof(SampleTargetAttribute))]\npublic class SampleTargetPropertyDrawer : PropertyDrawer\n{\n    private const float WarningBoxHeight = 22f;\n    private const float YMargin = 2f;\n    private bool propertyTypeIsValid = false;\n\n    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)\n    {\n        float addHeight = 0f;\n\n        propertyTypeIsValid = property.propertyType == SerializedPropertyType.String;\n        addHeight += propertyTypeIsValid ? (EditorGUIUtility.singleLineHeight + YMargin) : WarningBoxHeight;\n\n        return addHeight;\n    }\n\n    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)\n    {\n        label = EditorGUI.BeginProperty(position, label, property);\n        position.height -= YMargin;\n        position.y += YMargin / 2f;\n\n        if (propertyTypeIsValid)\n        {\n            string value = property.stringValue;\n\n            // Draw a dropdown selector with label\n            // Label\n            Rect labelRect = new Rect(position.x, position.y + (YMargin / 2f), EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight);\n            EditorGUI.LabelField(labelRect, label);\n\n            // Dropdown\n            bool previousShowMixed = EditorGUI.showMixedValue;\n            EditorGUI.showMixedValue = property.hasMultipleDifferentValues;\n            // Adding margin to the 'dropdownRect's y coordinate causes it to be off center on DropdownButton\n            Rect dropdownRect = new Rect(position.x + labelRect.width, position.y, Mathf.Max(position.width - labelRect.width, EditorGUIUtility.fieldWidth), EditorGUIUtility.singleLineHeight);\n            if (EditorGUI.DropdownButton(dropdownRect, new GUIContent(value, label.tooltip), FocusType.Keyboard))\n            {\n                // Display a 'KeyCode' selector\n                ExampleDropdown\u003cUGUISearchDropdownWindow\u003e selector = new();\n                selector.Show(dropdownRect);\n\n                SerializedObject copySo = new SerializedObject(property.serializedObject.targetObjects);\n                SerializedProperty copySetProperty = copySo.FindProperty(property.propertyPath);\n                selector.OnElementSelected += (SearchDropdownElement element) =\u003e\n                {\n                    copySetProperty.stringValue = element.content.Text;\n                    copySo.ApplyModifiedProperties();\n\n                    copySetProperty.Dispose();\n                    copySo.Dispose();\n                };\n                selector.OnDiscard += () =\u003e\n                {\n                    copySetProperty.Dispose();\n                    copySo.Dispose();\n                };\n            }\n            EditorGUI.showMixedValue = previousShowMixed;\n        }\n        else\n        {\n            EditorGUI.HelpBox(position, \"Type isn't valid. Please use this on `string` fields.\", MessageType.Warning);\n        }\n\n        EditorGUI.EndProperty();\n    }\n}\n```\nAnd then apply to any field with type `string` to display the `SampleDropdown\u003cT\u003e` that we have made.\n### ./Scripts/SampleClassFieldAttr.cs\n```cs\nusing UnityEngine;\n\npublic class SampleClassFieldAttr : MonoBehaviour\n{\n    [SampleTarget] public string dropdownSettingString;\n}\n```\n\nFor more examples, check [the Dropdown directory](./Dropdown/)\n\n## TODO\n* [ ] Allow adding of extra GUI/callback on the header/post draw list\n* [ ] Decouple the backing API to not rely on `UnityEditor` namespace (+ allow assembly to build on any platform)\n* [ ] Decouple the backing API to not rely on `UnityEngine` namespace\n* [ ] Other `SearchDropdownWindow` versions for other frameworks\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb3x206%2Fbxsearchdropdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb3x206%2Fbxsearchdropdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb3x206%2Fbxsearchdropdown/lists"}