完成预览相关内容

This commit is contained in:
bob
2025-06-26 19:20:42 +08:00
parent 29d7836b66
commit 4febfadd56
12 changed files with 415 additions and 200 deletions

View File

@@ -1,204 +1,372 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using NBC;
using NBF;
namespace NBF
public class RuntimePreviewEditor : EditorWindow
{
public class PreviewableAssetEditor : EditorWindow
{
private List<GameObject> previewablePrefabs = new List<GameObject>();
private Vector2 scrollPosition;
private int selectedIndex = -1;
private GameObject selectedPrefab;
private Editor prefabEditor;
private SerializedObject serializedObject;
// 运行时实例引用
private GameObject runtimeInstance;
private PreviewableAsset runtimePreviewableAsset;
[MenuItem("Tools/Previewable Asset Editor")]
public static void ShowWindow()
// 预制体列表
private List<GameObject> prefabList = new List<GameObject>();
private int selectedPrefabIndex = -1;
private Vector2 scrollPosition;
// 预览控制
private bool isPreviewing = false;
private PreviewPanel _previewPanel;
[MenuItem("Tools/Runtime Preview Editor")]
public static void ShowWindow()
{
GetWindow<RuntimePreviewEditor>("Runtime Preview");
}
private void OnEnable()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
private void OnDisable()
{
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
ClearRuntimeInstance();
}
private void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.ExitingPlayMode)
{
GetWindow<PreviewableAssetEditor>("Previewable Assets");
ClearRuntimeInstance();
isPreviewing = false;
}
}
private void RefreshPrefabList()
{
Debug.LogError("重新加载所有预制体==");
prefabList.Clear();
string[] guids = AssetDatabase.FindAssets("t:Prefab");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab.GetComponent<PreviewableAsset>() != null)
{
prefabList.Add(prefab);
}
}
}
private void OnGUI()
{
EditorGUILayout.BeginHorizontal();
// 左侧预制体列表
DrawPrefabList();
// 右侧预览和操作区域
DrawPreviewArea();
EditorGUILayout.EndHorizontal();
}
private void DrawPrefabList()
{
EditorGUILayout.BeginVertical(GUILayout.Width(250));
EditorGUILayout.LabelField("Available Prefabs", EditorStyles.boldLabel);
EditorGUILayout.Space();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
for (int i = 0; i < prefabList.Count; i++)
{
bool isSelected = i == selectedPrefabIndex;
if (GUILayout.Toggle(isSelected, prefabList[i].name, "Button"))
{
if (!isSelected)
{
selectedPrefabIndex = i;
if (Application.isPlaying)
{
LoadRuntimeInstance();
}
}
}
}
private void OnEnable()
EditorGUILayout.EndScrollView();
if (GUILayout.Button("Refresh List"))
{
RefreshPrefabList();
}
private void RefreshPrefabList()
EditorGUILayout.EndVertical();
}
private void DrawPreviewArea()
{
EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
if (!Application.isPlaying)
{
previewablePrefabs.Clear();
// 查找项目中所有预制体
string[] guids = AssetDatabase.FindAssets("t:Prefab");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
// 检查预制体是否有 PreviewableAsset 组件
if (prefab.GetComponent<PreviewableAsset>() != 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.HelpBox("运行模式才可以编辑.", MessageType.Info);
EditorGUILayout.EndVertical();
return;
}
private void DrawOperationArea()
if (selectedPrefabIndex == -1)
{
EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
EditorGUILayout.HelpBox("未选中预制体", MessageType.Info);
EditorGUILayout.EndVertical();
return;
}
if (selectedPrefab == null)
GUILayout.BeginHorizontal();
if (GUILayout.Button("上一个"))
{
if (selectedPrefabIndex > 0)
{
EditorGUILayout.HelpBox("Select a prefab from the list to edit its PreviewableAsset properties.",
MessageType.Info);
selectedPrefabIndex--;
RefreshRuntimeInstance();
// EnsureSelectionVisible();
}
else
}
GUILayout.Space(20);
if (GUILayout.Button("下一个"))
{
if (selectedPrefabIndex < prefabList.Count - 1)
{
EditorGUILayout.LabelField("Editing: " + selectedPrefab.name, EditorStyles.boldLabel);
EditorGUILayout.Space();
selectedPrefabIndex++;
RefreshRuntimeInstance();
// EnsureSelectionVisible();
}
}
// 显示预制体预览
if (prefabEditor != null)
GUILayout.EndHorizontal();
var selectedPrefab = prefabList[selectedPrefabIndex];
EditorGUILayout.LabelField("当前预览: " + selectedPrefab.name, EditorStyles.boldLabel);
// 预览控制按钮
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(isPreviewing ? "停止预览" : "开始预览"))
{
TogglePreview();
}
if (isPreviewing && GUILayout.Button("刷新实例"))
{
RefreshRuntimeInstance();
}
EditorGUILayout.EndHorizontal();
// 运行时实例预览和编辑
if (isPreviewing && runtimeInstance != null && runtimePreviewableAsset)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Transform Properties", EditorStyles.boldLabel);
// 记录变化开始
EditorGUI.BeginChangeCheck();
// 编辑Transform
var newPosition = EditorGUILayout.Vector3Field("位置", runtimeInstance.transform.localPosition);
var newRotation = EditorGUILayout.Vector3Field("旋转", runtimeInstance.transform.localEulerAngles);
var newScale = EditorGUILayout.Vector3Field("形变", runtimeInstance.transform.localScale);
var canZoom = EditorGUILayout.Toggle("允许缩放", runtimePreviewableAsset.canZoom);
if (canZoom)
{
runtimePreviewableAsset.zoom = EditorGUILayout.Vector3Field("放大缩小配置", runtimePreviewableAsset.zoom);
}
var canPan = EditorGUILayout.Toggle("允许拖动", runtimePreviewableAsset.canPan);
if (canPan)
{
runtimePreviewableAsset.pan = EditorGUILayout.RectField("拖动配置", runtimePreviewableAsset.pan);
}
// 应用Transform修改
if (EditorGUI.EndChangeCheck())
{
runtimeInstance.transform.localPosition = newPosition;
runtimeInstance.transform.localEulerAngles = newRotation;
runtimeInstance.transform.localScale = newScale;
runtimePreviewableAsset.position = newPosition;
runtimePreviewableAsset.rotation = newRotation;
runtimePreviewableAsset.scale = newScale;
runtimePreviewableAsset.canZoom = canZoom;
runtimePreviewableAsset.canPan = canPan;
if (canZoom)
{
prefabEditor.OnPreviewGUI(GUILayoutUtility.GetRect(100, 100), EditorStyles.helpBox);
}
EditorGUILayout.Space();
// 显示 PreviewableAsset 属性
var previewableAsset = selectedPrefab.GetComponent<PreviewableAsset>();
if (previewableAsset != null)
{
if (serializedObject == null || serializedObject.targetObject != previewableAsset)
if (!Mathf.Approximately(runtimeInstance.transform.localPosition.z,
runtimePreviewableAsset.zoom.z))
{
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();
var pos = runtimeInstance.transform.localPosition;
runtimeInstance.transform.localPosition = new Vector3(pos.x, pos.y, runtimePreviewableAsset.zoom.z);
}
}
else
{
EditorGUILayout.HelpBox("Selected prefab no longer has a PreviewableAsset component.",
MessageType.Warning);
runtimeInstance.transform.localPosition = Vector3.zero;
}
}
EditorGUILayout.EndVertical();
}
EditorGUILayout.Space();
private void CreatePrefabEditor()
{
if (prefabEditor != null)
// 保存到预制体按钮
if (GUILayout.Button("保存到预制体", GUILayout.Height(30)))
{
DestroyImmediate(prefabEditor);
SaveChangesToPrefab();
}
prefabEditor = Editor.CreateEditor(selectedPrefab);
}
private void SaveChanges()
{
if (selectedPrefab != null)
if (GUILayout.Button("生成ICON", GUILayout.Height(30)))
{
// 标记预制体为脏以便保存
EditorUtility.SetDirty(selectedPrefab);
// 保存预制体
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log("Prefab " + selectedPrefab.name + " saved successfully.");
// SaveChangesToPrefab();
}
}
private void OnDisable()
EditorGUILayout.EndVertical();
}
private void TogglePreview()
{
isPreviewing = !isPreviewing;
if (isPreviewing)
{
if (prefabEditor != null)
_previewPanel = UI.Inst.GetUI<PreviewPanel>();
if (_previewPanel == null)
{
DestroyImmediate(prefabEditor);
isPreviewing = false;
Debug.LogError("显示UI面包未打开");
}
}
if (isPreviewing)
{
LoadRuntimeInstance();
}
else
{
ClearRuntimeInstance();
}
}
private void LoadRuntimeInstance()
{
ClearRuntimeInstance();
if (selectedPrefabIndex == -1 || !Application.isPlaying) return;
var prefab = prefabList[selectedPrefabIndex];
// 调用自定义实例化方法
// runtimeInstance = Instantiate(prefab);
// runtimeInstance.hideFlags = HideFlags.DontSave;
if (_previewPanel == null) return;
runtimeInstance = _previewPanel.LoadModel(prefab);
runtimeInstance.hideFlags = HideFlags.DontSave;
if (runtimeInstance != null)
{
runtimePreviewableAsset = runtimeInstance.GetComponent<PreviewableAsset>();
Selection.activeGameObject = runtimeInstance;
}
}
private void RefreshRuntimeInstance()
{
if (selectedPrefabIndex == -1 || !Application.isPlaying) return;
ClearRuntimeInstance();
LoadRuntimeInstance();
}
private void SaveChangesToPrefab()
{
if (selectedPrefabIndex == -1 || runtimeInstance == null) return;
var prefab = prefabList[selectedPrefabIndex];
var previewableAsset = prefab.GetComponent<PreviewableAsset>();
if (previewableAsset && runtimePreviewableAsset)
{
previewableAsset.position = runtimeInstance.transform.localPosition;
previewableAsset.rotation = runtimeInstance.transform.localEulerAngles;
previewableAsset.scale = runtimeInstance.transform.localScale;
previewableAsset.canPan = runtimePreviewableAsset.canPan;
previewableAsset.canZoom = runtimePreviewableAsset.canZoom;
previewableAsset.zoom = runtimePreviewableAsset.zoom;
previewableAsset.pan = runtimePreviewableAsset.pan;
}
EditorUtility.SetDirty(prefab);
AssetDatabase.Refresh();
// // 默认实现 - 直接修改预制体
// PrefabUtility.SaveAsPrefabAsset(runtimeInstance, AssetDatabase.GetAssetPath(prefab));
// AssetDatabase.Refresh();
Debug.Log("Changes saved to prefab: " + prefab.name);
}
private void ClearRuntimeInstance()
{
if (runtimeInstance != null)
{
if (Application.isPlaying)
{
Destroy(runtimeInstance);
}
else
{
DestroyImmediate(runtimeInstance);
}
}
runtimeInstance = null;
runtimePreviewableAsset = null;
}
// // 确保选中项在可视区域内
// private void EnsureSelectionVisible()
// {
// // 计算选中项的大概位置
// float itemHeight = 24; // 每个列表项的大约高度
// float visibleHeight = position.height - 100; // 可视区域的大约高度
//
// // 计算选中项应该在的滚动位置范围
// float targetMin = selectedPrefabIndex * itemHeight;
// float targetMax = targetMin + itemHeight;
//
// // 调整滚动位置
// if (scrollPosition.y > targetMin)
// {
// scrollPosition.y = targetMin;
// }
// else if (scrollPosition.y + visibleHeight < targetMax)
// {
// scrollPosition.y = targetMax - visibleHeight;
// }
//
// // 重绘界面
// Repaint();
// }
}