com.alicizax.unity.framework/Editor/UI/GenerateWindow/UISettingEditorWindow.cs

629 lines
25 KiB
C#
Raw Normal View History

2025-11-07 20:47:57 +08:00
using System;
2025-09-05 19:46:30 +08:00
using System.Collections.Generic;
2025-11-07 20:47:57 +08:00
using System.IO;
using System.Linq;
using AlicizaX.UI.Runtime;
2025-09-05 19:46:30 +08:00
using Newtonsoft.Json;
using UnityEditor;
2025-11-07 20:47:57 +08:00
using UnityEditorInternal;
2025-09-05 19:46:30 +08:00
using UnityEngine;
namespace AlicizaX.UI.Editor
{
2025-11-07 20:47:57 +08:00
public class UISettingEditorWindow_NoOdin_v2 : EditorWindow
2025-09-05 19:46:30 +08:00
{
2025-11-07 20:47:57 +08:00
[MenuItem("Tools/AlicizaX/UISetting Window")]
2025-09-05 19:46:30 +08:00
private static void OpenWindow()
{
2025-11-07 20:47:57 +08:00
var w = GetWindow<UISettingEditorWindow_NoOdin_v2>("UI Setting");
w.minSize = new Vector2(760, 520);
w.Show();
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private UIGenerateConfiguration uiGenerateConfiguration;
private UIGenerateCommonData UIGenerateCommonData;
private List<UIEelementRegexData> UIElementRegexConfigs;
private List<UIScriptGenerateData> UIScriptGenerateConfigs;
private List<string> excludeKeywordsList = new List<string>();
private Vector2 scroll;
private int toolbarTab;
private readonly string[] toolbarTitles = { "UI基础设置", "UI构建配置", "UI元素映射" };
private ReorderableList regexList;
private ReorderableList projectList;
private ReorderableList excludeList;
private TextAsset importText;
private string previewLabel;
private string previewCompLabel;
private List<string> m_ScriptGeneratorHelperTypes = new();
private int m_ScriptGeneratorHelperSelectIndex;
private void OnEnable()
2025-09-05 19:46:30 +08:00
{
uiGenerateConfiguration = UIGenerateConfiguration.Instance;
2025-11-07 20:47:57 +08:00
if (uiGenerateConfiguration == null)
{
uiGenerateConfiguration = ScriptableObject.CreateInstance<UIGenerateConfiguration>();
}
UIGenerateCommonData = uiGenerateConfiguration.UIGenerateCommonData ?? new UIGenerateCommonData();
UIElementRegexConfigs = uiGenerateConfiguration.UIElementRegexConfigs ?? new List<UIEelementRegexData>();
UIScriptGenerateConfigs = uiGenerateConfiguration.UIScriptGenerateConfigs ?? new List<UIScriptGenerateData>();
excludeKeywordsList = (UIGenerateCommonData.ExcludeKeywords ?? new string[0]).ToList();
SetupLists();
2025-09-05 19:46:30 +08:00
RefreshLabel();
2025-11-07 20:47:57 +08:00
RefreshScriptGeneratorHelperTypes();
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private void SetupLists()
{
2025-09-05 19:46:30 +08:00
2025-11-07 20:47:57 +08:00
excludeList = new ReorderableList(excludeKeywordsList, typeof(string), true, true, true, true);
excludeList.drawHeaderCallback = (r) => EditorGUI.LabelField(r, "排除关键字(匹配则不生成)");
excludeList.drawElementCallback = (rect, index, active, focused) =>
{
rect.y += 2;
excludeKeywordsList[index] = EditorGUI.TextField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), excludeKeywordsList[index]);
};
excludeList.onAddCallback = (r) => excludeKeywordsList.Add(string.Empty);
excludeList.onRemoveCallback = (r) =>
{
if (r.index >= 0) excludeKeywordsList.RemoveAt(r.index);
};
2025-09-05 19:46:30 +08:00
2025-11-07 20:47:57 +08:00
regexList = new ReorderableList(UIElementRegexConfigs, typeof(UIEelementRegexData), true, true, true, true);
regexList.drawHeaderCallback = (r) => EditorGUI.LabelField(r, "UI元素映射 (正则 -> 组件)");
regexList.elementHeightCallback = (i) => EditorGUIUtility.singleLineHeight * 2 + 8;
regexList.drawElementCallback = (rect, index, active, focused) =>
{
var item = UIElementRegexConfigs[index];
rect.y += 2;
float lh = EditorGUIUtility.singleLineHeight;
2025-09-05 19:46:30 +08:00
2025-11-07 20:47:57 +08:00
EditorGUI.BeginChangeCheck();
item.uiElementRegex = EditorGUI.TextField(new Rect(rect.x + 70, rect.y, rect.width - 70, lh), item.uiElementRegex);
if (EditorGUI.EndChangeCheck()) RefreshLabel();
2025-09-05 19:46:30 +08:00
2025-11-07 20:47:57 +08:00
EditorGUI.LabelField(new Rect(rect.x, rect.y + lh + 4, 60, lh), "Component");
var btnRect = new Rect(rect.x + 70, rect.y + lh + 4, 180, lh);
string btnLabel = string.IsNullOrEmpty(item.componentType) ? "(选择类型)" : item.componentType;
if (GUI.Button(btnRect, btnLabel, EditorStyles.popup))
{
var opts = CollectComponentTypeNamesFallback();
Rect anchor = new Rect(btnRect.x, btnRect.y + btnRect.height, Math.Min(360f, Mathf.Max(btnRect.width, 200f)), btnRect.height);
SearchablePopup.Show(anchor, opts, Math.Max(0, opts.IndexOf(item.componentType)), (selIndex) =>
{
if (selIndex >= 0 && selIndex < opts.Count)
{
item.componentType = opts[selIndex];
Repaint();
}
});
}
item.componentType = EditorGUI.TextField(new Rect(rect.x + 260, rect.y + lh + 4, rect.width - 260, lh), item.componentType);
};
regexList.onAddCallback = (r) => UIElementRegexConfigs.Add(new UIEelementRegexData { uiElementRegex = "", componentType = "" });
regexList.onRemoveCallback = (r) =>
{
if (r.index >= 0) UIElementRegexConfigs.RemoveAt(r.index);
};
projectList = new ReorderableList(UIScriptGenerateConfigs, typeof(UIScriptGenerateData), true, true, true, true);
projectList.drawHeaderCallback = (r) => EditorGUI.LabelField(r, "UI脚本生成配置多个项目");
projectList.elementHeightCallback = (i) => EditorGUIUtility.singleLineHeight * 5 + 10;
projectList.drawElementCallback = (rect, index, active, focused) =>
{
var d = UIScriptGenerateConfigs[index];
float lh = EditorGUIUtility.singleLineHeight;
float pad = 2;
d.ProjectName = EditorGUI.TextField(new Rect(rect.x, rect.y, rect.width, lh), "项目名", d.ProjectName);
d.NameSpace = EditorGUI.TextField(new Rect(rect.x, rect.y + (lh + pad), rect.width, lh), "命名空间", d.NameSpace);
d.GenerateHolderCodePath = DrawFolderField("生成脚本路径", d.GenerateHolderCodePath, rect.x, rect.y + 2 * (lh + pad), rect.width, lh);
d.UIPrefabRootPath = DrawFolderField("Prefab根目录", d.UIPrefabRootPath, rect.x, rect.y + 3 * (lh + pad), rect.width, lh);
d.LoadType = (EUIResLoadType)EditorGUI.EnumPopup(new Rect(rect.x, rect.y + 4 * (lh + pad), rect.width, lh), "加载类型", d.LoadType);
};
2025-11-10 16:01:53 +08:00
projectList.onAddCallback = (r) => UIScriptGenerateConfigs.Add(new UIScriptGenerateData { ProjectName = "NewProject", NameSpace = "Game.UI", GenerateHolderCodePath = "Assets/Scripts/UI/Generated", UIPrefabRootPath = "Assets/Resources/UI", LoadType = EUIResLoadType.Resources });
2025-11-07 20:47:57 +08:00
projectList.onRemoveCallback = (r) =>
{
if (r.index >= 0) UIScriptGenerateConfigs.RemoveAt(r.index);
};
}
private string DrawFolderField(string label, string value, float x, float y, float width, float h)
2025-09-05 19:46:30 +08:00
{
2025-11-07 20:47:57 +08:00
var txtRect = new Rect(x, y, width - 76, h);
var btnRect = new Rect(x + width - 72, y, 68, h);
value = EditorGUI.TextField(txtRect, label, value);
if (GUI.Button(btnRect, "选择"))
{
string p = EditorUtility.OpenFolderPanel("选择路径", Application.dataPath, "");
if (!string.IsNullOrEmpty(p))
{
if (p.StartsWith(Application.dataPath))
value = "Assets" + p.Substring(Application.dataPath.Length);
else
EditorUtility.DisplayDialog("提示", "请选择 Assets 下的路径", "确定");
}
}
return value;
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private void RefreshScriptGeneratorHelperTypes()
2025-09-05 19:46:30 +08:00
{
2025-11-07 20:47:57 +08:00
m_ScriptGeneratorHelperTypes = new List<string>();
2025-11-10 16:01:53 +08:00
m_ScriptGeneratorHelperTypes.AddRange(AlicizaX.Utility.Assembly.GetRuntimeTypeNames(typeof(IUIGeneratorRuleHelper)));
2025-11-07 20:47:57 +08:00
2025-11-10 16:01:53 +08:00
m_ScriptGeneratorHelperSelectIndex = m_ScriptGeneratorHelperTypes.IndexOf(UIGenerateConfiguration.Instance.UIScriptGeneratorRuleHelper);
2025-11-07 20:47:57 +08:00
if (m_ScriptGeneratorHelperSelectIndex < 0)
{
m_ScriptGeneratorHelperSelectIndex = 0;
}
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private void OnGUI()
2025-09-05 19:46:30 +08:00
{
2025-11-07 20:47:57 +08:00
GUILayout.Space(6);
GUILayout.BeginHorizontal(EditorStyles.toolbar);
for (int i = 0; i < toolbarTitles.Length; i++)
{
bool isActive = (toolbarTab == i);
bool result = GUILayout.Toggle(isActive, toolbarTitles[i], EditorStyles.toolbarButton, GUILayout.Height(22));
if (result && toolbarTab != i)
{
toolbarTab = i;
Repaint();
}
}
GUILayout.FlexibleSpace();
var saveIcon = EditorGUIUtility.IconContent("SaveActive");
var refreshIcon = EditorGUIUtility.IconContent("Refresh");
var reloadIcon = EditorGUIUtility.IconContent("RotateTool");
GUIContent saveBtn = new GUIContent(saveIcon.image, "保存 (Save Now)");
GUIContent refreshBtn = new GUIContent(refreshIcon.image, "刷新预览");
GUIContent reloadBtn = new GUIContent(reloadIcon.image, "重载配置");
if (GUILayout.Button(saveBtn, EditorStyles.toolbarButton, GUILayout.Width(36)))
SaveConfig();
if (GUILayout.Button(refreshBtn, EditorStyles.toolbarButton, GUILayout.Width(36)))
RefreshLabel();
if (GUILayout.Button(reloadBtn, EditorStyles.toolbarButton, GUILayout.Width(36)))
{
OnEnable();
Repaint();
}
GUILayout.EndHorizontal();
scroll = EditorGUILayout.BeginScrollView(scroll);
GUILayout.Space(8);
switch (toolbarTab)
{
case 0: DrawCommonPane(); break;
case 1: DrawScriptPane(); break;
case 2: DrawElementPane(); break;
}
EditorGUILayout.EndScrollView();
GUILayout.Space(8);
}
private void DrawCommonPane()
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("通用生成配置", EditorStyles.boldLabel);
EditorGUILayout.Space(4);
EditorGUILayout.BeginVertical();
EditorGUI.BeginChangeCheck();
UIGenerateCommonData.ComCheckSplitName = EditorGUILayout.TextField(new GUIContent("组件检查分隔符", "例如 Button#Close"), UIGenerateCommonData.ComCheckSplitName);
UIGenerateCommonData.ComCheckEndName = EditorGUILayout.TextField(new GUIContent("组件结尾分隔符", "例如 @End"), UIGenerateCommonData.ComCheckEndName);
UIGenerateCommonData.ArrayComSplitName = EditorGUILayout.TextField(new GUIContent("数组组件分隔符", "例如 *Item"), UIGenerateCommonData.ArrayComSplitName);
UIGenerateCommonData.GeneratePrefix = EditorGUILayout.TextField(new GUIContent("生成脚本前缀"), UIGenerateCommonData.GeneratePrefix);
2025-11-12 17:48:41 +08:00
m_ScriptGeneratorHelperSelectIndex = EditorGUILayout.Popup("UI辅助生成", m_ScriptGeneratorHelperSelectIndex, m_ScriptGeneratorHelperTypes.ToArray());
2025-11-07 20:47:57 +08:00
string selectService = m_ScriptGeneratorHelperTypes[m_ScriptGeneratorHelperSelectIndex];
2025-11-10 16:01:53 +08:00
if (uiGenerateConfiguration.UIScriptGeneratorRuleHelper != selectService)
2025-11-07 20:47:57 +08:00
{
2025-11-10 16:01:53 +08:00
UIGenerateConfiguration.Instance.UIScriptGeneratorRuleHelper = selectService;
2025-11-07 20:47:57 +08:00
UIGenerateConfiguration.Save();
}
EditorGUILayout.EndVertical();
GUILayout.Space(8);
excludeList.DoLayoutList();
EditorGUILayout.Space(8);
EditorGUILayout.LabelField("脚本生成预览", EditorStyles.boldLabel);
EditorGUILayout.HelpBox(previewLabel ?? "", MessageType.None);
EditorGUILayout.LabelField("组件生成预览 (下标0开始)", EditorStyles.boldLabel);
EditorGUILayout.HelpBox(previewCompLabel ?? "", MessageType.None);
EditorGUILayout.EndVertical();
GUILayout.Space(8);
}
private void DrawScriptPane()
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("UI脚本生成配置支持多个项目", EditorStyles.boldLabel);
GUILayout.Space(6);
projectList.DoLayoutList();
EditorGUILayout.EndVertical();
GUILayout.Space(8);
}
private void DrawElementPane()
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("UI元素映射正则 -> 组件)", EditorStyles.boldLabel);
GUILayout.Space(6);
GUILayout.BeginHorizontal(EditorStyles.toolbar);
{
if (GUILayout.Button("加载默认", EditorStyles.toolbarButton, GUILayout.Width(90)))
LoadDefault();
if (GUILayout.Button("导出", EditorStyles.toolbarButton, GUILayout.Width(70)))
ExportConfig();
GUILayout.Space(8);
importText = (TextAsset)EditorGUILayout.ObjectField(importText, typeof(TextAsset), false, GUILayout.Height(18), GUILayout.MinWidth(200));
GUI.enabled = importText != null;
if (GUILayout.Button("执行导入", EditorStyles.toolbarButton, GUILayout.Width(84)))
{
if (importText != null)
{
ImportConfig(importText);
importText = null;
}
}
GUI.enabled = true;
GUILayout.FlexibleSpace();
}
GUILayout.EndHorizontal();
GUILayout.Space(6);
regexList.elementHeightCallback = (i) => EditorGUIUtility.singleLineHeight + 6;
regexList.drawElementCallback = (rect, index, active, focused) =>
{
if (index < 0 || index >= UIElementRegexConfigs.Count) return;
var item = UIElementRegexConfigs[index];
rect.y += 2;
float lh = EditorGUIUtility.singleLineHeight;
float padding = 6f;
float leftWidth = rect.width * 0.80f;
Rect regexRect = new Rect(rect.x, rect.y, leftWidth - 8, lh);
EditorGUI.BeginChangeCheck();
string newRegex = EditorGUI.TextField(regexRect, item.uiElementRegex);
if (EditorGUI.EndChangeCheck())
{
item.uiElementRegex = newRegex;
RefreshLabel();
}
float rightX = rect.x + leftWidth + 8;
float rightWidth = rect.width - leftWidth - 8;
Rect btnRect = new Rect(rightX, rect.y, Math.Min(180, rightWidth), lh);
string btnLabel = string.IsNullOrEmpty(item.componentType) ? "(选择类型)" : item.componentType;
if (GUI.Button(btnRect, btnLabel, EditorStyles.popup))
{
var opts = CollectComponentTypeNamesFallback();
Rect anchor = new Rect(btnRect.x, btnRect.y + btnRect.height, Math.Min(360f, Mathf.Max(btnRect.width, 200f)), btnRect.height);
SearchablePopup.Show(anchor, opts, Math.Max(0, opts.IndexOf(item.componentType)), (selIndex) =>
{
if (selIndex >= 0 && selIndex < opts.Count)
{
item.componentType = opts[selIndex];
Repaint();
}
});
}
};
regexList.DoLayoutList();
EditorGUILayout.EndVertical();
}
private static List<string> cacheFilterType;
private List<string> CollectComponentTypeNamesFallback()
{
if (cacheFilterType == null)
{
cacheFilterType = AlicizaX.Utility.Assembly.GetTypes()
.Where(m => !m.FullName.Contains("Editor"))
.Where(x => !x.IsAbstract || x.IsInterface)
.Where(x => !x.IsGenericTypeDefinition)
.Where(x => !x.IsSubclassOf(typeof(UIHolderObjectBase)))
.Where(x => x.IsSubclassOf(typeof(Component)))
.Where(x => !x.FullName.Contains("YooAsset"))
.Where(x => !x.FullName.Contains(("Unity.VisualScripting")))
.Where(x => !x.FullName.Contains(("Cysharp.Threading")))
.Where(x => !x.FullName.Contains(("UnityEngine.Rendering.UI.Debug")))
.Where(x => !x.FullName.Contains(("Unity.PerformanceTesting")))
.Where(x => !x.FullName.Contains(("UnityEngine.TestTools")))
.Select(x => x.Name).ToList();
cacheFilterType.Add(typeof(GameObject).Name);
}
return cacheFilterType;
}
private void LoadDefault()
{
string defaultPath = null;
try
{
var f = typeof(UIGlobalPath).GetField("DefaultComPath", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
if (f != null) defaultPath = f.GetValue(null) as string;
}
catch
{
}
if (string.IsNullOrEmpty(defaultPath)) defaultPath = "Assets/uielementconfig.txt";
if (!File.Exists(defaultPath))
{
EditorUtility.DisplayDialog("加载默认", $"未找到默认文件:{defaultPath}", "OK");
return;
}
string txt = File.ReadAllText(defaultPath);
var list = JsonConvert.DeserializeObject<List<UIEelementRegexData>>(txt);
if (list != null)
{
UIElementRegexConfigs = list;
regexList.list = UIElementRegexConfigs;
RefreshLabel();
}
2025-09-05 19:46:30 +08:00
}
private void ImportConfig(TextAsset text)
{
2025-11-07 20:47:57 +08:00
try
{
var list = JsonConvert.DeserializeObject<List<UIEelementRegexData>>(text.text);
if (list != null)
{
UIElementRegexConfigs = list;
regexList.list = UIElementRegexConfigs;
RefreshLabel();
}
}
catch (Exception ex)
{
Debug.LogException(ex);
EditorUtility.DisplayDialog("错误", "导入失败,请查看控制台", "OK");
}
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private void ExportConfig()
{
string json = JsonConvert.SerializeObject(UIElementRegexConfigs, Formatting.Indented);
string path = EditorUtility.SaveFilePanel("导出 UI 元素配置为 JSON", Application.dataPath, "uielementconfig", "txt");
if (!string.IsNullOrEmpty(path))
{
File.WriteAllText(path, json);
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("导出完成", "已导出", "OK");
}
}
2025-09-05 19:46:30 +08:00
2025-11-07 20:47:57 +08:00
private void RefreshLabel()
2025-09-05 19:46:30 +08:00
{
2025-11-07 20:47:57 +08:00
previewLabel = $"{UIGenerateCommonData.GeneratePrefix}_UITestWindow";
previewCompLabel = $"{UIGenerateCommonData.ArrayComSplitName}Text{UIGenerateCommonData.ComCheckSplitName}Img{UIGenerateCommonData.ComCheckEndName}Test{UIGenerateCommonData.ArrayComSplitName}0";
Repaint();
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private void SaveConfig()
2025-09-05 19:46:30 +08:00
{
2025-11-07 20:47:57 +08:00
UIGenerateCommonData.ExcludeKeywords = excludeKeywordsList.ToArray();
2025-09-05 19:46:30 +08:00
uiGenerateConfiguration.UIGenerateCommonData = UIGenerateCommonData;
uiGenerateConfiguration.UIElementRegexConfigs = UIElementRegexConfigs;
2025-11-07 20:47:57 +08:00
uiGenerateConfiguration.UIScriptGenerateConfigs = UIScriptGenerateConfigs;
2025-09-05 19:46:30 +08:00
UIGenerateConfiguration.Save();
2025-11-10 16:01:53 +08:00
Debug.Log("UIGenerateConfiguration Saved...");
2025-09-05 19:46:30 +08:00
}
2025-11-07 20:47:57 +08:00
private void OnDisable() => SaveConfig();
}
internal class SearchablePopup : PopupWindowContent
{
private readonly List<string> allItems;
private List<string> filtered;
private readonly Action<int> onSelect;
private int currentIndex;
private string search = "";
private Vector2 scroll;
private static GUIStyle searchFieldStyle;
private static GUIStyle cancelStyle;
private static GUIStyle rowStyle;
private static GUIStyle selectedRowStyle;
private const float ROW_HEIGHT = 20f;
private SearchablePopup(List<string> items, int currentIndex, Action<int> onSelect)
{
this.allItems = items ?? new List<string>();
this.filtered = new List<string>(this.allItems);
this.currentIndex = Mathf.Clamp(currentIndex, -1, this.allItems.Count - 1);
this.onSelect = onSelect;
}
public static void Show(Rect anchorRect, List<string> items, int currentIndex, Action<int> onSelect)
{
PopupWindow.Show(anchorRect, new SearchablePopup(items, currentIndex, onSelect));
}
public override Vector2 GetWindowSize() => new Vector2(360, 320);
public override void OnOpen()
{
EditorApplication.delayCall += () => EditorGUI.FocusTextInControl("SearchField");
}
public override void OnGUI(Rect rect)
{
InitStyles();
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
GUI.SetNextControlName("SearchField");
search = EditorGUILayout.TextField(search, searchFieldStyle, GUILayout.ExpandWidth(true));
if (GUILayout.Button("", cancelStyle, GUILayout.Width(18)))
{
search = "";
GUI.FocusControl("SearchField");
}
EditorGUILayout.EndHorizontal();
FilterList(search);
HandleKeyboard();
scroll = EditorGUILayout.BeginScrollView(scroll);
for (int i = 0; i < filtered.Count; i++)
{
bool selected = (i == currentIndex);
var style = selected ? selectedRowStyle : rowStyle;
Rect r = GUILayoutUtility.GetRect(new GUIContent(filtered[i]), style, GUILayout.Height(ROW_HEIGHT), GUILayout.ExpandWidth(true));
if (Event.current.type == EventType.Repaint)
style.Draw(r, filtered[i], false, false, selected, false);
if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition))
{
Select(filtered[i]);
Event.current.Use();
}
}
EditorGUILayout.EndScrollView();
}
private void HandleKeyboard()
{
var e = Event.current;
if (e.type != EventType.KeyDown) return;
if (e.keyCode == KeyCode.DownArrow)
{
currentIndex = Mathf.Min(currentIndex + 1, filtered.Count - 1);
e.Use();
editorWindow.Repaint();
}
else if (e.keyCode == KeyCode.UpArrow)
{
currentIndex = Mathf.Max(currentIndex - 1, 0);
e.Use();
editorWindow.Repaint();
}
else if (e.keyCode == KeyCode.Return || e.keyCode == KeyCode.KeypadEnter)
{
if (filtered.Count > 0 && currentIndex >= 0 && currentIndex < filtered.Count)
Select(filtered[currentIndex]);
e.Use();
}
}
private void FilterList(string keyword)
{
if (string.IsNullOrEmpty(keyword))
filtered = new List<string>(allItems);
else
{
string lower = keyword.ToLowerInvariant();
filtered = allItems.Where(i => i != null && i.ToLowerInvariant().Contains(lower)).ToList();
}
if (filtered.Count == 0) currentIndex = -1;
else currentIndex = Mathf.Clamp(currentIndex, 0, filtered.Count - 1);
}
private void Select(string item)
{
int originalIndex = allItems.IndexOf(item);
if (originalIndex >= 0)
onSelect?.Invoke(originalIndex);
editorWindow.Close();
GUIUtility.ExitGUI();
}
private void InitStyles()
{
if (searchFieldStyle == null)
searchFieldStyle = GUI.skin.FindStyle("ToolbarSeachTextField") ?? EditorStyles.toolbarSearchField;
if (cancelStyle == null)
cancelStyle = GUI.skin.FindStyle("ToolbarSeachCancelButton") ?? EditorStyles.toolbarButton;
if (rowStyle == null)
{
rowStyle = new GUIStyle("PR Label") { alignment = TextAnchor.MiddleLeft, padding = new RectOffset(6, 6, 2, 2) };
}
if (selectedRowStyle == null)
{
selectedRowStyle = new GUIStyle(rowStyle) { normal = { background = Texture2D.grayTexture } };
}
}
2025-09-05 19:46:30 +08:00
}
}