104 lines
4.3 KiB
C#
104 lines
4.3 KiB
C#
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;
|
||
}
|
||
} |