using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.Linq; using System.Reflection; /// /// A base class for creating editors that decorate Unity's built-in editor types. /// public abstract class DecoratorEditor : Editor { // empty array for invoking methods using reflection private static readonly object[] EMPTY_ARRAY = new object[0]; #region Editor Fields /// /// Type object for the internally used (decorated) editor. /// private System.Type decoratedEditorType; /// /// Type object for the object that is edited by this editor. /// private System.Type editedObjectType; private Editor editorInstance; #endregion private static Dictionary decoratedMethods = new Dictionary(); private static Assembly editorAssembly = Assembly.GetAssembly(typeof(Editor)); protected Editor EditorInstance { get { if (editorInstance == null && targets != null && targets.Length > 0) { editorInstance = Editor.CreateEditor(targets, decoratedEditorType); } if (editorInstance == null) { Debug.LogError("Could not create editor !"); } return editorInstance; } } public DecoratorEditor(string editorTypeName) { this.decoratedEditorType = editorAssembly.GetTypes().Where(t => t.Name == editorTypeName).FirstOrDefault(); Init(); // Check CustomEditor types. var originalEditedType = GetCustomEditorType(decoratedEditorType); if (originalEditedType != editedObjectType) { throw new System.ArgumentException( string.Format("Type {0} does not match the editor {1} type {2}", editedObjectType, editorTypeName, originalEditedType)); } } private System.Type GetCustomEditorType(System.Type type) { var flags = BindingFlags.NonPublic | BindingFlags.Instance; var attributes = type.GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[]; var field = attributes.Select(editor => editor.GetType().GetField("m_InspectedType", flags)).First(); return field.GetValue(attributes[0]) as System.Type; } private void Init() { var flags = BindingFlags.NonPublic | BindingFlags.Instance; var attributes = this.GetType().GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[]; var field = attributes.Select(editor => editor.GetType().GetField("m_InspectedType", flags)).First(); editedObjectType = field.GetValue(attributes[0]) as System.Type; } void OnDisable() { if (editorInstance != null) { DestroyImmediate(editorInstance); } } /// /// Delegates a method call with the given name to the decorated editor instance. /// protected void CallInspectorMethod(string methodName) { MethodInfo method = null; // Add MethodInfo to cache if (!decoratedMethods.ContainsKey(methodName)) { var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; method = decoratedEditorType.GetMethod(methodName, flags); if (method != null) { decoratedMethods[methodName] = method; } else { Debug.LogError(string.Format("Could not find method {0}", method)); } } else { method = decoratedMethods[methodName]; } if (method != null) { method.Invoke(EditorInstance, EMPTY_ARRAY); } } public void OnSceneGUI() { CallInspectorMethod("OnSceneGUI"); } protected override void OnHeaderGUI() { CallInspectorMethod("OnHeaderGUI"); } public override void OnInspectorGUI() { EditorInstance.OnInspectorGUI(); } public override void DrawPreview(Rect previewArea) { EditorInstance.DrawPreview(previewArea); } public override string GetInfoString() { return EditorInstance.GetInfoString(); } public override GUIContent GetPreviewTitle() { return EditorInstance.GetPreviewTitle(); } public override bool HasPreviewGUI() { return EditorInstance.HasPreviewGUI(); } public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) { EditorInstance.OnInteractivePreviewGUI(r, background); } public override void OnPreviewGUI(Rect r, GUIStyle background) { EditorInstance.OnPreviewGUI(r, background); } public override void OnPreviewSettings() { EditorInstance.OnPreviewSettings(); } public override void ReloadPreviewInstances() { EditorInstance.ReloadPreviewInstances(); } public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) { return EditorInstance.RenderStaticPreview(assetPath, subAssets, width, height); } public override bool RequiresConstantRepaint() { return true; } public override bool UseDefaultMargins() { return EditorInstance.UseDefaultMargins(); } } public class RCKCustomiziationEditor : Editor { public override bool RequiresConstantRepaint() { return true; } public override void ReloadPreviewInstances() { base.ReloadPreviewInstances(); } public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) { base.OnInteractivePreviewGUI(r, background); } public override void OnPreviewSettings() { base.OnPreviewSettings(); } }