This simple script allows developers to build their own hierarchy view of assets/inspectors/whatever you can think of in Unity.
With the latest addition you're able to navigate through all levels
At first you'll need a StackEditor
class inheriting from Editor
for providing a base-class for every editor which should support hierarchys.
It may be built up like this.
using System;
using System.Collections.Generic;
using UnityEditor;
using UObject = UnityEngine.Object;
[Serializable]
public class StackEditor : Editor
{
private Stack<Editor> activeEditors = new Stack<Editor>();
public override void OnInspectorGUI()
{
if (activeEditors.Count > 0)
activeEditors.Peek().OnInspectorGUI();
}
public void Pop()
{
DestroyImmediate(activeEditors.Pop());
}
public void Push<T>(UObject target) where T : Editor, new()
{
var editor = CreateEditor(target, typeof(T));
activeEditors.Push(editor);
if (editor is StackEditorBase)
{
var stackEditor = (StackEditorBase)editor;
stackEditor.StackEditor = this;
stackEditor.Load();
}
Repaint();
}
public void Push(UObject target)
{
var editor = CreateEditor(target);
activeEditors.Push(editor);
if (editor is StackEditorBase)
{
var stackEditor = (StackEditorBase)editor;
stackEditor.StackEditor = this;
stackEditor.Load();
}
Repaint();
}
private void OnDisable()
{
while (activeEditors.Count > 0)
Pop();
}
}
Without further knowledge about the magical StackEditorBase
-class it could be rather annoying ... so this class is the base for the simple hierarchical usage of this StackEditor
.
using System;
using UnityEditor;
[Serializable]
public class StackEditorBase : Editor
{
public StackEditor StackEditor
{
get; set;
}
public virtual string Title => GetType().Name;
public void Load()
{
OnLoad();
}
protected virtual void OnLoad()
{
}
}
These two scripts should be located in a folder called Plugins\StackEditor\Editor
It could be used like this:
[Serializable]
[CustomEditor(typeof(ContainerObject))]
public class ContainerEditor : StackEditor
{
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("Container Editor");
EditorGUILayout.Space();
base.OnInspectorGUI();
}
private void OnEnable()
{
Push<ContainerObjectEditor>(target);
}
}
This is based on how Unity is resolving types internally. The Container-Editor should not contain any logic because the Object-Editor is used for this.
[Serializable]
[CustomEditor(typeof(ConainerObject))]
public class ContainerObjectEditor : StackEditorBase
{
[MenuItem("Assets/Create/Container")]
[ContextMenu("Create/Container")]
public static void CreateObject()
{
var path = "";
var obj = Selection.activeObject;
if (!obj)
path = "Assets";
else
path = AssetDatabase.GetAssetPath(obj.GetInstanceID());
if (path.Length > 0)
{
if (!AssetDatabase.IsValidFolder(path))
path = Path.GetDirectoryName(path);
}
var instance = CreateInstance<ContainerObject>();
ProjectWindowUtil.CreateAsset(instance, AssetDatabase.GenerateUniqueAssetPath(path + "/New Container.asset"));
Selection.activeObject = instance;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("startTime"));
serializedObject.ApplyModifiedProperties();
}
}
For navigating in the hierarchy it's enough to call StackEditor.Push<>()
or StackEditor.Pop()
. Former goes down the hierarchy, latter navigates a level higher.
GitHub/AliveDevil/stackededitor Github/AliveDevil/stackededitor/Releases