Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.51 KB | None | 0 0
  1. using UnityEditor;
  2. using UnityEditor.Experimental.AssetImporters;
  3. using UnityEngine;
  4. using System.Reflection;
  5. using System;
  6. using System.Collections;
  7. using System.Linq;
  8. using Object = UnityEngine.Object;
  9. using System.Collections.Generic;
  10.  
  11. public class CustomPrefabImporterEditor : AssetImporterEditor
  12. {
  13. #region Injection
  14. /*
  15. * See Editor/Mono/CustomEditorAttributes.cs for original logic of getting an editor by type. The UnityEditor.CustomEditorAttributes class handles this
  16. *
  17. * We sneak ourselfs in by
  18. * 1. Call FindCustomEditorTypeByType to initialize state
  19. * 2. Modify the kSCustomEditors and kSCustomMultiEditors lists with our class for the type 'UnityEditor.PrefabImporter'
  20. * 3. ??
  21. * 4. Profit!
  22. */
  23.  
  24. //We have to find the types in this assembly
  25. private static readonly Assembly editorAssembly = Assembly.GetAssembly(typeof(AssetImporterEditor));
  26. private static readonly string customEditorAttributes = "UnityEditor.CustomEditorAttributes",
  27. findCustomEditorTypeByType = "FindCustomEditorTypeByType",
  28. kSCustomEditors = "kSCustomEditors",
  29. kSCustomMultiEditors = "kSCustomMultiEditors",
  30. prefabImporter = "PrefabImporter",
  31. m_InspectorType = "m_InspectorType";
  32. [InitializeOnLoadMethod]
  33. private static void inject()
  34. {
  35. callPrivateStaticMethod(customEditorAttributes, findCustomEditorTypeByType, null, false); //null as type to get does an early out.
  36.  
  37. var editorTypeDictionary = getPrivateStaticField<ICollection>(customEditorAttributes, kSCustomEditors);
  38.  
  39. //editorTypeKey is of type KeyValuePair<Type, List<UnityEditor.CustomEditorAttributes.MonoEditorType>>, but we cant cast it. Reflection all the way!
  40. foreach (var editorTypeDictEntry in editorTypeDictionary)
  41. {
  42. if (getPublicProperty<Type>(editorTypeDictEntry, "Key").Name != prefabImporter) continue; //Only our importer
  43.  
  44. //editor is of type UnityEditor.CustomEditorAttribute.MonoEditorType
  45. foreach (var editor in getPublicProperty<IList>(editorTypeDictEntry, "Value"))
  46. setPublicField(editor, m_InspectorType, typeof(CustomPrefabImporterEditor));
  47. }
  48. }
  49.  
  50. private static object callPrivateStaticMethod(string typeName, string methodName, params object[] parameters)
  51. {
  52. var type = editorAssembly.GetType(typeName, true);
  53. var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);
  54.  
  55. return method.Invoke(null, parameters);
  56. }
  57. private static T getPrivateStaticField<T>(string typeName, string fieldName)
  58. {
  59. var type = editorAssembly.GetType(typeName, true);
  60. var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static);
  61. return (T)field.GetValue(null);
  62. }
  63.  
  64. private static T getPublicProperty<T>(object target, string fieldName)
  65. {
  66. return (T)target.GetType().GetProperty(fieldName, BindingFlags.Public | BindingFlags.Instance).GetValue(target);
  67. }
  68. public static void setPublicField(object target, string fieldName, object value)
  69. {
  70. target.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.Instance).SetValue(target, value);
  71. }
  72.  
  73. #endregion
  74.  
  75. #region Inspector GUI
  76. private Editor[] targetEditors;
  77. private bool[] folds;
  78. public override void OnEnable()
  79. {
  80. base.OnEnable();
  81.  
  82. if (assetTargets == null) return;
  83.  
  84. if (assetTargets.Length <= 1)
  85. {
  86. var targets = (assetTarget as GameObject).GetComponents<Component>();
  87. targetEditors = new Editor[targets.Length + 1];
  88. folds = new bool[targetEditors.Length];
  89. for( int f = 0; f < folds.Length; f++ ) { folds[f] = true; }
  90. assetTarget.hideFlags = HideFlags.None;
  91. targetEditors[0] = CreateEditor(assetTarget);
  92. for (int i = 0; i < targets.Length; i++)
  93. {
  94. if( targets[i] == null ) { continue; }
  95. targets[i].hideFlags = HideFlags.None; //This is the magic that makes them editable, by default they are set to NonEditable.
  96. targetEditors[i + 1] = CreateEditor(targets[i]);
  97. }
  98. }
  99. else //multiple
  100. {
  101. //Get all components that are shared on all objects
  102. var commonComponents = assetTargets.SelectMany(a => (a as GameObject).GetComponents<Component>()).GroupBy(c => c.GetType()).Where(g => g.Count() > 1);
  103.  
  104. foreach (var t in assetTargets) t.hideFlags = HideFlags.None;
  105.  
  106. targetEditors = new Editor[commonComponents.Count() + 1];
  107. targetEditors[0] = CreateEditor(assetTargets);
  108.  
  109. folds = new bool[targetEditors.Length];
  110. for( int f = 0; f < folds.Length; f++ ) { folds[f] = true; }
  111.  
  112. int i = 1;
  113. foreach (var group in commonComponents)
  114. {
  115. foreach (var c in group)
  116. c.hideFlags = HideFlags.None;
  117. targetEditors[i++] = CreateEditor(group.ToArray());
  118. }
  119. }
  120. }
  121.  
  122. public override void OnInspectorGUI()
  123. {
  124. string[] splits;
  125. for (int i = 0; i < targetEditors.Length; i++)
  126. {
  127. if( targetEditors[i] == null ) { continue; }
  128.  
  129. if( targetEditors[i].target is GameObject )
  130. {
  131. targetEditors[i].DrawHeader();
  132. }
  133. else
  134. {
  135. folds[i] = EditorGUILayout.InspectorTitlebar( folds[i], targetEditors[i].target );
  136. }
  137.  
  138. if( folds[i] )
  139. {
  140. EditorGUI.BeginChangeCheck();
  141. targetEditors[i].OnInspectorGUI();
  142.  
  143. EditorGUIUtility.LookLikeControls( 150.0f );
  144.  
  145. //When the object is changed it is reimported, and our editors point to incorrect objects. Restart to create new editors!
  146. if (EditorGUI.EndChangeCheck())
  147. {
  148. OnEnable();
  149. return;
  150. }
  151. }
  152. }
  153.  
  154. for( int i = 0; i < 5; i++ ) { EditorGUILayout.Space(); }
  155.  
  156. using (new EditorGUI.DisabledScope(assetTargets.Length > 1))
  157. {
  158. if (GUILayout.Button("Open Prefab"))
  159. {
  160. AssetDatabase.OpenAsset(assetTarget);
  161.  
  162. GUIUtility.ExitGUI();
  163. }
  164. }
  165. }
  166. protected override void OnHeaderGUI() { }
  167. public override bool showImportedObject { get { return false; } }
  168. #endregion
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement