SHARE
TWEET

Untitled

a guest Jun 16th, 2019 55 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.     public override void OnEnable()
  78.     {
  79.         base.OnEnable();
  80.  
  81.         if (assetTargets == null) return;
  82.  
  83.         if (assetTargets.Length <= 1)
  84.         {
  85.             var targets = (assetTarget as GameObject).GetComponents<Component>();
  86.             targetEditors = new Editor[targets.Length + 1];
  87.             assetTarget.hideFlags = HideFlags.None;
  88.             targetEditors[0] = CreateEditor(assetTarget);
  89.             for (int i = 0; i < targets.Length; i++)
  90.             {
  91.                 targets[i].hideFlags = HideFlags.None; //This is the magic that makes them editable, by default they are set to NonEditable.
  92.                 targetEditors[i + 1] = CreateEditor(targets[i]);
  93.             }
  94.         }
  95.         else //multiple
  96.         {
  97.             //Get all components that are shared on all objects
  98.             var commonComponents = assetTargets.SelectMany(a => (a as GameObject).GetComponents<Component>()).GroupBy(c => c.GetType()).Where(g => g.Count() > 1);
  99.  
  100.             foreach (var t in assetTargets) t.hideFlags = HideFlags.None;
  101.  
  102.             targetEditors = new Editor[commonComponents.Count() + 1];
  103.             targetEditors[0] = CreateEditor(assetTargets);
  104.  
  105.             int i = 1;
  106.             foreach (var group in commonComponents)
  107.             {
  108.                 foreach (var c in group)
  109.                     c.hideFlags = HideFlags.None;
  110.                 targetEditors[i++] = CreateEditor(group.ToArray());
  111.             }
  112.         }
  113.     }
  114.    
  115.     public override void OnInspectorGUI()
  116.     {
  117.         for (int i = 0; i < targetEditors.Length; i++)
  118.         {
  119.             EditorGUIUtility.labelWidth = 0;
  120.             targetEditors[i].DrawHeader();
  121.  
  122.             EditorGUI.BeginChangeCheck();
  123.             targetEditors[i].OnInspectorGUI();
  124.  
  125.             //When the object is changed it is reimported, and our editors point to incorrect objects. Restart to create new editors!
  126.             if (EditorGUI.EndChangeCheck())
  127.             {
  128.                 OnEnable();
  129.                 return;
  130.             }
  131.         }
  132.  
  133.         using (new EditorGUI.DisabledScope(assetTargets.Length > 1))
  134.         {
  135.             if (GUILayout.Button("Open Prefab"))
  136.             {
  137.                 AssetDatabase.OpenAsset(assetTarget);
  138.  
  139.                 GUIUtility.ExitGUI();
  140.             }
  141.         }
  142.     }
  143.     protected override void OnHeaderGUI() { }
  144.     public override bool showImportedObject { get { return false; } }
  145.     #endregion
  146. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top