1.Name Duplicator:名称复制机(根据层级结构复制名称)
2.Material Duplicator:材质复制机(根据层级结构复制材质)
代码如下:
代码语言:javascript复制namespace SK.Framework
{
public interface IDuplicator
{
string InvalidatedInfo { get; }
bool IsValidated();
void Duplicate();
}
}
代码语言:javascript复制
代码语言:javascript复制namespace SK.Framework
{
public abstract class AbstractDuplicator<T> : IDuplicator
{
public virtual string InvalidatedInfo
{
get
{
return "Is invalidated.";
}
}
protected T from;
protected T to;
public abstract bool IsValidated();
public abstract void Duplicate();
}
}
代码语言:javascript复制using UnityEngine;
using System.Text;
using System.Collections.Generic;
namespace SK.Framework
{
public class NameDuplicator : AbstractDuplicator<Transform>
{
private readonly Dictionary<string, Transform> fromHierarchy;
private readonly Dictionary<string, Transform> toHierarchy;
public override string InvalidatedInfo
{
get
{
return "Is invalidated:请先验证层级结构是否一致";
}
}
public NameDuplicator(Transform from, Transform to)
{
this.from = from;
this.to = to;
fromHierarchy = new Dictionary<string, Transform>();
toHierarchy = new Dictionary<string, Transform>();
}
//递归遍历From层级
private void ForEachFromHierarchy(Transform t)
{
foreach (Transform child in t)
{
string fullName = GetFullName(child);
fromHierarchy.Add(fullName, child);
ForEachFromHierarchy(child);
}
}
//递归遍历To层级
private void ForEachToHierarchy(Transform t)
{
foreach (Transform child in t)
{
string fullName = GetFullName(child);
toHierarchy.Add(fullName, child);
ForEachToHierarchy(child);
}
}
//获取层级结构
private string GetFullName(Transform t)
{
const string flag = "hierarchy";
List<Transform> tfs = new List<Transform>();
Transform tf = t.transform;
tfs.Add(tf);
while (tf.parent)
{
tf = tf.parent;
tfs.Add(tf);
}
StringBuilder sb = new StringBuilder();
sb.Append($"{flag}{tfs[tfs.Count - 2].GetSiblingIndex()}");
for (int i = tfs.Count - 3; i >= 0; i--)
{
sb.Append($"/{flag}{tfs[i].GetSiblingIndex()}");
}
return sb.ToString();
}
public override bool IsValidated()
{
ForEachFromHierarchy(from);
ForEachToHierarchy(to);
bool retV = true;
retV &= fromHierarchy.Count == toHierarchy.Count;
foreach (var kv in toHierarchy)
{
if (!fromHierarchy.ContainsKey(kv.Key))
{
retV = false;
break;
}
}
return retV;
}
public override void Duplicate()
{
foreach (var kv in toHierarchy)
{
kv.Value.name = fromHierarchy[kv.Key].name;
}
}
}
}
代码语言:javascript复制using UnityEngine;
using System.Text;
using System.Collections.Generic;
namespace SK.Framework
{
public class MaterialDuplicator : AbstractDuplicator<Transform>
{
private readonly Dictionary<string, Renderer> fromDic;
private readonly Dictionary<string, Renderer> toDic;
public MaterialDuplicator(Transform from, Transform to)
{
this.from = from;
this.to = to;
fromDic = new Dictionary<string, Renderer>();
toDic = new Dictionary<string, Renderer>();
}
private void GetFromMeshRenderer()
{
Renderer[] renderers = from.GetComponentsInChildren<Renderer>(true);
for(int i = 0; i < renderers.Length; i )
{
Renderer renderer = renderers[i];
fromDic.Add(GetFullName(renderer.transform), renderer);
}
}
private void GetToMeshRenderer()
{
Renderer[] renderers = to.GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < renderers.Length; i )
{
Renderer renderer = renderers[i];
toDic.Add(GetFullName(renderer.transform), renderer);
}
}
private string GetFullName(Transform t)
{
List<Transform> tfs = new List<Transform>();
Transform tf = t.transform;
tfs.Add(tf);
while (tf.parent)
{
tf = tf.parent;
tfs.Add(tf);
}
StringBuilder sb = new StringBuilder();
sb.Append(tfs[tfs.Count - 2].name);
for (int i = tfs.Count - 3; i >= 0; i--)
{
sb.Append("/" tfs[i].name);
}
return sb.ToString();
}
public override bool IsValidated()
{
GetFromMeshRenderer();
GetToMeshRenderer();
bool retV = true;
retV &= fromDic.Count == toDic.Count;
foreach (var kv in toDic)
{
if (!fromDic.ContainsKey(kv.Key))
{
retV = false;
break;
}
}
return retV;
}
public override void Duplicate()
{
foreach (var kv in toDic)
{
kv.Value.sharedMaterials = fromDic[kv.Key].sharedMaterials;
}
}
}
}
代码语言:javascript复制
代码语言:javascript复制using UnityEngine;
using UnityEditor;
namespace SK.Framework
{
public class DuplicatorWindow : EditorWindow
{
[MenuItem("SKFramework/Duplicator")]
private static void Open()
{
GetWindow<DuplicatorWindow>("Duplicator").Show();
}
private Transform from;
private Transform to;
private bool isValidated;
private const float labelWidth = 80f;
private enum Mode
{
Name,
Material,
}
private Mode mode = Mode.Name;
private IDuplicator duplicator;
private void OnGUI()
{
OnModeGUI();
OnFromToGUI();
OnValidateGUI();
OnDuplicateGUI();
}
private void OnModeGUI()
{
GUILayout.BeginHorizontal();
GUILayout.Label("Mode", GUILayout.Width(labelWidth));
mode = (Mode)EditorGUILayout.EnumPopup(mode);
GUILayout.EndHorizontal();
}
private void OnFromToGUI()
{
//From
GUILayout.BeginHorizontal();
GUILayout.Label("From", GUILayout.Width(labelWidth));
Transform newFrom = EditorGUILayout.ObjectField(from, typeof(Transform), true) as Transform;
if (newFrom != from)
{
from = newFrom;
isValidated = false;
}
GUILayout.EndHorizontal();
//To
GUILayout.BeginHorizontal();
GUILayout.Label("To", GUILayout.Width(labelWidth));
Transform newTo = EditorGUILayout.ObjectField(to, typeof(Transform), true) as Transform;
if (newTo != to)
{
to = newTo;
isValidated = false;
}
GUILayout.EndHorizontal();
}
private void OnValidateGUI()
{
GUI.enabled = from != null && to != null;
if (GUILayout.Button("Validate"))
{
switch (mode)
{
case Mode.Name: duplicator = new NameDuplicator(from, to); break;
case Mode.Material: duplicator = new MaterialDuplicator(from, to); break;
default: break;
}
isValidated = duplicator.IsValidated();
}
GUI.enabled = true;
if (duplicator != null && !isValidated)
{
EditorGUILayout.HelpBox(duplicator.InvalidatedInfo, MessageType.Warning);
}
}
private void OnDuplicateGUI()
{
GUI.enabled = isValidated;
if (GUILayout.Button("Duplicate"))
{
duplicator.Duplicate();
EditorUtility.SetDirty(to);
}
}
}
}