NLDClient-yudde/ProjectNLD/Assets/Editor/Scene/PostProcesser/PostProcessor.cs

405 lines
15 KiB
C#
Raw Normal View History

2024-01-15 20:25:49 +08:00
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.EventSystems;
2024-04-28 18:19:18 +08:00
using UnityEngine.Rendering;
2024-01-15 20:25:49 +08:00
using UnityEngine.SceneManagement;
public abstract class PostProcessor
{
public const string SCENE_POST_PROCESS_NAME = "PostProcess";
private const string SCENE_SURFACE_FOLDER_NAME = "SurfaceData";
private const string SCENE_COMBINED_NAME = "Combined";
private const string GROUND_SPLIT_NAME = "GroundSplit";
2024-10-22 16:10:43 +08:00
protected const string SCENE_POSTPROCESS_DIR = "Assets/Art_Out/AutoGen/PostProcessScenes";
protected const string PREFAB_POSTPROCESS_DIR = "Assets/Art_Out/AutoGen/PostProcessPrefabs";
2024-01-15 20:25:49 +08:00
protected const string SURFACE_SHADER_PATH = "Assets/Code/Shaders/Scene/NLD_Scene_Surface.shader";
protected const string SCENE_ADDRESSABLE_GROUP = "PostProcessScenes";
protected const string PREFAB_ADDRESSABLE_GROUP = "PostProcessPrefabs";
private const int GROUND_SPLIT_WIDTH = 1024;
private const int GROUND_SPLIT_HEIGHT = 1024;
private const int UPP = 100;
2024-10-22 16:10:43 +08:00
private readonly List<string> sceneRoots = new()
{ "Main Camera", "TerrainGridSystem", "Art", "SceneManager", "MapEditor", "LevelEditor", "TGSPreview", "InputManager (Singleton)" };
2024-01-15 20:25:49 +08:00
protected string ProcessedResourceDir => $"{ResourcesBaseDir}/{PostProcessFolderName}";
protected abstract string ResourcesBaseDir { get; }
private string SurfaceDir => $"{ProcessedResourceDir}/{SCENE_SURFACE_FOLDER_NAME}";
private string CombinedDir => $"{ProcessedResourceDir}/{SCENE_COMBINED_NAME}";
private string GroundSplitDir => $"{ProcessedResourceDir}/{GROUND_SPLIT_NAME}";
protected abstract string PostProcessFolderName { get; }
protected PostProcessInstructor _processInstructor;
private PostProcessInstructor _clonedProcessInstructor;
//private NLDSceneManager NLDSceneManager { get; set; }
//private NLDSceneManager _postProcessSceneManager;
private bool HasClone { get; set; }
2024-01-16 18:37:02 +08:00
protected abstract Object AssetToPostProcess { get; }
protected string OriginAssetPath => AssetDatabase.GetAssetPath(AssetToPostProcess);
2024-10-22 16:10:43 +08:00
2024-01-16 18:37:02 +08:00
protected abstract string OutputAssetPath { get; }
2024-01-15 20:25:49 +08:00
private PostProcessInstructor PostProcessInstructor => HasClone ? _clonedProcessInstructor : _processInstructor;
2024-01-17 13:44:26 +08:00
private Transform CombinedObjectsRoot
2024-01-15 20:25:49 +08:00
{
get
{
2024-01-17 13:44:26 +08:00
if (PostProcessInstructor == null || PostProcessInstructor.combinedObjectsRoot == null)
2024-01-15 20:25:49 +08:00
{
Debug.LogError($"找不到Art节点!");
return PostProcessInstructor.transform.parent;
}
2024-01-17 13:44:26 +08:00
return PostProcessInstructor.combinedObjectsRoot;
2024-01-15 20:25:49 +08:00
}
}
private bool CheckPostProcessInstructor(PostProcessInstructor postProcessInstructor)
{
if (postProcessInstructor == null)
{
Debug.LogError("postProcessInstructor is null");
return false;
}
2024-10-22 16:10:43 +08:00
if (postProcessInstructor.processPrefab &&
(!PrefabUtility.IsPartOfAnyPrefab(postProcessInstructor) || EditorUtility.IsPersistent(postProcessInstructor)))
2024-01-15 20:25:49 +08:00
{
2024-01-16 14:23:05 +08:00
Debug.LogError("postProcessInstructor不在任何预制体内或者其不是预制体实例");
2024-01-15 20:25:49 +08:00
return false;
}
2024-09-24 16:57:21 +08:00
var currentScene = postProcessInstructor.gameObject.scene;
var objs = currentScene.GetRootGameObjects();
foreach (var obj in objs)
{
if (!sceneRoots.Contains(obj.name))
{
DebugUtil.LogWarning("{1} 场景有其他节点:{0},请检查节点规范", obj.name, currentScene.name);
}
}
2024-01-15 20:25:49 +08:00
return true;
}
protected virtual void Init(PostProcessInstructor postProcessInstructor)
{
_processInstructor = postProcessInstructor;
}
2024-10-22 16:10:43 +08:00
public void PostProcess(PostProcessInstructor postProcessInstructor, bool destroyAfterPostProcess = false, bool defaultCameraParam = true)
2024-01-15 20:25:49 +08:00
{
if (!CheckPostProcessInstructor(postProcessInstructor))
return;
Init(postProcessInstructor);
HasClone = false;
EditorSceneManager.SaveOpenScenes();
PrepareFolders();
//NLDSceneManager = CommonUtils.GetSceneRootComponent<NLDSceneManager>(Scene);
//暂时先不渲染成面片(地面阴影还没法解决,以及一些与笔刷工具的耦合)
//BakeSurfaceData();
_clonedProcessInstructor = Clone();
2024-01-16 14:23:05 +08:00
HasClone = true;
2024-01-15 20:25:49 +08:00
if (_clonedProcessInstructor == null)
{
Debug.LogError("_clonedProcessInstructor is null!");
return;
}
2024-01-16 14:23:05 +08:00
2024-01-15 20:25:49 +08:00
BakeCombinedGameObject();
SplitGroundTexture();
SetFogPosition();
2024-10-22 16:10:43 +08:00
if (!defaultCameraParam)
{
SetCameraParam();
}
RemoveRedundant();
2024-10-22 16:10:43 +08:00
2024-01-16 14:23:05 +08:00
DestroyUselessObject();
2024-01-15 20:25:49 +08:00
AfterAll(destroyAfterPostProcess);
PostProcessData.EditorInstance.AddPostProcessData(AssetToPostProcess, OutputAssetPath);
2024-01-16 18:37:02 +08:00
Debug.Log($"执行后处理成功,后处理资源源路径:{OriginAssetPath} 后处理后路径:{OutputAssetPath}");
2024-01-26 16:02:49 +08:00
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
2024-01-15 20:25:49 +08:00
}
protected abstract void AfterAll(bool destroyAfterPostProcess);
public static PostProcessInstructor FindInstructorInScene(Scene scene)
{
var instructors = Object.FindObjectsOfType<PostProcessInstructor>();
return instructors.FirstOrDefault(pi => pi.gameObject.scene == scene);
}
// private void DeleteSurfaceData(SceneSurfaceData surfaceData)
// {
// var mat = AssetDatabase.LoadAssetAtPath<Material>(surfaceData.materialPath);
// if (mat == null)
// {
// return;
// }
//
// AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(mat.mainTexture));
// AssetDatabase.DeleteAsset(surfaceData.materialPath);
// }
private void PrepareFolders()
{
AssetDatabase.DeleteAsset(ProcessedResourceDir);
2024-01-16 14:23:05 +08:00
AssetDatabase.CreateFolder(ResourcesBaseDir, PostProcessFolderName);
2024-01-15 20:25:49 +08:00
AssetDatabase.CreateFolder(ProcessedResourceDir, SCENE_SURFACE_FOLDER_NAME);
AssetDatabase.CreateFolder(ProcessedResourceDir, SCENE_COMBINED_NAME);
AssetDatabase.CreateFolder(ProcessedResourceDir, GROUND_SPLIT_NAME);
}
protected abstract PostProcessInstructor Clone();
2024-01-16 14:23:05 +08:00
2024-01-15 20:25:49 +08:00
//烘焙面片数据
// private void BakeSurfaceData()
// {
// if (NLDSceneManager == null)
// return;
// NLDSceneManager.allSceneSurfaceData.Clear();
// List<SceneObjectRenderInfo> renderInfos = new();
// var camera = Camera.main;
// if (camera == null)
// {
// Debug.LogError("找不到主相机!请设置主相机的tag");
// return;
// }
//
// foreach (var sObj in NLDSceneManager.sceneObjects)
// {
// if (sObj && sObj.renderInfo && !renderInfos.Contains(sObj.renderInfo))
// {
// var brush = SceneBrushHelper.GetSceneBrushByRenderInfo(sObj.renderInfo);
// if (!brush.SupportSurface)
// continue;
// renderInfos.Add(sObj.renderInfo);
// var gameObject = brush.prefab;
// var texPath =
// EditorUtil.GetAssetUniquePath($"{SurfaceDir}/{gameObject.name}_surface.jpg", out var name);
// Vector3 offset = Vector3.zero;
// Vector3 scale = Vector3.one;
// Quaternion rotation = Quaternion.identity;
// var texture = gameObject.RenderToTexture(camera, texPath, ref offset, ref scale, ref rotation);
// if (texture != null)
// {
// var material = new Material(AssetDatabase.LoadAssetAtPath<Shader>(SURFACE_SHADER_PATH))
// {
// mainTexture = texture
// };
// material.enableInstancing = true;
// var matPath = $"{SurfaceDir}/{gameObject.name}_surface.mat".Replace("\\", "/");
// EditorUtil.CreateAnUniqueAsset(material, matPath);
// SceneSurfaceData surfaceData = new()
// {
// renderInfo = sObj.renderInfo,
// materialPath = matPath,
// cachedOffset = offset,
// eulerAngleID = gameObject.transform.eulerAngles,
// cachedRotation = rotation.eulerAngles,
// cachedScale = scale,
// valid = true,
// };
// NLDSceneManager.allSceneSurfaceData.Add(surfaceData);
// }
// }
// }
//
// //MarkSceneDirty();
// }
//合并网格,贴图
private void BakeCombinedGameObject()
{
2024-01-17 13:44:26 +08:00
var art = CombinedObjectsRoot;
2024-01-15 20:25:49 +08:00
var renderers = CollectRenderers();
var combinedRoot = new GameObject("CombinedRoot");
combinedRoot.transform.parent = art.transform;
2024-10-22 16:10:43 +08:00
SceneCombineUtil.Instance.CombineGameObjects(renderers, combinedRoot.transform, CombinedDir,
(int)PostProcessInstructor.postProcessTextureUnitSize);
2024-01-15 20:25:49 +08:00
foreach (var renderer in renderers)
{
Object.DestroyImmediate(renderer.gameObject);
}
}
private List<Renderer> CollectRenderers()
{
List<Renderer> allRenderers = new();
2024-01-17 13:44:26 +08:00
foreach (var root in PostProcessInstructor.rootsToCombine)
2024-01-15 20:25:49 +08:00
{
if (!root)
{
continue;
}
2024-10-22 16:10:43 +08:00
var render = root.GetComponentsInChildren<Renderer>();
if (render is not { Length: > 0 })
{
continue;
}
2024-10-22 16:10:43 +08:00
allRenderers.AddRange(render);
2024-01-15 20:25:49 +08:00
}
return allRenderers;
}
private void SplitGroundTexture()
{
var ground = PostProcessInstructor.ground;
if (ground == null)
return;
var renderer = ground.GetComponent<MeshRenderer>();
if (renderer == null)
return;
var mat = renderer.sharedMaterial;
if (mat == null)
return;
var texture = mat.mainTexture as Texture2D;
if (texture == null)
return;
2024-01-16 14:23:05 +08:00
var groundParent = Object.Instantiate(ground, ground.transform.parent, true);
2024-01-15 20:25:49 +08:00
groundParent.name = "Ground";
var scaleRatioX = ground.transform.localScale.x * UPP / texture.width;
var scaleRatioY = ground.transform.localScale.y * UPP / texture.height;
2024-02-02 16:45:56 +08:00
var originPos = -new Vector3(ground.transform.localScale.x / 2f, ground.transform.localScale.y / 2f, 0);
2024-01-15 20:25:49 +08:00
groundParent.transform.localScale = Vector3.one;
//groundParent.transform.localScale = new Vector3(scaleRatio, scaleRatio, 1);
var textures = SplitTextureUtil.SplitTexture(texture, GROUND_SPLIT_WIDTH, GROUND_SPLIT_HEIGHT, GroundSplitDir);
var fixedWidth = (float)GROUND_SPLIT_WIDTH / UPP * scaleRatioX;
var fixedHeight = (float)GROUND_SPLIT_HEIGHT / UPP * scaleRatioY;
for (int row = 0; row < textures.GetLength(0); row++)
{
for (int column = 0; column < textures.GetLength(1); column++)
{
var splitTexture = textures[row, column];
var xScale = (float)splitTexture.width / UPP * scaleRatioX;
var yScale = (float)splitTexture.height / UPP * scaleRatioY;
var splitGround = Object.Instantiate(ground, groundParent.transform, true);
Object.DestroyImmediate(splitGround.GetComponent<Collider>());
var splitName = $"Ground_{row}_{column}";
splitGround.name = splitName;
splitGround.transform.localScale = new Vector3(xScale, yScale, 1);
var splitMat = Object.Instantiate(mat);
splitMat.mainTexture = splitTexture;
AssetDatabase.CreateAsset(splitMat, $"{GroundSplitDir}/{splitName}.mat");
splitGround.GetComponent<MeshRenderer>().sharedMaterial = splitMat;
2024-04-28 18:19:18 +08:00
splitGround.GetComponent<MeshRenderer>().shadowCastingMode = ShadowCastingMode.Off;
2024-02-02 16:45:56 +08:00
splitGround.transform.localPosition =
2024-10-22 16:10:43 +08:00
originPos + new Vector3(column * fixedWidth + xScale / 2f, row * fixedHeight + yScale / 2f, 0);
2024-01-15 20:25:49 +08:00
}
}
Object.DestroyImmediate(ground);
Object.DestroyImmediate(groundParent.GetComponent<Renderer>());
Object.DestroyImmediate(groundParent.GetComponent<Collider>());
var boxCollider = groundParent.gameObject.AddComponent<BoxCollider>();
boxCollider.size = new Vector3(200, 200, 1);
2024-01-15 20:25:49 +08:00
boxCollider.center = new Vector3(0, 0, 0.5f);
Object.DestroyImmediate(groundParent.GetComponent<MeshFilter>());
}
private void SetFogPosition()
{
var fog = PostProcessInstructor.fog;
if (fog == null)
return;
var transform = fog.transform;
var position = transform.position;
transform.position = new Vector3(position.x, position.y + 0.01f, position.z);
2024-01-15 20:25:49 +08:00
}
2024-01-16 14:23:05 +08:00
2024-10-22 16:10:43 +08:00
private void SetCameraParam()
{
var postScene = PostProcessInstructor.gameObject.scene;
var postSceneName = postScene.name;
var scene = _processInstructor.gameObject.scene;
var sceneName = scene.name;
foreach (var rootObj in scene.GetRootGameObjects())
{
if (rootObj.CompareTag("MainCamera"))
{
CloneCameraToScene(rootObj, postScene);
break;
}
}
}
private void RemoveRedundant()
{
Scene postScene = PostProcessInstructor.gameObject.scene;
foreach (GameObject rootObj in postScene. GetRootGameObjects())
{
EventSystem[] eventSystems = rootObj.GetComponentsInChildren<EventSystem>();
if (null == eventSystems)
continue;
for (int i = 0; i < eventSystems.Length; ++i)
{
Object.DestroyImmediate(eventSystems[i].gameObject);
}
}
}
2024-10-22 16:10:43 +08:00
private void CloneCameraToScene(GameObject obj, Scene scene)
{
// 只更改transform
var oldPosition = obj.transform.position;
var oldRotation = obj.transform.rotation;
GameObject oldCamera = null;
foreach (var rootObj in scene.GetRootGameObjects())
{
if (rootObj.CompareTag("MainCamera"))
{
oldCamera = rootObj;
break;
}
}
if (oldCamera == null) return;
oldCamera.transform.position = oldPosition;
oldCamera.transform.rotation = oldRotation;
}
2024-01-16 14:23:05 +08:00
private void DestroyUselessObject()
{
2024-01-17 13:44:26 +08:00
foreach (var root in PostProcessInstructor.rootsToCombine)
2024-01-16 14:23:05 +08:00
{
if (!root)
{
continue;
}
2024-10-22 16:10:43 +08:00
2024-01-16 14:23:05 +08:00
Object.DestroyImmediate(root.gameObject, true);
}
Object.DestroyImmediate(PostProcessInstructor.gameObject, true);
}
2024-01-15 20:25:49 +08:00
}