Unity3D研究院编辑器之不影响原有布局拓展Inspector
2016-11-22 10:05
393 查看
今天无意间发现了一篇好文章,也让我解决了一个很久都没解决的难题。问题是这样的,假如我想去拓展Unity自带的inspector但是并不想影响原有布局。 比如下面这段代码:
我的本意是想在Rect Transform面板的下面去添加一个按钮,可是我一旦调用base.OnInspectorGUI()方法以后,原有的布局都就变了。
为什么会影响到原有布局呢?原因是这样的上面的代码是继承Editor的,那么base.OnInspectorGUI()实际上去掉用了Editor类里的OnInspectorGUI()方法,可是RectTransfm的OnInspectorGUI()方法是在RectTransformEditor这个类写的。
但是问题就来了,RectTransformEditor这个类不是一个对外公开的类。所以不能继承它,那也就无法调用它的OnInspectorGUI()方法了,所以就有了上述问题。
这里有一个巧妙的反射方法,完美的解决这个问题。https://gist.github.com/liortal53/352fda2d01d339306e03
理论上unity提供的每一个脚本都有一个 XXXEditor 类 , 用来绘制它的面板。(本文用到的就是 RectTransformEditor)如果你不确定可以去我反编译的代码里面去找。https://bitbucket.org/xuanyusong/unity-decompiled
如下图所示,现在既保留了原有的布局,也可以方便的拓展了。。
版本: Unity5.3.3
本文固定链接: http://www.xuanyusong.com/archives/3931
转载请注明: 雨松MOMO 2016年03月26日 于 雨松MOMO程序研究院 发表
1 2 3 4 5 6 7 8 9 10 11 12 13 | [CustomEditor(typeof(RectTransform))] public class MyTest : Editor { public override void OnInspectorGUI () { base.OnInspectorGUI (); if(GUILayout.Button("Adding this button")) { Debug.Log("Adding this button"); } } } |
为什么会影响到原有布局呢?原因是这样的上面的代码是继承Editor的,那么base.OnInspectorGUI()实际上去掉用了Editor类里的OnInspectorGUI()方法,可是RectTransfm的OnInspectorGUI()方法是在RectTransformEditor这个类写的。
但是问题就来了,RectTransformEditor这个类不是一个对外公开的类。所以不能继承它,那也就无法调用它的OnInspectorGUI()方法了,所以就有了上述问题。
这里有一个巧妙的反射方法,完美的解决这个问题。https://gist.github.com/liortal53/352fda2d01d339306e03
1 2 3 4 5 6 7 8 9 10 11 12 13 | [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"); } } } |
如下图所示,现在既保留了原有的布局,也可以方便的拓展了。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | 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 (); } } |
本文固定链接: http://www.xuanyusong.com/archives/3931
转载请注明: 雨松MOMO 2016年03月26日 于 雨松MOMO程序研究院 发表
相关文章推荐
- Unity3D研究院之在开始学习拓展编辑器(一)
- Unity3D研究院编辑器之独立Inspector属性(九)
- Unity3D研究院之在开始学习拓展编辑器
- 在EditText中设置图片,背景为圆角,输入法弹出不影响activity原有布局...(一)
- android输入法弹出后,不影响activity原有布局
- 软键盘消失有残影 不影响activity原有布局 不会重绘之前界面
- 4. 在Inspector面板中显示类中变量+ 拓展编辑器
- [Unity] Unity3D研究院编辑器之独立Inspector属性
- [Unity] Unity3D研究院编辑器之自定义默认资源的Inspector面板
- Unity3D研究院之拓展系统自带组件的Inspector视图
- Unity3D研究院编辑器之自定义默认资源的Inspector面板
- 键盘显示影响布局的解决方法
- Unity编辑器拓展之三:拓展Unity的Hierarchy面板
- 内嵌盒子定位和居中问题,在缩放浏览器情况下,不会影响盒子的布局
- 比较详细的DIV+CSS布局网页对网站SEO的影响
- Android Studio 2.2之布局编辑器
- 三十二、C++内存布局,对象大小计算、虚函数虚继承对类内存模型的影响
- css3 鼠标放上去,如何实现图片缩放并且不影响布局
- 页面布局对SEO的影响
- Android Studio由于support版本冲突导致布局编辑器无法显示RecyclerView