219 lines
7.6 KiB
C#
219 lines
7.6 KiB
C#
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通用 Item 选择窗口
|
||
/// 支持按类型筛选、按 Id/名称搜索、分页浏览与回填选择结果
|
||
/// </summary>
|
||
public class DesignToolItemPickerWindow : EditorWindow
|
||
{
|
||
private readonly List<DesignToolItemPickerItem> allItems = new List<DesignToolItemPickerItem>();
|
||
private readonly List<int> allItemTypes = new List<int>();
|
||
private readonly Dictionary<int, string> itemTypeNames = new Dictionary<int, string>();
|
||
|
||
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<int> onItemSelected;
|
||
|
||
public static void ShowWindow(
|
||
List<DesignToolItemPickerItem> items,
|
||
List<int> itemTypes,
|
||
Dictionary<int, string> typeNames,
|
||
int currentType,
|
||
int selectedItemId,
|
||
Rect ownerWindowRect,
|
||
Action<int> onSelected)
|
||
{
|
||
DesignToolItemPickerWindow window = CreateInstance<DesignToolItemPickerWindow>();
|
||
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<int, string> 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<string> typeOptions = new List<string> { "全部类型" };
|
||
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<DesignToolItemPickerItem> 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<DesignToolItemPickerItem> 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}";
|
||
}
|
||
}
|
||
}
|