NLDClient-yudde/ProjectNLD/Assets/Editor/Scene/PostProcessInstructorInspec...

119 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<PostProcessInstructor>();
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);
}
}
}
/// <summary>
/// 执行模型切割操作
/// </summary>
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);
}
}