using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace NBF { public class PreviewableAssetEditor : EditorWindow { private List previewablePrefabs = new List(); private Vector2 scrollPosition; private int selectedIndex = -1; private GameObject selectedPrefab; private Editor prefabEditor; private SerializedObject serializedObject; [MenuItem("Tools/Previewable Asset Editor")] public static void ShowWindow() { GetWindow("Previewable Assets"); } private void OnEnable() { RefreshPrefabList(); } private void RefreshPrefabList() { previewablePrefabs.Clear(); // 查找项目中所有预制体 string[] guids = AssetDatabase.FindAssets("t:Prefab"); foreach (string guid in guids) { string path = AssetDatabase.GUIDToAssetPath(guid); GameObject prefab = AssetDatabase.LoadAssetAtPath(path); // 检查预制体是否有 PreviewableAsset 组件 if (prefab.GetComponent() != null) { previewablePrefabs.Add(prefab); } } // 按名称排序 previewablePrefabs = previewablePrefabs.OrderBy(p => p.name).ToList(); } private void OnGUI() { EditorGUILayout.BeginHorizontal(); // 左侧列表 DrawPrefabList(); // 右侧操作区域 DrawOperationArea(); EditorGUILayout.EndHorizontal(); } private void DrawPrefabList() { EditorGUILayout.BeginVertical(GUILayout.Width(250)); EditorGUILayout.LabelField("Previewable Assets", EditorStyles.boldLabel); EditorGUILayout.Space(); scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, "box"); for (int i = 0; i < previewablePrefabs.Count; i++) { var prefab = previewablePrefabs[i]; bool isSelected = i == selectedIndex; EditorGUILayout.BeginHorizontal(); // 使用 toggle 样式按钮来模拟选择 if (GUILayout.Toggle(isSelected, prefab.name, "Button", GUILayout.Height(20))) { if (!isSelected) { selectedIndex = i; selectedPrefab = prefab; CreatePrefabEditor(); } } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); // 刷新按钮 if (GUILayout.Button("Refresh List")) { RefreshPrefabList(); selectedIndex = -1; selectedPrefab = null; prefabEditor = null; } EditorGUILayout.EndVertical(); } private void DrawOperationArea() { EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true)); if (selectedPrefab == null) { EditorGUILayout.HelpBox("Select a prefab from the list to edit its PreviewableAsset properties.", MessageType.Info); } else { EditorGUILayout.LabelField("Editing: " + selectedPrefab.name, EditorStyles.boldLabel); EditorGUILayout.Space(); // 显示预制体预览 if (prefabEditor != null) { prefabEditor.OnPreviewGUI(GUILayoutUtility.GetRect(100, 100), EditorStyles.helpBox); } EditorGUILayout.Space(); // 显示 PreviewableAsset 属性 var previewableAsset = selectedPrefab.GetComponent(); if (previewableAsset != null) { if (serializedObject == null || serializedObject.targetObject != previewableAsset) { serializedObject = new SerializedObject(previewableAsset); } serializedObject.Update(); // 自动绘制所有序列化字段 SerializedProperty prop = serializedObject.GetIterator(); bool enterChildren = true; while (prop.NextVisible(enterChildren)) { enterChildren = false; if (prop.name == "m_Script") continue; // 跳过脚本引用 EditorGUILayout.PropertyField(prop, true); } serializedObject.ApplyModifiedProperties(); EditorGUILayout.Space(); // 保存按钮 if (GUILayout.Button("Save Changes", GUILayout.Height(30))) { SaveChanges(); } } else { EditorGUILayout.HelpBox("Selected prefab no longer has a PreviewableAsset component.", MessageType.Warning); } } EditorGUILayout.EndVertical(); } private void CreatePrefabEditor() { if (prefabEditor != null) { DestroyImmediate(prefabEditor); } prefabEditor = Editor.CreateEditor(selectedPrefab); } private void SaveChanges() { if (selectedPrefab != null) { // 标记预制体为脏以便保存 EditorUtility.SetDirty(selectedPrefab); // 保存预制体 AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log("Prefab " + selectedPrefab.name + " saved successfully."); } } private void OnDisable() { if (prefabEditor != null) { DestroyImmediate(prefabEditor); } } } }