using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace DesignTools.Common
{
[Serializable]
public class DesignToolItemPickerItem
{
public int Id;
public string Name;
public int IType;
}
///
/// 通用 Item 选择窗口
/// 支持按类型筛选、按 Id/名称搜索、分页浏览与回填选择结果
///
public class DesignToolItemPickerWindow : EditorWindow
{
private readonly List allItems = new List();
private readonly List allItemTypes = new List();
private readonly Dictionary itemTypeNames = new Dictionary();
private Vector2 scrollPosition;
private string searchText = "";
private int selectedType = -1;
private int currentItemId;
private int currentPage;
private const int ITEMS_PER_PAGE = 20;
private Action onItemSelected;
public static void ShowWindow(
List items,
List itemTypes,
Dictionary typeNames,
int currentType,
int selectedItemId,
Rect ownerWindowRect,
Action onSelected)
{
DesignToolItemPickerWindow window = CreateInstance();
window.titleContent = new GUIContent("选择道具");
window.minSize = new Vector2(700, 520);
window.allItems.Clear();
window.allItems.AddRange(items.OrderBy(x => x.IType).ThenBy(x => x.Id));
window.allItemTypes.Clear();
window.allItemTypes.AddRange(itemTypes);
window.itemTypeNames.Clear();
foreach (KeyValuePair pair in typeNames)
{
window.itemTypeNames[pair.Key] = pair.Value;
}
window.selectedType = currentType;
window.currentItemId = selectedItemId;
window.onItemSelected = onSelected;
window.position = GetCenteredRect(ownerWindowRect, window.minSize);
window.ShowModalUtility();
}
private static Rect GetCenteredRect(Rect ownerWindowRect, Vector2 windowSize)
{
float x = ownerWindowRect.x + (ownerWindowRect.width - windowSize.x) * 0.5f;
float y = ownerWindowRect.y + (ownerWindowRect.height - windowSize.y) * 0.5f;
return new Rect(x, y, windowSize.x, windowSize.y);
}
private void OnGUI()
{
DrawToolbar();
EditorGUILayout.Space(4);
DrawList();
}
private void DrawToolbar()
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("搜索", GUILayout.Width(40));
string newSearchText = EditorGUILayout.TextField(searchText);
if (newSearchText != searchText)
{
searchText = newSearchText;
currentPage = 0;
}
if (GUILayout.Button("清空", GUILayout.Width(50)))
{
searchText = "";
GUI.FocusControl(null);
currentPage = 0;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
List typeOptions = new List { "全部类型" };
typeOptions.AddRange(allItemTypes.Select(GetTypeDisplayName));
int selectedIndex = 0;
if (selectedType >= 0)
{
int typeIndex = allItemTypes.IndexOf(selectedType);
selectedIndex = typeIndex >= 0 ? typeIndex + 1 : 0;
}
int newIndex = EditorGUILayout.Popup("类型", selectedIndex, typeOptions.ToArray(),GUILayout.Width(420));
int newType = newIndex == 0 ? -1 : allItemTypes[newIndex - 1];
if (newType != selectedType)
{
selectedType = newType;
currentPage = 0;
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
EditorGUILayout.HelpBox("棋子上的宝箱如果是两个,id奇数是未解锁的,偶数是已解锁的", MessageType.Info);
EditorGUILayout.EndVertical();
}
private void DrawList()
{
List filteredItems = allItems
.Where(MatchFilter)
.ToList();
int totalPages = Mathf.Max(1, Mathf.CeilToInt(filteredItems.Count / (float)ITEMS_PER_PAGE));
currentPage = Mathf.Clamp(currentPage, 0, totalPages - 1);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($"共 {filteredItems.Count} 个道具", GUILayout.Width(120));
GUILayout.FlexibleSpace();
GUI.enabled = currentPage > 0;
if (GUILayout.Button("<", GUILayout.Width(30)))
{
currentPage--;
}
GUI.enabled = currentPage < totalPages - 1;
if (GUILayout.Button(">", GUILayout.Width(30)))
{
currentPage++;
}
GUI.enabled = true;
EditorGUILayout.LabelField($"第 {currentPage + 1}/{totalPages} 页", GUILayout.Width(90));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(4);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
IEnumerable pageItems = filteredItems
.Skip(currentPage * ITEMS_PER_PAGE)
.Take(ITEMS_PER_PAGE);
foreach (DesignToolItemPickerItem item in pageItems)
{
DrawItemRow(item);
}
EditorGUILayout.EndScrollView();
}
private void DrawItemRow(DesignToolItemPickerItem item)
{
bool isCurrent = item.Id == currentItemId;
GUI.backgroundColor = isCurrent ? new Color(0.8f, 1f, 0.8f) : Color.white;
EditorGUILayout.BeginVertical("box");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(item.Id.ToString(), GUILayout.Width(70));
EditorGUILayout.LabelField(item.Name, GUILayout.Width(280));
EditorGUILayout.LabelField(GetTypeDisplayName(item.IType), GUILayout.Width(160));
GUILayout.FlexibleSpace();
if (GUILayout.Button("选择", GUILayout.Width(60)))
{
onItemSelected?.Invoke(item.Id);
Close();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
GUI.backgroundColor = Color.white;
}
private bool MatchFilter(DesignToolItemPickerItem item)
{
if (selectedType >= 0 && item.IType != selectedType)
{
return false;
}
if (string.IsNullOrWhiteSpace(searchText))
{
return true;
}
return item.Id.ToString().Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
(!string.IsNullOrEmpty(item.Name) && item.Name.Contains(searchText, StringComparison.OrdinalIgnoreCase));
}
private string GetTypeDisplayName(int itemType)
{
return itemTypeNames.TryGetValue(itemType, out string typeName)
? $"{typeName} ({itemType})"
: $"类型 {itemType}";
}
}
}