您的位置:首页 > 移动开发 > Unity3D

unity3d 扩展unity原有的Inspector

2016-03-29 09:58 537 查看


为什么会影响到原有布局呢?原因是这样的上面的代码是继承Editor的,那么base.OnInspectorGUI()实际上去掉用了Editor类里的OnInspectorGUI()方法,可是RectTransfm的OnInspectorGUI()方法是在RectTransformEditor这个类写的。

但是问题就来了,RectTransformEditor这个类不是一个对外公开的类。所以不能继承它,那也就无法调用它的OnInspectorGUI()方法了,所以就有了上述问题。

这里有一个巧妙的反射方法,完美的解决这个问题。https://gist.github.com/liortal53/352fda2D01d339306e03

[CustomEditor(typeof(RectTransform))]
public class MyTest : DecoratorEditor
{
public MyTest(): base("RectTransformEditor"){}
public override void OnInspectorGUI ()
{
base.OnInspectorGUI ();
if(GUILayout.Button("Adding this button"))
{
Debug.Log("Adding this button");
}
}
}

理论上unity提供的每一个脚本都有一个 XXXEditor 类 , 用来绘制它的面板。(本文用到的就是 RectTransformEditor)如果你不确定可以去我反编译的代码里面去找。https://bitbucket.org/xuanyusong/unity-decompiled

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 ();
}
}

版本: unity5.3.3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: