Files
JJBB/Assets/Project/Script/Shader/Editor/SceneBlockDivideEditor.cs
2024-08-23 15:49:34 +08:00

104 lines
4.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}