public
class
InspectorDecoratorEditor : Editor
{
public
static
readonly
System.Type EndType =
typeof
(UnityEngine.MonoBehaviour);
// end type dont need show in inspector
public
static
readonly
System.Type BaseEditorType =
typeof
(UnityEditor.Editor);
// CustomEditor must inherit from it, filter
public
static
readonly
BindingFlags CustomEditorFieldFlags = BindingFlags.NonPublic | BindingFlags.Instance;
// flag
// type cache[Assembly, [scriptType, customEditorType]]
protected
static
Dictionary<Assembly, Dictionary<System.Type, System.Type>> ms_editorReferenceScript
=
new
Dictionary<Assembly, Dictionary<System.Type, System.Type>>();
protected
List<Editor> m_inheritEditors =
null
;
// cached editors
// ctor, use ctor instead Mono life circle, more user friendly
public
InspectorDecoratorEditor()
{
CacheEditorReferenceScript();
}
#region Main Funcs
/// <summary>
/// Cache all CustomEditor in current Assembly
/// </summary>
protected
void
CacheEditorReferenceScript()
{
var
editorAssembly = Assembly.GetAssembly(
this
.GetType());
// editor may in diferent assemblies
if
(ms_editorReferenceScript.ContainsKey(editorAssembly) ==
false
)
{
Dictionary<System.Type, System.Type> cachedData =
new
Dictionary<System.Type, System.Type>();
var
types = editorAssembly.GetExportedTypes();
foreach
(
var
editorType
in
types)
{
if
(editorType.IsSubclassOf(BaseEditorType))
{
var
scriptType = GetTypeFormCustomEditor(editorType);
if
(scriptType !=
null
)
{
cachedData[scriptType] = editorType;
}
}
}
ms_editorReferenceScript[editorAssembly] = cachedData;
}
}
/// <summary>
/// Draw a Target Type Inspector, call OnInspectorGUI
/// </summary>
/// <typeparam name="T"></typeparam>
protected
virtual
void
DrawBaseInspectorGUI<T>()
where
T : InspectorDecoratorEditor
{
if
(m_inheritEditors ==
null
)
{
m_inheritEditors =
new
List<Editor>();
Dictionary<System.Type, System.Type> scriptEditorCache =
null
;
if
(ms_editorReferenceScript.TryGetValue(Assembly.GetAssembly(
this
.GetType()),
out
scriptEditorCache) && scriptEditorCache !=
null
)
{
var
baseType = target.GetType().BaseType;
while
(baseType !=
null
&& baseType != EndType)
{
System.Type editorType =
null
;
if
(scriptEditorCache.TryGetValue(baseType,
out
editorType) && editorType !=
null
)
{
m_inheritEditors.Add(Editor.CreateEditor(targets, editorType));
}
baseType = baseType.BaseType;
}
}
}
if
(m_inheritEditors.Count > 0)
{
for
(
int
i = m_inheritEditors.Count - 1; i >= 0; i--)
{
var
drawTarget = m_inheritEditors[i];
if
(drawTarget && drawTarget.GetType() ==
typeof
(T))
{
drawTarget.OnInspectorGUI();
// draw target type only, avoid endless loop
break
;
}
}
}
}
#endregion
#region Help Funcs
public
static
System.Type GetTypeFormCustomEditor(System.Type editorType)
{
var
attributes = editorType.GetCustomAttributes(
typeof
(CustomEditor),
false
)
as
CustomEditor[];
if
(attributes !=
null
&& attributes.Length > 0)
{
var
attribute = attributes[0];
var
type = attribute.GetType().GetField(
"m_InspectedType"
, CustomEditorFieldFlags).GetValue(attribute)
as
System.Type;
return
type;
}
return
null
;
}
#endregion
}