Odin Editor Windows

Whether it is to get an overview of your project, handle large sets of data, or even to create custom tooling, making editor windows can go a long way to ease and streamline the production workflow of a project. However, it can be a pain to keep them maintained and relevant as the project changes.

This is where Odin Editor Windows come in. By merely inheriting from a single class you gain access to the powerful Odin drawing system in its entirety. You no longer have to worry about how your windows are drawn, but can instead focus on what is actually important: the function they should provide.

How it works

By simply inheriting from OdinEditorWindow instead of EditorWindow, you get the ability to render fields, properties and methods in the window without writing any custom editor GUI code, just as when customizing your inspector with Odin.

public class MyCustomEditorWindow : OdinEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow()
    {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    public string Hello;
}

Use attributes to design your editors

Design your editor window using attributes, as if it was a MonoBehaviour or a ScriptableObject, using all of the attributes available from Odin and Unity.

public class MyCustomEditorWindow : OdinEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow()
    {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    [EnumToggleButtons, BoxGroup("Settings")]
    public ScaleMode ScaleMode;

    [FolderPath(RequireExistingPath = true), BoxGroup("Settings")]
    public string OutputPath;

    [HorizontalGroup(0.5f)]
    public List<Texture> InputTextures;

    [HorizontalGroup, InlineEditor(InlineEditorModes.LargePreview)]
    public Texture Preview;

    [Button(ButtonSizes.Gigantic), GUIColor(0, 1, 0)]
    public void PerformSomeAction()
    {

    }
}

Render any object in the editor window

You can override the GetTarget method, and give it any instance of any type to render. It doesn't need to be serializable or even a Unity object - you have the freedom to take complete control.

public class MyCustomEditorWindow : OdinEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow()
    {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    protected override void Initialize()
    {
        this.WindowPadding = Vector4.zero;
    }

    protected override object GetTarget()
    {
        return Selection.activeObject;
    }
}

Stay organized with OdinMenuEditorWindow

Inherit from OdinMenuEditorWindow instead of OdinEditorWindow, and easily build a powerful, well-organized editor overview for your project data.

public class MyCustomEditorWindow : OdinMenuEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow()
    {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    protected override OdinMenuTree BuildMenuTree()
    {
        var tree = new OdinMenuTree();
        tree.Selection.SupportsMultiSelect = false;

        tree.Add("Settings", GeneralDrawerConfig.Instance);
        tree.Add("Utilities", new TextureUtilityEditor());
        tree.AddAllAssetsAtPath("Odin Settings", "Assets/Plugins/Sirenix", typeof(ScriptableObject), true, true);
        return tree;
    }
}

public class TextureUtilityEditor
{
    [BoxGroup("Tool"), HideLabel, EnumToggleButtons]
    public Tool Tool;

    public List<Texture> Textures;

    [Button(ButtonSizes.Large), HideIf("Tool", Tool.Rotate)]
    public void SomeAction() { }

    [Button(ButtonSizes.Large), ShowIf("Tool", Tool.Rotate)]
    public void SomeOtherAction() { }
}

Customizing OdinMenuTrees

OdinMenuTrees are very powerful and flexible. Here we show how you can easily customize the look of the menu tree.

public class MyCustomEditorWindow : OdinMenuEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow()
    {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    protected override OdinMenuTree BuildMenuTree()
    {
        var tree = new OdinMenuTree();
        tree.DefaultMenuStyle = OdinMenuStyle.TreeViewStyle;

        tree.Add("Menu Style", tree.DefaultMenuStyle);

        var allAssets = AssetDatabase.GetAllAssetPaths()
            .Where(x => x.StartsWith("Assets/"))
            .OrderBy(x => x);

        foreach (var path in allAssets)
        {
            tree.AddAssetAtPath(path.Substring("Assets/".Length), path);
        }

        tree.EnumerateTree().AddThumbnailIcons();
        
        return tree;
    }
}

Protip: You can use the OnInspectorGUI attribute if you wish to mix custom editor IMGUI code together with Odin-drawn editors.

You should not override the OnGUI method in OdinEditorWindows. Instead, if you want to inject custom GUI code, then you override either the DrawEditors method or you can use the OnInspectorGUI attribute on a custom GUI method.

If you do have to override the OnGUI method for some reason, then make sure to call base.OnGUI(). Without this, none of the Odin magic will work and you're basically left with an ordinary EditorWindow instead.