Files
JJBB/Assets/Project/Script/Shader/Editor/SceneBlockDivideEditor.cs

104 lines
4.3 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
[CustomEditor(typeof(SceneBlockDivide))]
public class SceneBlockDivideEditor : Editor
{
private const string rootFormat = "Root_{0} ({1}, {2})";
private const string multiMaterialRoot = "MultipleMaterials";
private SceneBlockDivide mTarget;
private int mLastBlockWidth;
private Rect mapRect;
private MonoScript script;
private void OnEnable()
{
mTarget = (SceneBlockDivide)target;
script = MonoScript.FromMonoBehaviour(mTarget);
mLastBlockWidth = Mathf.Max(1, mTarget.blockWidth);
RefreshSceneSize();
}
public override void OnInspectorGUI()
{
script = EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false) as MonoScript;
mTarget.blockWidth = EditorGUILayout.IntField("Block Width", mTarget.blockWidth);
if (mTarget.blockWidth >= 1 && mTarget.blockWidth != mLastBlockWidth)
mLastBlockWidth = mTarget.blockWidth;
var widthTiles = Mathf.CeilToInt(mapRect.width / mLastBlockWidth);
var heightTiles = Mathf.CeilToInt(mapRect.height / mLastBlockWidth);
EditorGUILayout.LabelField(string.Format("Width: {0}", widthTiles));
EditorGUILayout.LabelField(string.Format("Height: {0}", heightTiles));
if (GUILayout.Button("Refresh Scene", GUILayout.Width(100f)))
RefreshSceneSize();
GUILayout.Space(10f);
if (GUILayout.Button("Divide Blocks", GUILayout.Width(100f)))
{
var meshRenderers = GetMeshRenderers();
for (int i = 0; i < meshRenderers.Length; i++)
{
var multiShaders = false;
var meshRenderer = meshRenderers[i];
if (meshRenderer.sharedMaterials.Length > 1)
{
// 如果多个材质是同一个Shader则视为普通物体否则视为特殊物体
for (int j = 1; j < meshRenderer.sharedMaterials.Length; j++)
{
if (meshRenderer.sharedMaterials[j - 1].shader != meshRenderer.sharedMaterials[j].shader)
{
multiShaders = true;
break;
}
}
}
if (multiShaders)
{
var root = GetRoot(multiMaterialRoot, 0, 0);
meshRenderer.transform.SetParent(root);
}
else
{
var x = Mathf.FloorToInt((meshRenderer.bounds.min.x - mapRect.min.x) / mLastBlockWidth);
var z = Mathf.FloorToInt((meshRenderer.bounds.min.z - mapRect.min.y) / mLastBlockWidth);
var root = GetRoot(meshRenderer.sharedMaterial.shader.name, x, z);
meshRenderer.transform.SetParent(root);
}
}
}
}
private void RefreshSceneSize()
{
var meshRenderers = GetMeshRenderers();
if (meshRenderers.Length == 0)
mapRect = new Rect();
else
{
var bounds = meshRenderers[0].bounds;
for (int i = 1; i < meshRenderers.Length; i++)
bounds.Encapsulate(meshRenderers[i].bounds);
mapRect = new Rect(bounds.min.x, bounds.min.z, bounds.size.x, bounds.size.z);
}
}
private MeshRenderer[] GetMeshRenderers()
{
var meshRenderers = Object.FindObjectsOfType<MeshRenderer>();
var meshRenderList = new List<MeshRenderer>();
for (int i = 0; i < meshRenderers.Length; i++)
{
if (meshRenderers[i].gameObject.tag != "SkyBox")
meshRenderList.Add(meshRenderers[i]);
}
return meshRenderList.ToArray();
}
private static Transform GetRoot(string name, int x, int z)
{
var rootName = string.Format(rootFormat, name, x, z);
var rootObj = GameObject.Find(rootName);
if (rootObj == null)
{
rootObj = new GameObject(rootName);
rootObj.transform.localPosition = Vector3.zero;
rootObj.transform.localRotation = Quaternion.identity;
rootObj.transform.localScale = Vector3.one;
}
return rootObj.transform;
}
}