我需要一个列表,列表很多(枚举列表)。现在列表正在使用弹出窗口(组合框),但正常的组合框并没有真正帮助,因为它内部的项目太多了。当尝试选择远离底部的物品时,这有点令人沮丧。打开时,屏幕上的列表已满。
当打开一个组合框并输入一个字母时,它只会跳第一个字母,当我按下第二个字母时,列表将跳转到另一个第一个字母开头。例如,我想选择DIAMOND - >我按D键,它将以D开始进入列表。当我按下I时,它将跳转到以I开头而不是DI的项目。
是否有任何GUI组件可以进行搜索?
答案 0 :(得分:4)
Unity没有像您这样的搜索组件。
但你可以尝试这样的事情(SearchEnumLabel
函数):
using System;
using System.Globalization;
using System.Linq;
using UnityEditor;
public enum States
{
ABCDEF,
ACBDEF,
AdEXG,
bErDSa
}
[CustomEditor(typeof(ObjectControllerTester))]
[CanEditMultipleObjects]
public class ObjectControllerTesterEditor : Editor
{
States _selected;
public override void OnInspectorGUI ()
{
_selected = SearchEnumLabel("My search enum", _selected);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("[Debug]Current selected: "+_selected);
}
private String _searchEnumText = "";
private bool _isSearchEnumLabelInSearch = false;
private T SearchEnumLabel<T>(String label, T state) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
EditorGUILayout.LabelField("T must be an enumerated type");
return state;
}
var states = Enum.GetValues(typeof (T)).Cast<object>().Select(o => o.ToString()).ToArray();
if (string.IsNullOrEmpty(_searchEnumText) && states.Length > 0) _searchEnumText = state.ToString(CultureInfo.InvariantCulture);
var text = EditorGUILayout.TextField(label, _searchEnumText);
if (text != _searchEnumText || _isSearchEnumLabelInSearch)
{
_searchEnumText = text;
var mach = states.Select((v,i)=>new {value = v, index = i}).FirstOrDefault(a => a.value.ToLower().StartsWith(text.ToLower()));
var targetState = state;
if (mach != null) targetState = (T) Enum.GetValues(typeof (T)).GetValue(mach.index);
EditorGUILayout.LabelField("Select closest: "+targetState);
Repaint();
state = targetState;
_isSearchEnumLabelInSearch = !string.Equals(_searchEnumText, targetState.ToString(CultureInfo.InvariantCulture), StringComparison.CurrentCultureIgnoreCase);
}
return state;
}
}
此脚本将显示如下内容:
默认视图
输入一些数据后
===更新===
具有快速选择按钮的更复杂变体
using System;
using System.Globalization;
using System.Linq;
using UnityEditor;
using UnityEngine;
public enum States
{
ABCDEF,
ACBDEF,
AdEXG,
bErDSa,
sEOjsfl,
SdDiaso,
POsdjaow,
PSADJsd,
Oasdo,
IOQWEnds
}
[CustomEditor(typeof(ObjectControllerTester))]
[CanEditMultipleObjects]
public class ObjectControllerTesterEditor : Editor
{
States _selected;
public override void OnInspectorGUI()
{
_selected = SearchEnumLabel("My search enum", _selected);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("[Debug]Current selected: " + _selected);
}
private String _searchEnumText = "";
private bool _isSearchEnumLabelInSearch = false;
private T SearchEnumLabel<T>(String label, T state) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
EditorGUILayout.LabelField("T must be an enumerated type");
return state;
}
var states = Enum.GetValues(typeof(T)).Cast<object>().Select(o => o.ToString()).ToArray();
if (string.IsNullOrEmpty(_searchEnumText) && states.Length > 0) _searchEnumText = state.ToString(CultureInfo.InvariantCulture);
var text = EditorGUILayout.TextField(label, _searchEnumText);
if (text != _searchEnumText || _isSearchEnumLabelInSearch)
{
_searchEnumText = text;
var mach = states.Select((v, i) => new { value = v, index = i }).Where(a => a.value.ToLower().StartsWith(text.ToLower())).ToList();
var targetState = state;
if (mach.Any())
{
// many of results
targetState = (T)Enum.GetValues(typeof(T)).GetValue(mach[0].index);
EditorGUILayout.LabelField("Select closested: " + targetState);
Repaint();
var selected = GUILayout.SelectionGrid(-1, mach.Select(v => v.value).ToArray(), 4);
if (selected != -1)
{
targetState = (T)Enum.GetValues(typeof(T)).GetValue(mach[selected].index);
_searchEnumText = targetState.ToString(CultureInfo.InvariantCulture);
_isSearchEnumLabelInSearch = false;
GUI.FocusControl("FocusAway");
Repaint();
}
}
state = targetState;
_isSearchEnumLabelInSearch = !string.Equals(_searchEnumText, targetState.ToString(CultureInfo.InvariantCulture), StringComparison.CurrentCultureIgnoreCase);
}
return state;
}
}
答案 1 :(得分:1)
这是我的解决方案,您可以根据需要更换“EnumNBEvent”。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Newborn.Pb.Event;
using System;
using System.Reflection;
using Google.Protobuf.Reflection;
using System.Text.RegularExpressions;
[CustomPropertyDrawer(typeof(EnumNBEvent), false)]
public class FSMEventDrawer : PropertyDrawer {
struct EnumStringValuePair : IComparable<EnumStringValuePair>
{
public string strValue;
public int intValue;
public int CompareTo(EnumStringValuePair another)
{
if (intValue < another.intValue)
return -1;
else if (intValue > another.intValue)
return 1;
return 0;
}
}
Dictionary<int, string> filters = new Dictionary<int, string>();
//string filter = string.Empty;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
int y = (int)position.position.y;
if (!filters.ContainsKey(y))
filters[y] = string.Empty;
EditorGUI.BeginProperty(position, label, property);
EditorGUI.LabelField(new Rect(position.x, position.y, 100, 20), property.name);
filters[y] = EditorGUI.TextField(new Rect(position.x + 100, position.y, 60, 15), filters[y]);
List<EnumStringValuePair> enumList = GetEnumList(filters[y]);
List<string> enumStrList = new List<string>(enumList.Count);
for (int i = 0; i < enumList.Count; ++i)
{
enumStrList.Add(enumList[i].strValue);
}
int selectedIndex = 0;
for (int i = 0; i < enumList.Count; ++i)
{
if (enumList[i].intValue == property.enumValueIndex)
{
selectedIndex = i;
break;
}
}
selectedIndex = EditorGUI.Popup(new Rect(position.x + 170, position.y, 200, 20), selectedIndex, enumStrList.ToArray());
if (enumList.Count > selectedIndex)
{
property.enumValueIndex = enumList[selectedIndex].intValue;
}
EditorGUI.EndProperty();
}
private List<EnumStringValuePair> GetEnumList(string filter)
{
List<EnumStringValuePair> allList = new List<EnumStringValuePair>();
Array enumValues = Enum.GetValues(typeof(EnumNBEvent));
for (int i = 0; i < enumValues.Length; ++i)
{
EnumStringValuePair pair = new EnumStringValuePair();
pair.strValue = enumValues.GetValue(i).ToString();
pair.intValue = (int)enumValues.GetValue(i);
allList.Add(pair);
}
List<EnumStringValuePair> ret = new List<EnumStringValuePair>();
Regex regex = new Regex(filter.ToLower());
for (int i = 0; i < allList.Count; ++i)
{
if (regex.IsMatch(allList[i].strValue.ToLower()))
{
ret.Add(allList[i]);
}
}
return ret;
}
}