2023-12-07 16:41:41 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.IO;
|
2023-12-15 13:44:42 +08:00
|
|
|
|
using Gameplay;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
using Sirenix.OdinInspector.Editor;
|
2023-12-08 20:02:39 +08:00
|
|
|
|
using TGS;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
using UnityEditor;
|
2023-12-09 22:06:08 +08:00
|
|
|
|
using UnityEditor.SceneManagement;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
using UnityEngine;
|
2023-12-12 20:03:44 +08:00
|
|
|
|
using UnityEngine.SceneManagement;
|
2023-12-08 20:02:39 +08:00
|
|
|
|
using Object = UnityEngine.Object;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
|
|
|
|
|
[CustomEditor(typeof(NLDSceneManager))]
|
2024-01-04 13:52:29 +08:00
|
|
|
|
public partial class NLDSceneManagerInspector : OdinEditor
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
private const string SCENE_BRUSH_PATH = "Assets/Art/Scene/SceneBrush/Brush/Editor";
|
|
|
|
|
|
private const string SCENE_RENDER_INFO_PATH = "Assets/Art/Scene/SceneBrush/SceneRenderInfo";
|
2023-12-12 20:03:44 +08:00
|
|
|
|
private const string SURFACE_SHADER_PATH = "Assets/Code/Shaders/Scene/NLD_Scene_Surface.shader";
|
2023-12-14 18:07:51 +08:00
|
|
|
|
private const string GROUND_MATERIAL_PATH = "Assets/Art/Scene/Map/Mat";
|
2023-12-15 13:44:42 +08:00
|
|
|
|
private const float UPP = 100;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
|
|
|
|
|
private List<SceneBrush> _showBrushes = new();
|
|
|
|
|
|
|
|
|
|
|
|
private bool _isSelectingBrush;
|
|
|
|
|
|
private bool _isCreatingBrush;
|
2023-12-08 20:02:39 +08:00
|
|
|
|
private bool _isEditingScene;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
2023-12-14 18:07:51 +08:00
|
|
|
|
private bool _foldOutGround;
|
|
|
|
|
|
private bool _foldOutBrush;
|
|
|
|
|
|
private bool _foldOutSceneManager;
|
|
|
|
|
|
|
2023-12-07 16:41:41 +08:00
|
|
|
|
private SceneBrush _currBrush;
|
|
|
|
|
|
private string _brushName;
|
|
|
|
|
|
private EBrushType _brushType;
|
|
|
|
|
|
private string _searchStr;
|
2023-12-08 20:02:39 +08:00
|
|
|
|
private EBrushType _searchType;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
|
|
|
|
|
private Vector2 _scrollPosition;
|
2023-12-08 20:02:39 +08:00
|
|
|
|
private NLDSceneManager Target => target as NLDSceneManager;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
2023-12-12 20:03:44 +08:00
|
|
|
|
private Scene Scene => Target.gameObject.scene;
|
|
|
|
|
|
|
2023-12-07 16:41:41 +08:00
|
|
|
|
private PreviewRenderUtility _previewRenderUtility;
|
|
|
|
|
|
|
|
|
|
|
|
private GameObject Prefab => _currBrush != null ? _currBrush.prefab : null;
|
|
|
|
|
|
|
2025-08-26 19:00:29 +08:00
|
|
|
|
private GameObject Ground
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
var obj = Target.Art.Find("Ground");
|
|
|
|
|
|
return obj != null ? obj.gameObject : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-14 18:07:51 +08:00
|
|
|
|
|
|
|
|
|
|
private Texture2D _groundTex;
|
|
|
|
|
|
|
|
|
|
|
|
private Texture2D GroundTexture
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Ground == null)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
if (_groundTex == null)
|
|
|
|
|
|
{
|
2023-12-20 13:14:02 +08:00
|
|
|
|
var renderer = Ground.GetComponent<MeshRenderer>();
|
|
|
|
|
|
if (renderer != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var mat = renderer.sharedMaterial;
|
|
|
|
|
|
if (mat != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_groundTex = mat.mainTexture as Texture2D;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-14 18:07:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return _groundTex;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_groundTex != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_groundTex = value;
|
|
|
|
|
|
var mat = GetMapMaterial(value);
|
|
|
|
|
|
Ground.GetComponent<MeshRenderer>().sharedMaterial = mat;
|
2023-12-15 13:44:42 +08:00
|
|
|
|
ResetGroundScale();
|
2023-12-14 18:07:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-15 13:44:42 +08:00
|
|
|
|
private TerrainGridSystem _tgs;
|
|
|
|
|
|
|
|
|
|
|
|
private TerrainGridSystem TGS
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_tgs == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var allTgs = FindObjectsOfType<TerrainGridSystem>();
|
|
|
|
|
|
_tgs = allTgs.FirstOrDefault(t => t.gameObject.scene == Scene);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return _tgs;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-05 14:48:47 +08:00
|
|
|
|
|
2023-12-14 18:07:51 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-15 13:44:42 +08:00
|
|
|
|
private void ResetGroundScale()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_groundTex != null)
|
|
|
|
|
|
Ground.transform.localScale = new Vector3(_groundTex.width, _groundTex.height, 1) / UPP;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-07 16:41:41 +08:00
|
|
|
|
private void ValidateData()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_previewRenderUtility == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_previewRenderUtility = new PreviewRenderUtility();
|
|
|
|
|
|
|
|
|
|
|
|
_previewRenderUtility.camera.transform.rotation = Quaternion.identity;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override bool HasPreviewGUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
ValidateData();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-09 22:06:08 +08:00
|
|
|
|
protected override void OnEnable()
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
2023-12-09 22:06:08 +08:00
|
|
|
|
base.OnEnable();
|
2023-12-07 16:41:41 +08:00
|
|
|
|
RefreshData();
|
2023-12-09 22:06:08 +08:00
|
|
|
|
Undo.undoRedoEvent += PreventEraserUnable;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-09 22:06:08 +08:00
|
|
|
|
private void PreventEraserUnable(in UndoRedoInfo undo)
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
2023-12-09 22:06:08 +08:00
|
|
|
|
if (undo.isRedo && undo.undoName == SceneBrush.BRUSH_DRAW_UNDO_NAME)
|
|
|
|
|
|
{
|
2023-12-12 20:03:44 +08:00
|
|
|
|
EditorSceneManager.SaveScene(Scene);
|
2023-12-09 22:06:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnDisable()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnDisable();
|
2023-12-07 16:41:41 +08:00
|
|
|
|
if (_previewRenderUtility != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_previewRenderUtility.Cleanup();
|
|
|
|
|
|
}
|
2023-12-12 20:03:44 +08:00
|
|
|
|
|
2023-12-09 22:06:08 +08:00
|
|
|
|
Undo.undoRedoEvent -= PreventEraserUnable;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshData()
|
|
|
|
|
|
{
|
|
|
|
|
|
RefreshAllBrush();
|
|
|
|
|
|
RefreshBrushToShow();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshAllBrush()
|
|
|
|
|
|
{
|
|
|
|
|
|
SceneBrushHelper.RefreshAllBrush();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshBrushToShow()
|
|
|
|
|
|
{
|
|
|
|
|
|
_showBrushes.Clear();
|
|
|
|
|
|
foreach (var brush in SceneBrushHelper.AllBrushes)
|
|
|
|
|
|
{
|
2023-12-08 20:02:39 +08:00
|
|
|
|
if ((string.IsNullOrEmpty(_searchStr) || brush.name.IsStringContains(_searchStr) ||
|
|
|
|
|
|
brush.remarkName.IsStringContains(_searchStr)) &&
|
|
|
|
|
|
(_searchType == EBrushType.None || brush.brushType == _searchType))
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
_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())
|
|
|
|
|
|
{
|
2023-12-12 20:03:44 +08:00
|
|
|
|
var bounds = Prefab.GetMaxBounds();
|
|
|
|
|
|
if (bounds == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
var realBounds = (Bounds)bounds;
|
|
|
|
|
|
var y = realBounds.center.y;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
_previewRenderUtility.BeginPreview(r, background);
|
|
|
|
|
|
_previewRenderUtility.camera.farClipPlane = 100;
|
2023-12-12 20:03:44 +08:00
|
|
|
|
var height = realBounds.size.y + 1;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
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;
|
2023-12-12 20:03:44 +08:00
|
|
|
|
var meshRenderers = Prefab.GetComponentsInChildren<MeshRenderer>();
|
|
|
|
|
|
foreach (var msr in meshRenderers)
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
2023-12-12 20:03:44 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_previewRenderUtility.camera.Render();
|
|
|
|
|
|
|
|
|
|
|
|
var result_render = _previewRenderUtility.EndPreview();
|
|
|
|
|
|
GUI.DrawTexture(r, result_render, ScaleMode.StretchToFill, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void OnInspectorGUI()
|
|
|
|
|
|
{
|
2023-12-08 20:02:39 +08:00
|
|
|
|
base.OnInspectorGUI();
|
2023-12-14 14:33:45 +08:00
|
|
|
|
if (!Application.isPlaying)
|
|
|
|
|
|
{
|
2023-12-19 12:45:17 +08:00
|
|
|
|
MarkSceneDirty();
|
2023-12-14 18:07:51 +08:00
|
|
|
|
DrawGround();
|
2023-12-14 14:33:45 +08:00
|
|
|
|
DrawBrush();
|
2023-12-14 18:07:51 +08:00
|
|
|
|
//EditorGUILayout.Space(10);
|
2023-12-14 14:33:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-08 20:02:39 +08:00
|
|
|
|
DrawSceneManager();
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-14 18:07:51 +08:00
|
|
|
|
private void DrawGround()
|
|
|
|
|
|
{
|
2025-08-26 19:00:29 +08:00
|
|
|
|
if (Ground == null) return;
|
2023-12-14 18:07:51 +08:00
|
|
|
|
_foldOutGround = EditorGUILayout.Foldout(_foldOutGround, "地面");
|
|
|
|
|
|
if (!_foldOutGround)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GroundTexture = EditorGUILayout.ObjectField("地图贴图", GroundTexture, typeof(Texture2D), true) as Texture2D;
|
|
|
|
|
|
if (GroundTexture != null)
|
|
|
|
|
|
{
|
2023-12-15 13:44:42 +08:00
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
2023-12-14 18:07:51 +08:00
|
|
|
|
EditorGUI.BeginChangeCheck();
|
2023-12-19 12:26:03 +08:00
|
|
|
|
var scale = EditorGUILayout.Vector2Field("地图尺寸", GroundScale, GUILayout.MaxWidth(400),
|
|
|
|
|
|
GUILayout.ExpandWidth(false));
|
2023-12-14 18:07:51 +08:00
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
|
|
|
|
{
|
|
|
|
|
|
GroundScale = scale;
|
|
|
|
|
|
}
|
2023-12-15 13:44:42 +08:00
|
|
|
|
|
2023-12-19 12:26:03 +08:00
|
|
|
|
if (GUILayout.Button("重置", GUILayout.Width(100)))
|
2023-12-15 13:44:42 +08:00
|
|
|
|
{
|
|
|
|
|
|
ResetGroundScale();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
|
|
|
2023-12-20 12:47:57 +08:00
|
|
|
|
// 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;
|
|
|
|
|
|
// }
|
2023-12-14 18:07:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DrawBrush()
|
|
|
|
|
|
{
|
2025-08-26 19:00:29 +08:00
|
|
|
|
/*if (!GroundValid)
|
|
|
|
|
|
return;*/
|
2023-12-14 18:07:51 +08:00
|
|
|
|
_foldOutBrush = EditorGUILayout.Foldout(_foldOutBrush, "笔刷");
|
|
|
|
|
|
if (!_foldOutBrush)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DrawBrushSelecting();
|
|
|
|
|
|
DrawCreateBrush();
|
|
|
|
|
|
DrawBrushSettings();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-07 16:41:41 +08:00
|
|
|
|
private void DrawBrushSelecting()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isSelectingBrush)
|
|
|
|
|
|
{
|
|
|
|
|
|
RefreshBrushToShow();
|
|
|
|
|
|
_searchStr = EditorGUILayout.TextField("搜索笔刷", _searchStr);
|
2023-12-08 20:02:39 +08:00
|
|
|
|
_searchType = (EBrushType)EditorGUILayout.EnumPopup("搜索笔刷类型", _searchType);
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
|
|
|
|
|
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));
|
2023-12-08 20:02:39 +08:00
|
|
|
|
EditorGUILayout.LabelField("笔刷名", GUILayout.Width(120));
|
|
|
|
|
|
EditorGUILayout.LabelField("笔刷类型", GUILayout.Width(60));
|
|
|
|
|
|
EditorGUILayout.LabelField("备注", GUILayout.Width(100));
|
2023-12-07 16:41:41 +08:00
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
|
|
foreach (var brush in _showBrushes)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (brush == _currBrush)
|
|
|
|
|
|
GUI.color = Color.cyan;
|
|
|
|
|
|
EditorGUILayout.BeginHorizontal(GUI.skin.box, GUILayout.Height(20));
|
2023-12-08 20:02:39 +08:00
|
|
|
|
EditorGUILayout.LabelField(brush.name, GUILayout.Width(120));
|
|
|
|
|
|
EditorGUILayout.LabelField(brush.brushType.ToString(), GUILayout.Width(60));
|
|
|
|
|
|
EditorGUILayout.LabelField(brush.remarkName, GUILayout.Width(100));
|
2023-12-07 16:41:41 +08:00
|
|
|
|
if (GUILayout.Button("选择"))
|
|
|
|
|
|
{
|
|
|
|
|
|
_currBrush = brush;
|
2023-12-15 13:44:42 +08:00
|
|
|
|
_currBrush.OnSelected(Target, TGS);
|
2023-12-08 20:02:39 +08:00
|
|
|
|
Repaint();
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
2023-12-14 14:33:45 +08:00
|
|
|
|
_brushType = (EBrushType)EditorGUILayout.Popup("新建笔刷类型", (int)_brushType, SceneBrush.EBrushTypeStrings);
|
2023-12-07 16:41:41 +08:00
|
|
|
|
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;
|
2023-12-14 12:21:48 +08:00
|
|
|
|
case EBrushType.Stuff:
|
|
|
|
|
|
EditorUtil.CreateAnUniqueAsset(CreateInstance<SceneBrushStuff>(), brushPath);
|
|
|
|
|
|
break;
|
2023-12-07 16:41:41 +08:00
|
|
|
|
default: break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
var brush = AssetDatabase.LoadAssetAtPath<SceneBrush>(brushPath);
|
2023-12-14 12:21:48 +08:00
|
|
|
|
if (brush == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("创建笔刷失败!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-12-14 14:33:45 +08:00
|
|
|
|
|
2023-12-07 16:41:41 +08:00
|
|
|
|
brush.renderInfo = renderInfo;
|
|
|
|
|
|
brush.name = brushName;
|
|
|
|
|
|
|
|
|
|
|
|
EditorUtility.SetDirty(renderInfo);
|
|
|
|
|
|
EditorUtility.SetDirty(brush);
|
|
|
|
|
|
|
|
|
|
|
|
_currBrush = brush;
|
2023-12-15 13:44:42 +08:00
|
|
|
|
_currBrush.OnSelected(Target, TGS);
|
2023-12-07 16:41:41 +08:00
|
|
|
|
_isCreatingBrush = false;
|
|
|
|
|
|
RefreshData();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (GUILayout.Button("取消创建"))
|
|
|
|
|
|
{
|
|
|
|
|
|
_isCreatingBrush = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.EndVertical();
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-14 18:07:51 +08:00
|
|
|
|
private void DrawBrushSettings()
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
2023-12-08 20:02:39 +08:00
|
|
|
|
if (_currBrush != null && !_isCreatingBrush)
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
GUI.enabled = false;
|
|
|
|
|
|
EditorGUILayout.ObjectField("当前笔刷:", _currBrush, typeof(SceneBrush), false);
|
|
|
|
|
|
EditorGUILayout.ObjectField("当前渲染信息:", _currBrush.renderInfo, typeof(SceneObjectRenderInfo), false);
|
|
|
|
|
|
GUI.enabled = true;
|
|
|
|
|
|
|
2023-12-08 20:02:39 +08:00
|
|
|
|
_currBrush.OnInspectorGUI();
|
|
|
|
|
|
|
2023-12-12 20:03:44 +08:00
|
|
|
|
if (_currBrush.Valid)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isEditingScene)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (GUILayout.Button("开始编辑场景"))
|
|
|
|
|
|
{
|
|
|
|
|
|
_isEditingScene = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (GUILayout.Button("退出编辑场景"))
|
|
|
|
|
|
{
|
|
|
|
|
|
_isEditingScene = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
|
|
|
|
|
if (GUILayout.Button("删除笔刷"))
|
|
|
|
|
|
{
|
2023-12-08 20:02:39 +08:00
|
|
|
|
if (EditorUtility.DisplayDialog("删除笔刷", "您确定要删除笔刷吗?删除后可能会导致场景中该笔刷绘制的物体失效!" +
|
|
|
|
|
|
"\r\n如果确定要删除,删除后可以在SceneManager上点击删除失效场景对象。", "确认", "取消"))
|
|
|
|
|
|
{
|
|
|
|
|
|
_currBrush.OnDelete();
|
|
|
|
|
|
var path = AssetDatabase.GetAssetPath(_currBrush);
|
|
|
|
|
|
AssetDatabase.DeleteAsset(path);
|
|
|
|
|
|
_currBrush = null;
|
|
|
|
|
|
RefreshData();
|
|
|
|
|
|
}
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-08 20:02:39 +08:00
|
|
|
|
private void DrawSceneManager()
|
2023-12-07 16:41:41 +08:00
|
|
|
|
{
|
2023-12-14 18:07:51 +08:00
|
|
|
|
if (!GroundValid)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
_foldOutSceneManager = EditorGUILayout.Foldout(_foldOutSceneManager, "其他");
|
|
|
|
|
|
if (!_foldOutSceneManager)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2023-12-14 14:50:29 +08:00
|
|
|
|
EditorGUI.BeginChangeCheck();
|
2023-12-14 14:33:45 +08:00
|
|
|
|
Target.UseAllSurface = EditorGUILayout.Toggle("开启面片", Target.UseAllSurface);
|
2023-12-14 14:50:29 +08:00
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
|
|
|
|
{
|
2023-12-14 18:07:51 +08:00
|
|
|
|
if (!Application.isPlaying)
|
2023-12-19 12:45:17 +08:00
|
|
|
|
MarkSceneDirty();
|
2023-12-14 14:50:29 +08:00
|
|
|
|
}
|
2023-12-14 18:07:51 +08:00
|
|
|
|
|
2023-12-14 14:33:45 +08:00
|
|
|
|
if (!Application.isPlaying)
|
2023-12-08 20:02:39 +08:00
|
|
|
|
{
|
2023-12-14 14:33:45 +08:00
|
|
|
|
// if (GUILayout.Button("清除所有场景对象"))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (EditorUtility.DisplayDialog("清除场景", "请问您确定要清除场景吗,清除后将不存在任何场景物件!", "确认", "取消"))
|
|
|
|
|
|
// ClearAllSceneObject();
|
|
|
|
|
|
// }
|
2023-12-12 20:03:44 +08:00
|
|
|
|
|
2023-12-19 14:28:32 +08:00
|
|
|
|
if (GUILayout.Button("保留失效场景对象"))
|
|
|
|
|
|
{
|
|
|
|
|
|
PreserveUselessSceneObjects();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-14 14:33:45 +08:00
|
|
|
|
if (GUILayout.Button("清除失效场景对象"))
|
|
|
|
|
|
{
|
|
|
|
|
|
ClearUselessSceneObjects();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-22 16:10:43 +08:00
|
|
|
|
if (!Scene.name.Contains(PostProcessor.SCENE_POST_PROCESS_NAME) && GUILayout.Button("场景后处理 (默认相机)"))
|
2023-12-14 14:33:45 +08:00
|
|
|
|
{
|
2024-01-04 13:52:29 +08:00
|
|
|
|
PostProcessScene();
|
2023-12-14 14:33:45 +08:00
|
|
|
|
}
|
2024-10-22 16:10:43 +08:00
|
|
|
|
|
|
|
|
|
|
if (!Scene.name.Contains(PostProcessor.SCENE_POST_PROCESS_NAME) && GUILayout.Button("场景后处理 (保存相机更改)"))
|
|
|
|
|
|
{
|
|
|
|
|
|
PostProcessScene(false);
|
|
|
|
|
|
}
|
2023-12-14 14:33:45 +08:00
|
|
|
|
}
|
2023-12-08 20:02:39 +08:00
|
|
|
|
}
|
2023-12-07 16:41:41 +08:00
|
|
|
|
|
2023-12-08 20:02:39 +08:00
|
|
|
|
private void ClearAllSceneObject()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var sObj in Target.sceneObjects)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (sObj)
|
|
|
|
|
|
DestroyImmediate(sObj.gameObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Target.sceneObjects.Clear();
|
2023-12-19 12:45:17 +08:00
|
|
|
|
MarkSceneDirty();
|
2023-12-08 20:02:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ClearUselessSceneObjects()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = Target.sceneObjects.Count - 1; i >= 0; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sObj = Target.sceneObjects[i];
|
|
|
|
|
|
if (sObj == null || sObj.renderInfo == null)
|
2023-12-07 18:40:32 +08:00
|
|
|
|
{
|
2023-12-08 20:02:39 +08:00
|
|
|
|
if (sObj != null)
|
|
|
|
|
|
DestroyImmediate(sObj.gameObject);
|
|
|
|
|
|
Target.sceneObjects.RemoveAt(i);
|
2023-12-07 18:40:32 +08:00
|
|
|
|
}
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|
2023-12-20 13:14:02 +08:00
|
|
|
|
|
2023-12-19 14:28:32 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-20 13:14:02 +08:00
|
|
|
|
|
2023-12-19 14:28:32 +08:00
|
|
|
|
ClearUselessSurfaceData();
|
|
|
|
|
|
MarkSceneDirty();
|
|
|
|
|
|
}
|
2024-01-05 14:48:47 +08:00
|
|
|
|
|
2024-01-04 17:22:36 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-22 16:10:43 +08:00
|
|
|
|
private void PostProcessScene(bool defaultCameraParam = true)
|
2024-01-04 17:22:36 +08:00
|
|
|
|
{
|
2025-08-26 19:00:29 +08:00
|
|
|
|
ObjectPostProcessorManager.Instance.PostProcess(Scene, false, defaultCameraParam);
|
2024-01-04 17:22:36 +08:00
|
|
|
|
}
|
2024-01-05 14:48:47 +08:00
|
|
|
|
|
2023-12-19 12:45:17 +08:00
|
|
|
|
private void MarkSceneDirty()
|
|
|
|
|
|
{
|
|
|
|
|
|
EditorSceneManager.MarkSceneDirty(Scene);
|
|
|
|
|
|
}
|
2023-12-19 14:28:32 +08:00
|
|
|
|
|
2023-12-08 20:02:39 +08:00
|
|
|
|
private void OnSceneGUI()
|
|
|
|
|
|
{
|
2023-12-21 19:08:04 +08:00
|
|
|
|
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)
|
2024-01-04 13:52:29 +08:00
|
|
|
|
sceneView.LookAt(Ground.transform.position, mainCam.transform.rotation);
|
2023-12-21 19:08:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Handles.EndGUI();
|
2023-12-12 20:03:44 +08:00
|
|
|
|
if (!_isEditingScene || _currBrush == null || !_currBrush.Valid || Application.isPlaying)
|
2023-12-08 20:02:39 +08:00
|
|
|
|
return;
|
|
|
|
|
|
var e = Event.current;
|
2023-12-09 22:06:08 +08:00
|
|
|
|
_currBrush.OnSceneGUI(e);
|
2023-12-08 20:02:39 +08:00
|
|
|
|
}
|
2023-12-07 16:41:41 +08:00
|
|
|
|
}
|