InterfacePicker.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using Rokid.UXR.Interaction;
  5. namespace Rokid.UXR.Editor
  6. {
  7. public class InterfacePicker : EditorWindow
  8. {
  9. private class MonoInspector
  10. {
  11. public readonly MonoBehaviour Mono;
  12. public readonly UnityEditor.Editor Editor;
  13. public MonoInspector(MonoBehaviour mono)
  14. {
  15. Mono = mono;
  16. Editor = UnityEditor.Editor.CreateEditor(mono);
  17. }
  18. public void Destroy()
  19. {
  20. DestroyImmediate(Editor);
  21. }
  22. }
  23. private static class GUIStyles
  24. {
  25. public static readonly GUIStyle Default;
  26. public static readonly GUIStyle Window;
  27. public static readonly GUIStyle Inspector;
  28. private static readonly RectOffset padding =
  29. new RectOffset(EDGE_PADDING_PX,
  30. EDGE_PADDING_PX,
  31. EDGE_PADDING_PX,
  32. EDGE_PADDING_PX);
  33. static GUIStyles()
  34. {
  35. Default = new GUIStyle();
  36. Window = new GUIStyle(Default);
  37. Window.padding = padding;
  38. Inspector = new GUIStyle(GUI.skin.window);
  39. Inspector.padding = padding;
  40. }
  41. }
  42. private const float SELECT_BUTTON_HEIGHT_PX = 32f;
  43. private const float LABEL_COLUMN_RATIO = 0.4f;
  44. private const int EDGE_PADDING_PX = 8;
  45. public static bool AnyOpen => HasOpenInstances<InterfacePicker>();
  46. private Object _target;
  47. private string _propertyPath;
  48. private List<MonoInspector> _monoInspectors;
  49. private Vector2 _scrollPos = Vector2.zero;
  50. public static void Show(SerializedProperty prop, List<MonoBehaviour> monos)
  51. {
  52. if (monos == null ||
  53. monos.Count == 0 ||
  54. prop == null)
  55. {
  56. return;
  57. }
  58. InterfacePicker picker = GetWindow<InterfacePicker>(true);
  59. picker._propertyPath = prop.propertyPath;
  60. picker._target = prop.serializedObject.targetObject;
  61. picker._monoInspectors?.ForEach((mi) => mi.Destroy());
  62. picker._monoInspectors = new List<MonoInspector>();
  63. picker.titleContent = new GUIContent(monos[0].gameObject.name);
  64. monos.ForEach((m) => picker._monoInspectors.Add(new MonoInspector(m)));
  65. picker.ShowUtility();
  66. }
  67. private void OnGUI()
  68. {
  69. if (_target == null)
  70. {
  71. Close();
  72. return;
  73. }
  74. Prune();
  75. DrawAll();
  76. }
  77. private void OnDestroy()
  78. {
  79. _monoInspectors.ForEach((mi) => mi.Destroy());
  80. }
  81. private void Prune()
  82. {
  83. _monoInspectors.FindAll((m) => m.Mono == null).ForEach((mi) =>
  84. {
  85. _monoInspectors.Remove(mi);
  86. mi.Destroy();
  87. });
  88. }
  89. private void DrawAll()
  90. {
  91. _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUIStyles.Window);
  92. foreach (var monoInspector in _monoInspectors)
  93. {
  94. EditorGUILayout.Separator();
  95. EditorGUILayout.BeginVertical(GUIStyles.Inspector);
  96. DrawHeader(monoInspector);
  97. EditorGUILayout.Separator();
  98. DrawComponent(monoInspector);
  99. EditorGUILayout.EndVertical();
  100. }
  101. GUILayout.FlexibleSpace();
  102. EditorGUILayout.EndScrollView();
  103. }
  104. private void DrawHeader(MonoInspector monoInspector)
  105. {
  106. if (GUILayout.Button($"{monoInspector.Mono.GetType().Name}",
  107. GUILayout.Height(SELECT_BUTTON_HEIGHT_PX)))
  108. {
  109. Apply(monoInspector.Mono);
  110. Close();
  111. }
  112. }
  113. private void DrawComponent(MonoInspector monoInspector)
  114. {
  115. GUI.enabled = false;
  116. EditorGUIUtility.labelWidth = position.width * LABEL_COLUMN_RATIO;
  117. monoInspector.Editor.OnInspectorGUI();
  118. GUI.enabled = true;
  119. }
  120. private void Apply(MonoBehaviour mono)
  121. {
  122. SerializedProperty property =
  123. new SerializedObject(_target).FindProperty(_propertyPath);
  124. property.objectReferenceValue = mono;
  125. property.serializedObject.ApplyModifiedProperties();
  126. }
  127. }
  128. }