using Sirenix.OdinInspector.Editor; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; [CustomEditor(typeof(PostProcessInstructor))] public class PostProcessInstructorInspector : OdinEditor { private PostProcessInstructor Target => target as PostProcessInstructor; public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUILayout.Space(); var postProcessInstructors = FindObjectsOfType(); using (new EditorGUILayout.HorizontalScope()) { EditorGUI.BeginDisabledGroup(!Target.enableModelSlicing || Target.ground == null || Target.rootsToSlice == null || Target.rootsToSlice.Count == 0); if (GUILayout.Button("切割模型")) { SliceModels(); } EditorGUI.EndDisabledGroup(); if (GUILayout.Button("后处理")) { ObjectPostProcessorManager.Instance.PostProcess(Target); } if (postProcessInstructors.Length > 1 && GUILayout.Button("多节点后处理")) { ObjectPostProcessorManager.Instance.PostProcessMore(postProcessInstructors); } } } /// /// 执行模型切割操作 /// private void SliceModels() { if (!Target.enableModelSlicing || Target.ground == null || Target.rootsToSlice == null || Target.rootsToSlice.Count == 0) { Debug.LogWarning("无法执行切割:请确保启用了模型切割功能,并设置了地面和需要切割的模型节点"); return; } // 创建SlicerRoot节点,作为切割后模型的父节点(仅当保留原始模型时使用) GameObject slicerRootObj = null; Transform slicerRoot = null; if (Target.preserveOriginalModels) { // 保留原始模型时,创建SlicerRoot作为切割结果的容器 slicerRootObj = new GameObject("SlicerRoot"); slicerRootObj.transform.parent = Target.combinedObjectsRoot; slicerRoot = slicerRootObj.transform; Debug.Log($"创建切割结果根节点: {slicerRootObj.name}"); } // 预先检查要切割的物体是否是Prefab实例,如果是,解除Prefab链接 foreach (var root in Target.rootsToSlice) { if (root == null) continue; bool isPrefabInstance = PrefabUtility.IsPartOfPrefabInstance(root.gameObject); if (isPrefabInstance && !Target.preserveOriginalModels) { // 获取Prefab实例的根GameObject GameObject prefabRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(root.gameObject); if (prefabRoot != null) { Debug.Log($"物体 {root.name} 是Prefab实例的一部分,将解除其根节点 {prefabRoot.name} 的Prefab链接"); PrefabUtility.UnpackPrefabInstance(prefabRoot, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); } else { Debug.LogWarning($"无法获取物体 {root.name} 的Prefab根节点,跳过解除Prefab链接"); } } } // 调用模型切割工具执行切割,根据用户设置决定切割行为 ModelSlicerUtil.Instance.SliceModels( Target.rootsToSlice, Target.ground, Target.sliceMaterial, Target.slicePlaneDirection, Target.ignoreObjectBoundsCheck, Target.sliceAsynchronously, Target.preserveOriginalModels, // 使用用户的设置,决定是否保留原始模型 slicerRoot, // 当preserveOriginalModels为true时使用SlicerRoot,否则为null(使用原始节点) Target.saveMeshesToAssets, // 是否保存网格到Assets Target.meshSavePath, // 网格保存路径 Target.addTimestampToMeshName // 是否添加时间戳 ).Wait(); // 同步等待切割完成 var message = Target.preserveOriginalModels ? "模型切割处理完成,切割后的上半部分模型已放置在SlicerRoot节点下,原始模型未改变" : "模型切割处理完成,切割后的上半部分模型已替换原始模型,原始模型已移除"; // 如果保存了网格,添加相关信息 if (Target.saveMeshesToAssets) { message += $"\n切割后的网格已保存到路径: Assets/{Target.meshSavePath}"; } Debug.Log(message); // 标记场景为已修改,以便保存 EditorUtility.SetDirty(Target.gameObject); EditorSceneManager.MarkSceneDirty(Target.gameObject.scene); } }