Skip to content

Instantly share code, notes, and snippets.

@cdr9042
Created May 8, 2024 06:47
Show Gist options
  • Save cdr9042/a8b89bb9c7b5ca309b3b6ad770f8a03e to your computer and use it in GitHub Desktop.
Save cdr9042/a8b89bb9c7b5ca309b3b6ad770f8a03e to your computer and use it in GitHub Desktop.
Use SearchablePopupContent to show a popup with a search field input, a TreeView containing the options will be populated using parameter string[] data. Example of usage is in RoadSegmentDataDrawer.
using JacatGames.ShapeShifting;
using UnityEditor;
using UnityEngine;
namespace JacatGames.ShapeShifting
{
[CustomPropertyDrawer(typeof(RoadSegmentData))]
public class RoadSegmentDataDrawer : PropertyDrawer
{
// You can define your dropdown options here
private string[] _dropdownOptions;
private string[] DropdownOptions
{
get
{
if (_dropdownOptions == null)
{
_dropdownOptions = StageSetupConfig.GetConfig().SegmentsId.ToArray();
}
return _dropdownOptions;
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
// Drawing the label
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
// Getting the 'Id' property
SerializedProperty idProperty = property.FindPropertyRelative("_id");
// Checking if the property is null
if (idProperty != null)
{
if (GUI.Button(position, idProperty.stringValue))
{
PopupWindow.Show(position, new SearchablePopupContent(idProperty, DropdownOptions));
}
}
EditorGUI.EndProperty();
}
}
}
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
public class SearchablePopupContent : PopupWindowContent
{
private SerializedProperty property;
private SearchField searchField;
private MyTreeView treeView;
private List<string> data;
private bool focused;
public SearchablePopupContent(SerializedProperty property, string[] data)
{
this.property = property;
this.data = data.ToList();
searchField = new SearchField();
treeView = new MyTreeView(new TreeViewState(), this.data, property, this);
treeView.Reload();
searchField.SetFocus();
searchField.downOrUpArrowKeyPressed += OnArrowKeyPressed;
}
private void OnArrowKeyPressed()
{
treeView.SetFocusAndEnsureSelectedItem();
}
public override void OnGUI(Rect rect)
{
Rect searchRect = new Rect(rect.x, rect.y, rect.width, 25);
treeView.searchString = searchField.OnGUI(searchRect, treeView.searchString);
Rect treeViewRect = new Rect(rect.x, rect.y + 25, rect.width, rect.height - 25);
treeView.OnGUI(treeViewRect);
if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.Return)
{
treeView.SelectItem(0);
}
}
private class MyTreeView : TreeView
{
private List<string> data;
private SerializedProperty property;
private PopupWindowContent parentWindow;
private IList<TreeViewItem> filteredItems;
public MyTreeView(TreeViewState state, List<string> data, SerializedProperty property, PopupWindowContent parentWindow) :
base(state)
{
this.data = data;
this.property = property;
this.parentWindow = parentWindow;
}
protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
{
filteredItems = new List<TreeViewItem>();
for (int i = 0; i < data.Count; i++)
{
if (string.IsNullOrEmpty(searchString) || data[i].Contains(searchString))
{
filteredItems.Add(new TreeViewItem { id = i, depth = 1, displayName = data[i] });
}
}
SetupParentsAndChildrenFromDepths(root, filteredItems);
return filteredItems;
}
protected override void SingleClickedItem(int id)
{
base.SingleClickedItem(id);
SelectItem(id);
// var item = FindItem(id, rootItem);
// OnSelectItem(item.displayName);
}
protected override TreeViewItem BuildRoot()
{
var root = new TreeViewItem { id = 0, depth = -1, displayName = data[0] };
var allItems = new List<TreeViewItem>();
for (int i = 0; i < data.Count; i++)
{
allItems.Add(new TreeViewItem { id = i + 1, depth = 0, displayName = data[i] });
}
SetupParentsAndChildrenFromDepths(root, allItems);
return root;
}
public override void OnGUI(Rect rect)
{
base.OnGUI(rect);
if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return)
{
// Set the value of the property when the Return key is pressed
var selecteds = (IEnumerable<int>)GetSelection();
if (selecteds.Count() > 0)
{
int id = selecteds.First();
SelectItem(id);
}
}
}
public void SelectItem(int id)
{
// Debug.Log($"selecting:{id}");
var item = FindItem(id, rootItem);
// var item = filteredItems[id];
// Debug.Log($"selected:{item.displayName}");
OnSelectItem(item.displayName);
}
void OnSelectItem(string value)
{
property.stringValue = value;
property.serializedObject.ApplyModifiedProperties();
parentWindow.editorWindow.Close();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment