NLDClient-yudde/ProjectNLD/Assets/Editor/Scene/NLDSceneManagerInspector.cs

683 lines
21 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 System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Gameplay;
using Sirenix.OdinInspector.Editor;
using TGS;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
[CustomEditor(typeof(NLDSceneManager))]
public partial class NLDSceneManagerInspector : OdinEditor
{
private const string SCENE_BRUSH_PATH = "Assets/Art/Scene/SceneBrush/Brush/Editor";
private const string SCENE_RENDER_INFO_PATH = "Assets/Art/Scene/SceneBrush/SceneRenderInfo";
private const string SURFACE_SHADER_PATH = "Assets/Code/Shaders/Scene/NLD_Scene_Surface.shader";
private const string GROUND_MATERIAL_PATH = "Assets/Art/Scene/Map/Mat";
private const float UPP = 100;
private List<SceneBrush> _showBrushes = new();
private bool _isSelectingBrush;
private bool _isCreatingBrush;
private bool _isEditingScene;
private bool _foldOutGround;
private bool _foldOutBrush;
private bool _foldOutSceneManager;
private SceneBrush _currBrush;
private string _brushName;
private EBrushType _brushType;
private string _searchStr;
private EBrushType _searchType;
private Vector2 _scrollPosition;
private NLDSceneManager Target => target as NLDSceneManager;
private Scene Scene => Target.gameObject.scene;
private PreviewRenderUtility _previewRenderUtility;
private GameObject Prefab => _currBrush != null ? _currBrush.prefab : null;
private GameObject Ground => Target.Art.Find("Ground").gameObject;
private Texture2D _groundTex;
private Texture2D GroundTexture
{
get
{
if (Ground == null)
return null;
if (_groundTex == null)
{
var renderer = Ground.GetComponent<MeshRenderer>();
if (renderer != null)
{
var mat = renderer.sharedMaterial;
if (mat != null)
{
_groundTex = mat.mainTexture as Texture2D;
}
}
}
return _groundTex;
}
set
{
if (value == null)
{
return;
}
if (_groundTex != value)
{
_groundTex = value;
var mat = GetMapMaterial(value);
Ground.GetComponent<MeshRenderer>().sharedMaterial = mat;
ResetGroundScale();
}
}
}
private bool GroundValid => Ground != null && GroundTexture != null;
private Vector2 GroundScale
{
get => Ground.transform.localScale;
set
{
var currScale = Ground.transform.localScale;
var xRatio = value.x / currScale.x;
var yRatio = value.y / currScale.y;
var ration = Mathf.Approximately(xRatio, 1) ? yRatio : xRatio;
currScale *= ration;
Ground.transform.localScale = new Vector3(currScale.x, currScale.y, 1);
}
}
private TerrainGridSystem _tgs;
private TerrainGridSystem TGS
{
get
{
if (_tgs == null)
{
var allTgs = FindObjectsOfType<TerrainGridSystem>();
_tgs = allTgs.FirstOrDefault(t => t.gameObject.scene == Scene);
}
return _tgs;
}
}
private Material GetMapMaterial(Texture2D texture)
{
var guids = AssetDatabase.FindAssets("t:Material", new[] { GROUND_MATERIAL_PATH });
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(path))
continue;
var mat = AssetDatabase.LoadAssetAtPath<Material>(path);
if (mat.mainTexture == texture)
return mat;
}
var result = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"))
{
mainTexture = texture
};
var savePath = $"{GROUND_MATERIAL_PATH}/{texture.name}.mat";
EditorUtil.CreateAnUniqueAsset(result, savePath);
AssetDatabase.Refresh();
return result;
}
private void ResetGroundScale()
{
if (_groundTex != null)
Ground.transform.localScale = new Vector3(_groundTex.width, _groundTex.height, 1) / UPP;
}
private void ValidateData()
{
if (_previewRenderUtility == null)
{
_previewRenderUtility = new PreviewRenderUtility();
_previewRenderUtility.camera.transform.rotation = Quaternion.identity;
}
}
public override bool HasPreviewGUI()
{
ValidateData();
return true;
}
protected override void OnEnable()
{
base.OnEnable();
RefreshData();
Undo.undoRedoEvent += PreventEraserUnable;
}
private void PreventEraserUnable(in UndoRedoInfo undo)
{
if (undo.isRedo && undo.undoName == SceneBrush.BRUSH_DRAW_UNDO_NAME)
{
EditorSceneManager.SaveScene(Scene);
}
}
protected override void OnDisable()
{
base.OnDisable();
if (_previewRenderUtility != null)
{
_previewRenderUtility.Cleanup();
}
Undo.undoRedoEvent -= PreventEraserUnable;
}
private void RefreshData()
{
RefreshAllBrush();
RefreshBrushToShow();
}
private void RefreshAllBrush()
{
SceneBrushHelper.RefreshAllBrush();
}
private void RefreshBrushToShow()
{
_showBrushes.Clear();
foreach (var brush in SceneBrushHelper.AllBrushes)
{
if ((string.IsNullOrEmpty(_searchStr) || brush.name.IsStringContains(_searchStr) ||
brush.remarkName.IsStringContains(_searchStr)) &&
(_searchType == EBrushType.None || brush.brushType == _searchType))
{
_showBrushes.Add(brush);
}
}
}
private bool CheckCreateBrush()
{
if (string.IsNullOrEmpty(_brushName))
{
Debug.LogError("笔刷名为空!");
return false;
}
if (_brushType == EBrushType.None)
{
Debug.LogError("笔刷类型为空!");
return false;
}
foreach (var brush in SceneBrushHelper.AllBrushes)
{
var path = AssetDatabase.GetAssetPath(brush);
if (Path.GetFileNameWithoutExtension(path) == _brushName)
{
Debug.LogError("当前笔刷名字已存在,请重新命名!");
return false;
}
}
return true;
}
private bool CheckPreview()
{
return Prefab != null;
}
public override void OnPreviewGUI(Rect r, GUIStyle background)
{
if (Event.current.type == EventType.Repaint && CheckPreview())
{
var bounds = Prefab.GetMaxBounds();
if (bounds == null)
return;
var realBounds = (Bounds)bounds;
var y = realBounds.center.y;
_previewRenderUtility.BeginPreview(r, background);
_previewRenderUtility.camera.farClipPlane = 100;
var height = realBounds.size.y + 1;
var fov = _previewRenderUtility.camera.fieldOfView;
var z = -(height / 2) / Mathf.Tan(Mathf.Deg2Rad * (fov / 2));
var cameraPos = new Vector3(0, y, z);
_previewRenderUtility.camera.transform.position = cameraPos;
var meshRenderers = Prefab.GetComponentsInChildren<MeshRenderer>();
foreach (var msr in meshRenderers)
{
var matrix = msr.transform.localToWorldMatrix;
matrix[0, 3] = 0;
matrix[1, 3] = 0;
matrix[2, 3] = 0;
var materials = msr.sharedMaterials;
var mesh = msr.GetComponent<MeshFilter>().sharedMesh;
for (int i = 0; i < mesh.subMeshCount; i++)
{
if (i < materials.Length)
_previewRenderUtility.DrawMesh(mesh, matrix, materials[i], i);
}
}
_previewRenderUtility.camera.Render();
var result_render = _previewRenderUtility.EndPreview();
GUI.DrawTexture(r, result_render, ScaleMode.StretchToFill, false);
}
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!Application.isPlaying)
{
MarkSceneDirty();
DrawGround();
DrawBrush();
//EditorGUILayout.Space(10);
}
DrawSceneManager();
}
private void DrawGround()
{
_foldOutGround = EditorGUILayout.Foldout(_foldOutGround, "地面");
if (!_foldOutGround)
{
return;
}
GroundTexture = EditorGUILayout.ObjectField("地图贴图", GroundTexture, typeof(Texture2D), true) as Texture2D;
if (GroundTexture != null)
{
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginChangeCheck();
var scale = EditorGUILayout.Vector2Field("地图尺寸", GroundScale, GUILayout.MaxWidth(400),
GUILayout.ExpandWidth(false));
if (EditorGUI.EndChangeCheck())
{
GroundScale = scale;
}
if (GUILayout.Button("重置", GUILayout.Width(100)))
{
ResetGroundScale();
}
EditorGUILayout.EndHorizontal();
// if (TGS && GUILayout.Button("铺满网格"))
// {
// var column = CommonUtils.GetHexCount(GroundScale.x, TGS.regularHexagonsWidth, false);
// var row = CommonUtils.GetHexCount(GroundScale.y, _tgs.regularHexagonsWidth, true);
// CommonUtils.CorrectTGSColumnAndRow(ref column, ref row);
// TGS.columnCount = column;
// TGS.rowCount = row;
// }
}
}
private void DrawBrush()
{
if (!GroundValid)
return;
_foldOutBrush = EditorGUILayout.Foldout(_foldOutBrush, "笔刷");
if (!_foldOutBrush)
{
return;
}
DrawBrushSelecting();
DrawCreateBrush();
DrawBrushSettings();
}
private void DrawBrushSelecting()
{
if (_isSelectingBrush)
{
RefreshBrushToShow();
_searchStr = EditorGUILayout.TextField("搜索笔刷", _searchStr);
_searchType = (EBrushType)EditorGUILayout.EnumPopup("搜索笔刷类型", _searchType);
var scrollViewHeight = Mathf.Min(200, 30 * (_showBrushes.Count + 1) + 10);
_scrollPosition =
GUILayout.BeginScrollView(_scrollPosition, GUI.skin.box, GUILayout.Height(scrollViewHeight));
EditorGUILayout.BeginHorizontal(GUI.skin.label, GUILayout.Height(20));
EditorGUILayout.LabelField("笔刷名", GUILayout.Width(120));
EditorGUILayout.LabelField("笔刷类型", GUILayout.Width(60));
EditorGUILayout.LabelField("备注", GUILayout.Width(100));
EditorGUILayout.EndHorizontal();
foreach (var brush in _showBrushes)
{
if (brush == _currBrush)
GUI.color = Color.cyan;
EditorGUILayout.BeginHorizontal(GUI.skin.box, GUILayout.Height(20));
EditorGUILayout.LabelField(brush.name, GUILayout.Width(120));
EditorGUILayout.LabelField(brush.brushType.ToString(), GUILayout.Width(60));
EditorGUILayout.LabelField(brush.remarkName, GUILayout.Width(100));
if (GUILayout.Button("选择"))
{
_currBrush = brush;
_currBrush.OnSelected(Target, TGS);
Repaint();
}
GUI.color = Color.white;
EditorGUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
}
if (SceneBrushHelper.AllBrushes.Count > 0)
{
if (!_isSelectingBrush && GUILayout.Button("选择笔刷"))
{
_isSelectingBrush = true;
}
if (_isSelectingBrush && GUILayout.Button("选择完毕"))
{
_scrollPosition = Vector2.zero;
_isSelectingBrush = false;
}
}
else
{
_isSelectingBrush = false;
}
}
private void DrawCreateBrush()
{
if (!_isCreatingBrush)
{
if (GUILayout.Button("创建笔刷"))
{
_isCreatingBrush = true;
Repaint();
}
}
else
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
_brushName = EditorGUILayout.TextField("新建笔刷名", _brushName);
_brushType = (EBrushType)EditorGUILayout.Popup("新建笔刷类型", (int)_brushType, SceneBrush.EBrushTypeStrings);
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
if (GUILayout.Button("创建"))
{
if (!CheckCreateBrush())
{
return;
}
var renderInfoName = $"{_brushName}_renderInfo";
var renderInfoPath = $"{SCENE_RENDER_INFO_PATH}/{renderInfoName}.asset";
EditorUtil.CreateAnUniqueAsset(CreateInstance<SceneObjectRenderInfo>(), renderInfoPath);
AssetDatabase.Refresh();
var renderInfo = AssetDatabase.LoadAssetAtPath<SceneObjectRenderInfo>(renderInfoPath);
renderInfo.name = renderInfoName;
var brushName = _brushName;
var brushPath = $"{SCENE_BRUSH_PATH}/{brushName}.asset";
switch (_brushType)
{
case EBrushType.Tree:
EditorUtil.CreateAnUniqueAsset(CreateInstance<SceneBrushTree>(), brushPath);
break;
case EBrushType.Building:
EditorUtil.CreateAnUniqueAsset(CreateInstance<SceneBrushBuilding>(), brushPath);
break;
case EBrushType.Stuff:
EditorUtil.CreateAnUniqueAsset(CreateInstance<SceneBrushStuff>(), brushPath);
break;
default: break;
}
AssetDatabase.Refresh();
var brush = AssetDatabase.LoadAssetAtPath<SceneBrush>(brushPath);
if (brush == null)
{
Debug.LogError("创建笔刷失败!");
return;
}
brush.renderInfo = renderInfo;
brush.name = brushName;
EditorUtility.SetDirty(renderInfo);
EditorUtility.SetDirty(brush);
_currBrush = brush;
_currBrush.OnSelected(Target, TGS);
_isCreatingBrush = false;
RefreshData();
}
if (GUILayout.Button("取消创建"))
{
_isCreatingBrush = false;
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}
}
private void DrawBrushSettings()
{
if (_currBrush != null && !_isCreatingBrush)
{
GUI.enabled = false;
EditorGUILayout.ObjectField("当前笔刷:", _currBrush, typeof(SceneBrush), false);
EditorGUILayout.ObjectField("当前渲染信息:", _currBrush.renderInfo, typeof(SceneObjectRenderInfo), false);
GUI.enabled = true;
_currBrush.OnInspectorGUI();
if (_currBrush.Valid)
{
if (!_isEditingScene)
{
if (GUILayout.Button("开始编辑场景"))
{
_isEditingScene = true;
}
}
else
{
if (GUILayout.Button("退出编辑场景"))
{
_isEditingScene = false;
}
}
}
if (GUILayout.Button("删除笔刷"))
{
if (EditorUtility.DisplayDialog("删除笔刷", "您确定要删除笔刷吗?删除后可能会导致场景中该笔刷绘制的物体失效!" +
"\r\n如果确定要删除删除后可以在SceneManager上点击删除失效场景对象。", "确认", "取消"))
{
_currBrush.OnDelete();
var path = AssetDatabase.GetAssetPath(_currBrush);
AssetDatabase.DeleteAsset(path);
_currBrush = null;
RefreshData();
}
}
}
}
private void DrawSceneManager()
{
if (!GroundValid)
return;
_foldOutSceneManager = EditorGUILayout.Foldout(_foldOutSceneManager, "其他");
if (!_foldOutSceneManager)
return;
EditorGUI.BeginChangeCheck();
Target.UseAllSurface = EditorGUILayout.Toggle("开启面片", Target.UseAllSurface);
if (EditorGUI.EndChangeCheck())
{
if (!Application.isPlaying)
MarkSceneDirty();
}
if (!Application.isPlaying)
{
// if (GUILayout.Button("清除所有场景对象"))
// {
// if (EditorUtility.DisplayDialog("清除场景", "请问您确定要清除场景吗,清除后将不存在任何场景物件!", "确认", "取消"))
// ClearAllSceneObject();
// }
if (GUILayout.Button("保留失效场景对象"))
{
PreserveUselessSceneObjects();
}
if (GUILayout.Button("清除失效场景对象"))
{
ClearUselessSceneObjects();
}
if (!Scene.name.Contains(PostProcessor.SCENE_POST_PROCESS_NAME) && GUILayout.Button("场景后处理"))
{
PostProcessScene();
}
}
}
private void ClearAllSceneObject()
{
foreach (var sObj in Target.sceneObjects)
{
if (sObj)
DestroyImmediate(sObj.gameObject);
}
Target.sceneObjects.Clear();
MarkSceneDirty();
}
private void ClearUselessSceneObjects()
{
for (int i = Target.sceneObjects.Count - 1; i >= 0; i--)
{
var sObj = Target.sceneObjects[i];
if (sObj == null || sObj.renderInfo == null)
{
if (sObj != null)
DestroyImmediate(sObj.gameObject);
Target.sceneObjects.RemoveAt(i);
}
}
ClearUselessSurfaceData();
MarkSceneDirty();
}
private void PreserveUselessSceneObjects()
{
for (int i = Target.sceneObjects.Count - 1; i >= 0; i--)
{
var sObj = Target.sceneObjects[i];
if (sObj == null || sObj.renderInfo == null)
{
if (sObj != null)
DestroyImmediate(sObj);
Target.sceneObjects.RemoveAt(i);
}
}
ClearUselessSurfaceData();
MarkSceneDirty();
}
private void ClearUselessSurfaceData()
{
for (int i = Target.allSceneSurfaceData.Count - 1; i >= 0; i--)
{
var surfaceData = Target.allSceneSurfaceData[i];
if (surfaceData == null || surfaceData.renderInfo == null)
{
if (surfaceData != null)
DeleteSurfaceData(surfaceData);
Target.allSceneSurfaceData.RemoveAt(i);
}
}
}
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 PostProcessScene()
{
ObjectPostProcessorManager.Instance.PostProcess(Scene);
}
private void MarkSceneDirty()
{
EditorSceneManager.MarkSceneDirty(Scene);
}
private void OnSceneGUI()
{
Handles.BeginGUI();
var sceneView = SceneView.lastActiveSceneView;
var sceneViewPos = sceneView.position;
if (GUI.Button(new Rect(sceneViewPos.width - 100, sceneViewPos.height - 50, 100, 30), "Scene归位"))
{
var mainCam = Camera.main;
if (mainCam == null)
return;
if (Ground != null)
sceneView.LookAt(Ground.transform.position, mainCam.transform.rotation);
}
Handles.EndGUI();
if (!_isEditingScene || _currBrush == null || !_currBrush.Valid || Application.isPlaying)
return;
var e = Event.current;
_currBrush.OnSceneGUI(e);
}
}