Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEditor;
- using UnityEditor.Experimental.AssetImporters;
- using UnityEngine;
- using System.Reflection;
- using System;
- using System.Collections;
- using System.Linq;
- using Object = UnityEngine.Object;
- using System.Collections.Generic;
- public class CustomPrefabImporterEditor : AssetImporterEditor
- {
- #region Injection
- /*
- * See Editor/Mono/CustomEditorAttributes.cs for original logic of getting an editor by type. The UnityEditor.CustomEditorAttributes class handles this
- *
- * We sneak ourselfs in by
- * 1. Call FindCustomEditorTypeByType to initialize state
- * 2. Modify the kSCustomEditors and kSCustomMultiEditors lists with our class for the type 'UnityEditor.PrefabImporter'
- * 3. ??
- * 4. Profit!
- */
- //We have to find the types in this assembly
- private static readonly Assembly editorAssembly = Assembly.GetAssembly(typeof(AssetImporterEditor));
- private static readonly string customEditorAttributes = "UnityEditor.CustomEditorAttributes",
- findCustomEditorTypeByType = "FindCustomEditorTypeByType",
- kSCustomEditors = "kSCustomEditors",
- kSCustomMultiEditors = "kSCustomMultiEditors",
- prefabImporter = "PrefabImporter",
- m_InspectorType = "m_InspectorType";
- [InitializeOnLoadMethod]
- private static void inject()
- {
- callPrivateStaticMethod(customEditorAttributes, findCustomEditorTypeByType, null, false); //null as type to get does an early out.
- var editorTypeDictionary = getPrivateStaticField<ICollection>(customEditorAttributes, kSCustomEditors);
- //editorTypeKey is of type KeyValuePair<Type, List<UnityEditor.CustomEditorAttributes.MonoEditorType>>, but we cant cast it. Reflection all the way!
- foreach (var editorTypeDictEntry in editorTypeDictionary)
- {
- if (getPublicProperty<Type>(editorTypeDictEntry, "Key").Name != prefabImporter) continue; //Only our importer
- //editor is of type UnityEditor.CustomEditorAttribute.MonoEditorType
- foreach (var editor in getPublicProperty<IList>(editorTypeDictEntry, "Value"))
- setPublicField(editor, m_InspectorType, typeof(CustomPrefabImporterEditor));
- }
- }
- private static object callPrivateStaticMethod(string typeName, string methodName, params object[] parameters)
- {
- var type = editorAssembly.GetType(typeName, true);
- var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);
- return method.Invoke(null, parameters);
- }
- private static T getPrivateStaticField<T>(string typeName, string fieldName)
- {
- var type = editorAssembly.GetType(typeName, true);
- var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static);
- return (T)field.GetValue(null);
- }
- private static T getPublicProperty<T>(object target, string fieldName)
- {
- return (T)target.GetType().GetProperty(fieldName, BindingFlags.Public | BindingFlags.Instance).GetValue(target);
- }
- public static void setPublicField(object target, string fieldName, object value)
- {
- target.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.Instance).SetValue(target, value);
- }
- #endregion
- #region Inspector GUI
- private Editor[] targetEditors;
- private bool[] folds;
- public override void OnEnable()
- {
- base.OnEnable();
- if (assetTargets == null) return;
- if (assetTargets.Length <= 1)
- {
- var targets = (assetTarget as GameObject).GetComponents<Component>();
- targetEditors = new Editor[targets.Length + 1];
- folds = new bool[targetEditors.Length];
- for( int f = 0; f < folds.Length; f++ ) { folds[f] = true; }
- assetTarget.hideFlags = HideFlags.None;
- targetEditors[0] = CreateEditor(assetTarget);
- for (int i = 0; i < targets.Length; i++)
- {
- if( targets[i] == null ) { continue; }
- targets[i].hideFlags = HideFlags.None; //This is the magic that makes them editable, by default they are set to NonEditable.
- targetEditors[i + 1] = CreateEditor(targets[i]);
- }
- }
- else //multiple
- {
- //Get all components that are shared on all objects
- var commonComponents = assetTargets.SelectMany(a => (a as GameObject).GetComponents<Component>()).GroupBy(c => c.GetType()).Where(g => g.Count() > 1);
- foreach (var t in assetTargets) t.hideFlags = HideFlags.None;
- targetEditors = new Editor[commonComponents.Count() + 1];
- targetEditors[0] = CreateEditor(assetTargets);
- folds = new bool[targetEditors.Length];
- for( int f = 0; f < folds.Length; f++ ) { folds[f] = true; }
- int i = 1;
- foreach (var group in commonComponents)
- {
- foreach (var c in group)
- c.hideFlags = HideFlags.None;
- targetEditors[i++] = CreateEditor(group.ToArray());
- }
- }
- }
- public override void OnInspectorGUI()
- {
- string[] splits;
- for (int i = 0; i < targetEditors.Length; i++)
- {
- if( targetEditors[i] == null ) { continue; }
- if( targetEditors[i].target is GameObject )
- {
- targetEditors[i].DrawHeader();
- }
- else
- {
- folds[i] = EditorGUILayout.InspectorTitlebar( folds[i], targetEditors[i].target );
- }
- if( folds[i] )
- {
- EditorGUI.BeginChangeCheck();
- targetEditors[i].OnInspectorGUI();
- EditorGUIUtility.LookLikeControls( 150.0f );
- //When the object is changed it is reimported, and our editors point to incorrect objects. Restart to create new editors!
- if (EditorGUI.EndChangeCheck())
- {
- OnEnable();
- return;
- }
- }
- }
- for( int i = 0; i < 5; i++ ) { EditorGUILayout.Space(); }
- using (new EditorGUI.DisabledScope(assetTargets.Length > 1))
- {
- if (GUILayout.Button("Open Prefab"))
- {
- AssetDatabase.OpenAsset(assetTarget);
- GUIUtility.ExitGUI();
- }
- }
- }
- protected override void OnHeaderGUI() { }
- public override bool showImportedObject { get { return false; } }
- #endregion
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement