Design_SubModule/Scripts/Editor/Design_Tools/Common/DesignToolItemPickerWindow.cs
2026-03-16 14:56:09 +08:00

219 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}";
}
}
}