Unity 编辑器开发实战【Editor Window】- Duplicator复制机

举报
CoderZ1010 发表于 2022/09/25 04:49:51 2022/09/25
【摘要】 1.Name Duplicator:名称复制机(根据层级结构复制名称)   2.Material Duplicator:材质复制机(根据层级结构复制材质) 代码如下: namespace SK.Framework{ public interface IDuplicator { stri...

1.Name Duplicator:名称复制机(根据层级结构复制名称)

 

2.Material Duplicator:材质复制机(根据层级结构复制材质)

代码如下:


  
  1. namespace SK.Framework
  2. {
  3. public interface IDuplicator
  4. {
  5. string InvalidatedInfo { get; }
  6. bool IsValidated();
  7. void Duplicate();
  8. }
  9. }

  
  1. namespace SK.Framework
  2. {
  3. public abstract class AbstractDuplicator<T> : IDuplicator
  4. {
  5. public virtual string InvalidatedInfo
  6. {
  7. get
  8. {
  9. return "Is invalidated.";
  10. }
  11. }
  12. protected T from;
  13. protected T to;
  14. public abstract bool IsValidated();
  15. public abstract void Duplicate();
  16. }
  17. }

  
  1. using UnityEngine;
  2. using System.Text;
  3. using System.Collections.Generic;
  4. namespace SK.Framework
  5. {
  6. public class NameDuplicator : AbstractDuplicator<Transform>
  7. {
  8. private readonly Dictionary<string, Transform> fromHierarchy;
  9. private readonly Dictionary<string, Transform> toHierarchy;
  10. public override string InvalidatedInfo
  11. {
  12. get
  13. {
  14. return "Is invalidated:请先验证层级结构是否一致";
  15. }
  16. }
  17. public NameDuplicator(Transform from, Transform to)
  18. {
  19. this.from = from;
  20. this.to = to;
  21. fromHierarchy = new Dictionary<string, Transform>();
  22. toHierarchy = new Dictionary<string, Transform>();
  23. }
  24. //递归遍历From层级
  25. private void ForEachFromHierarchy(Transform t)
  26. {
  27. foreach (Transform child in t)
  28. {
  29. string fullName = GetFullName(child);
  30. fromHierarchy.Add(fullName, child);
  31. ForEachFromHierarchy(child);
  32. }
  33. }
  34. //递归遍历To层级
  35. private void ForEachToHierarchy(Transform t)
  36. {
  37. foreach (Transform child in t)
  38. {
  39. string fullName = GetFullName(child);
  40. toHierarchy.Add(fullName, child);
  41. ForEachToHierarchy(child);
  42. }
  43. }
  44. //获取层级结构
  45. private string GetFullName(Transform t)
  46. {
  47. const string flag = "hierarchy";
  48. List<Transform> tfs = new List<Transform>();
  49. Transform tf = t.transform;
  50. tfs.Add(tf);
  51. while (tf.parent)
  52. {
  53. tf = tf.parent;
  54. tfs.Add(tf);
  55. }
  56. StringBuilder sb = new StringBuilder();
  57. sb.Append($"{flag}{tfs[tfs.Count - 2].GetSiblingIndex()}");
  58. for (int i = tfs.Count - 3; i >= 0; i--)
  59. {
  60. sb.Append($"/{flag}{tfs[i].GetSiblingIndex()}");
  61. }
  62. return sb.ToString();
  63. }
  64. public override bool IsValidated()
  65. {
  66. ForEachFromHierarchy(from);
  67. ForEachToHierarchy(to);
  68. bool retV = true;
  69. retV &= fromHierarchy.Count == toHierarchy.Count;
  70. foreach (var kv in toHierarchy)
  71. {
  72. if (!fromHierarchy.ContainsKey(kv.Key))
  73. {
  74. retV = false;
  75. break;
  76. }
  77. }
  78. return retV;
  79. }
  80. public override void Duplicate()
  81. {
  82. foreach (var kv in toHierarchy)
  83. {
  84. kv.Value.name = fromHierarchy[kv.Key].name;
  85. }
  86. }
  87. }
  88. }

  
  1. using UnityEngine;
  2. using System.Text;
  3. using System.Collections.Generic;
  4. namespace SK.Framework
  5. {
  6. public class MaterialDuplicator : AbstractDuplicator<Transform>
  7. {
  8. private readonly Dictionary<string, Renderer> fromDic;
  9. private readonly Dictionary<string, Renderer> toDic;
  10. public MaterialDuplicator(Transform from, Transform to)
  11. {
  12. this.from = from;
  13. this.to = to;
  14. fromDic = new Dictionary<string, Renderer>();
  15. toDic = new Dictionary<string, Renderer>();
  16. }
  17. private void GetFromMeshRenderer()
  18. {
  19. Renderer[] renderers = from.GetComponentsInChildren<Renderer>(true);
  20. for(int i = 0; i < renderers.Length; i++)
  21. {
  22. Renderer renderer = renderers[i];
  23. fromDic.Add(GetFullName(renderer.transform), renderer);
  24. }
  25. }
  26. private void GetToMeshRenderer()
  27. {
  28. Renderer[] renderers = to.GetComponentsInChildren<Renderer>(true);
  29. for (int i = 0; i < renderers.Length; i++)
  30. {
  31. Renderer renderer = renderers[i];
  32. toDic.Add(GetFullName(renderer.transform), renderer);
  33. }
  34. }
  35. private string GetFullName(Transform t)
  36. {
  37. List<Transform> tfs = new List<Transform>();
  38. Transform tf = t.transform;
  39. tfs.Add(tf);
  40. while (tf.parent)
  41. {
  42. tf = tf.parent;
  43. tfs.Add(tf);
  44. }
  45. StringBuilder sb = new StringBuilder();
  46. sb.Append(tfs[tfs.Count - 2].name);
  47. for (int i = tfs.Count - 3; i >= 0; i--)
  48. {
  49. sb.Append("/" + tfs[i].name);
  50. }
  51. return sb.ToString();
  52. }
  53. public override bool IsValidated()
  54. {
  55. GetFromMeshRenderer();
  56. GetToMeshRenderer();
  57. bool retV = true;
  58. retV &= fromDic.Count == toDic.Count;
  59. foreach (var kv in toDic)
  60. {
  61. if (!fromDic.ContainsKey(kv.Key))
  62. {
  63. retV = false;
  64. break;
  65. }
  66. }
  67. return retV;
  68. }
  69. public override void Duplicate()
  70. {
  71. foreach (var kv in toDic)
  72. {
  73. kv.Value.sharedMaterials = fromDic[kv.Key].sharedMaterials;
  74. }
  75. }
  76. }
  77. }

  
  1. using UnityEngine;
  2. using UnityEditor;
  3. namespace SK.Framework
  4. {
  5. public class DuplicatorWindow : EditorWindow
  6. {
  7. [MenuItem("SKFramework/Duplicator")]
  8. private static void Open()
  9. {
  10. GetWindow<DuplicatorWindow>("Duplicator").Show();
  11. }
  12. private Transform from;
  13. private Transform to;
  14. private bool isValidated;
  15. private const float labelWidth = 80f;
  16. private enum Mode
  17. {
  18. Name,
  19. Material,
  20. }
  21. private Mode mode = Mode.Name;
  22. private IDuplicator duplicator;
  23. private void OnGUI()
  24. {
  25. OnModeGUI();
  26. OnFromToGUI();
  27. OnValidateGUI();
  28. OnDuplicateGUI();
  29. }
  30. private void OnModeGUI()
  31. {
  32. GUILayout.BeginHorizontal();
  33. GUILayout.Label("Mode", GUILayout.Width(labelWidth));
  34. mode = (Mode)EditorGUILayout.EnumPopup(mode);
  35. GUILayout.EndHorizontal();
  36. }
  37. private void OnFromToGUI()
  38. {
  39. //From
  40. GUILayout.BeginHorizontal();
  41. GUILayout.Label("From", GUILayout.Width(labelWidth));
  42. Transform newFrom = EditorGUILayout.ObjectField(from, typeof(Transform), true) as Transform;
  43. if (newFrom != from)
  44. {
  45. from = newFrom;
  46. isValidated = false;
  47. }
  48. GUILayout.EndHorizontal();
  49. //To
  50. GUILayout.BeginHorizontal();
  51. GUILayout.Label("To", GUILayout.Width(labelWidth));
  52. Transform newTo = EditorGUILayout.ObjectField(to, typeof(Transform), true) as Transform;
  53. if (newTo != to)
  54. {
  55. to = newTo;
  56. isValidated = false;
  57. }
  58. GUILayout.EndHorizontal();
  59. }
  60. private void OnValidateGUI()
  61. {
  62. GUI.enabled = from != null && to != null;
  63. if (GUILayout.Button("Validate"))
  64. {
  65. switch (mode)
  66. {
  67. case Mode.Name: duplicator = new NameDuplicator(from, to); break;
  68. case Mode.Material: duplicator = new MaterialDuplicator(from, to); break;
  69. default: break;
  70. }
  71. isValidated = duplicator.IsValidated();
  72. }
  73. GUI.enabled = true;
  74. if (duplicator != null && !isValidated)
  75. {
  76. EditorGUILayout.HelpBox(duplicator.InvalidatedInfo, MessageType.Warning);
  77. }
  78. }
  79. private void OnDuplicateGUI()
  80. {
  81. GUI.enabled = isValidated;
  82. if (GUILayout.Button("Duplicate"))
  83. {
  84. duplicator.Duplicate();
  85. EditorUtility.SetDirty(to);
  86. }
  87. }
  88. }
  89. }

文章来源: coderz.blog.csdn.net,作者:CoderZ1010,版权归原作者所有,如需转载,请联系作者。

原文链接:coderz.blog.csdn.net/article/details/123775027

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。