Last active
October 21, 2024 10:03
-
-
Save liortal53/352fda2d01d339306e03 to your computer and use it in GitHub Desktop.
Extend Unity's built-in inspectors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using UnityEditor; | |
using UnityEngine; | |
/// <summary> | |
/// A base class for creating editors that decorate Unity's built-in editor types. | |
/// </summary> | |
public abstract class DecoratorEditor : Editor | |
{ | |
// empty array for invoking methods using reflection | |
private static readonly object[] EMPTY_ARRAY = new object[0]; | |
#region Editor Fields | |
/// <summary> | |
/// Type object for the internally used (decorated) editor. | |
/// </summary> | |
private System.Type decoratedEditorType; | |
/// <summary> | |
/// Type object for the object that is edited by this editor. | |
/// </summary> | |
private System.Type editedObjectType; | |
private Editor editorInstance; | |
#endregion | |
private static Dictionary<string, MethodInfo> decoratedMethods = new Dictionary<string, MethodInfo>(); | |
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); | |
} | |
} | |
/// <summary> | |
/// Delegates a method call with the given name to the decorated editor instance. | |
/// </summary> | |
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 EditorInstance.RequiresConstantRepaint (); | |
} | |
public override bool UseDefaultMargins () | |
{ | |
return EditorInstance.UseDefaultMargins (); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Verify Github on Galaxy. gid:bCBksuiNuPEUeaXeZkH2BC