Files
aibis-dream/Assets/Plugins/SOEditorTool/Editor/SOEditorConfigEditor.cs
T
2025-12-09 16:13:32 +08:00

164 lines
5.4 KiB
C#

using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Collections.Generic;
[CustomEditor(typeof(SOEditorConfig))]
public class SOEditorConfigEditor : Editor
{
private SerializedProperty _typeNamesProp;
private string _searchText = "";
private void OnEnable()
{
_typeNamesProp = serializedObject.FindProperty("targetTypeNames");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
SOEditorConfig config = (SOEditorConfig)target;
GUILayout.Label("已管理的 SO 类型:", EditorStyles.boldLabel);
// === 1. 绘制已添加的类型列表 ===
EditorGUILayout.BeginVertical("box");
for (int i = 0; i < _typeNamesProp.arraySize; i++)
{
SerializedProperty prop = _typeNamesProp.GetArrayElementAtIndex(i);
string typeName = prop.stringValue;
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label($"{i + 1}. {typeName}", EditorStyles.label);
if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), EditorStyles.iconButton, GUILayout.Width(25)))
{
_typeNamesProp.DeleteArrayElementAtIndex(i);
break;
}
}
EditorGUILayout.EndHorizontal();
}
if (_typeNamesProp.arraySize == 0)
{
GUILayout.Label("暂无类型,请添加", EditorStyles.centeredGreyMiniLabel);
}
EditorGUILayout.EndVertical();
GUILayout.Space(10);
// === 2. 拖拽区域 (核心修改) ===
DrawDragDropArea();
GUILayout.Space(10);
// === 3. 搜索添加 ===
GUILayout.Label("或者:搜索添加", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
_searchText = EditorGUILayout.TextField(_searchText, EditorStyles.toolbarSearchField);
if (GUILayout.Button("搜索", GUILayout.Width(60)))
{
ShowTypeSelectorMenu(config);
}
EditorGUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
private void DrawDragDropArea()
{
// 绘制一个虚线框区域
Rect dropArea = GUILayoutUtility.GetRect(0.0f, 60.0f, GUILayout.ExpandWidth(true));
GUI.Box(dropArea, "\n拖拽文件到这里添加\n(支持 .cs 脚本 或 .asset 资源)", EditorStyles.helpBox);
Event evt = Event.current;
if (evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform)
{
if (!dropArea.Contains(evt.mousePosition)) return;
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (evt.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
foreach (UnityEngine.Object dragged_object in DragAndDrop.objectReferences)
{
Type typeToAdd = null;
// 情况 A: 拖入的是 .cs 脚本文件
if (dragged_object is MonoScript script)
{
typeToAdd = script.GetClass();
}
// 情况 B: 拖入的是 .asset 资源实例 (比如 New Tank.asset)
else if (dragged_object is ScriptableObject soInstance)
{
// 直接获取这个实例的类型
typeToAdd = soInstance.GetType();
}
// 执行添加逻辑
if (typeToAdd != null)
{
// 过滤掉 Config 本身,防止把自己加进去
if (typeToAdd == typeof(SOEditorConfig)) continue;
if (typeToAdd.IsSubclassOf(typeof(ScriptableObject)))
{
AddType(typeToAdd.FullName);
}
}
}
}
}
}
private void ShowTypeSelectorMenu(SOEditorConfig config)
{
GenericMenu menu = new GenericMenu();
var allSoTypes = TypeCache.GetTypesDerivedFrom<ScriptableObject>()
.Where(t => !t.IsAbstract && !t.IsGenericType && !t.Namespace.StartsWith("Unity") && !t.Namespace.StartsWith("UnityEditor"))
.OrderBy(t => t.Name);
foreach (var type in allSoTypes)
{
if (!string.IsNullOrEmpty(_searchText) && !type.Name.ToLower().Contains(_searchText.ToLower()))
continue;
string menuPath = string.IsNullOrEmpty(type.Namespace) ? type.Name : $"{type.Namespace}/{type.Name}";
menu.AddItem(new GUIContent(menuPath), config.targetTypeNames.Contains(type.FullName), () => { AddType(type.FullName); });
}
menu.ShowAsContext();
}
private void AddType(string typeFullName)
{
serializedObject.Update();
bool exists = false;
for (int i = 0; i < _typeNamesProp.arraySize; i++)
{
if (_typeNamesProp.GetArrayElementAtIndex(i).stringValue == typeFullName)
{
exists = true;
break;
}
}
if (!exists)
{
_typeNamesProp.InsertArrayElementAtIndex(_typeNamesProp.arraySize);
_typeNamesProp.GetArrayElementAtIndex(_typeNamesProp.arraySize - 1).stringValue = typeFullName;
serializedObject.ApplyModifiedProperties();
}
}
}