Drawer types

There are a few different types of drawers. Respectively, these are value drawers, attribute drawers, attribute value drawers, and group drawers. They all act in a very similar manner, but are different in where they apply in the inspector.

Note that all drawers in Odin are always strongly typed, and do not allow type polymorphism. For instance, if you have a FooDrawer that explicitly draws class Foo as in the first example beneath, and a class Bar that inherits from class Foo, your FooDrawer will never draw an instance of class Bar. Creating more general drawers that support polymorphism is done using generics (see the Generic drawers section), which lets Odin instantiate a strongly typed generic variant of your drawer for the type it should draw.

Value Drawers

Value drawers are created by deriving from OdinValueDrawer<T>, and replacing the "T" argument with the type of the value which is to be drawn. Value drawers are the "default" drawers for any given type - a value drawer for the type Foo will be added to the drawing chain of all instances of type Foo in the inspector, unless another drawer that draws the type Foo without passing the call further down the drawer chain has a higher priority.

[OdinDrawer]
public class FooDrawer : OdinValueDrawer<Foo>
{
}

All value drawers have a default priority of (0, 0, 1). It is advised to keep the priority of value drawers which do not pass the drawing call down the chain under (0, 0, 1000), as that is the default attribute drawer priority, and value drawers should, as a general rule, not override attribute drawers. You can change the priority of a drawer by adding the [DrawerPriority] attribute to it.

Note the [OdinDrawer] attribute that the drawer class is decorated with. This attribute has to be added if you want any drawer to be registered with the inspector - if you don't add this attribute, the drawer will not be found and used by Odin's default inspector!

Attribute Drawers

Attribute drawers are created by deriving from OdinAttributeDrawer<TAttribute> class, and replacing the "TAttribute" argument with the type of the attribute which is to be drawn. Attribute drawers will be added to the drawing chain of any drawn member with that attribute defined.

[OdinDrawer]
public class SomeAttributeDrawer : OdinAttributeDrawer<SomeAttribute>
{
}

All attribute drawers have a default priority of (0, 0, 1000), and will thus tend to come earlier in the chain than value drawers, which have a default of (0, 0, 1). You can change the priority of a drawer by adding the [DrawerPriority] attribute to it.

Attribute Value Drawers

Attribute value drawers are distinct from attribute drawers and value drawers, in that they combine the two concepts. An attribute drawer will apply to a member with a given attribute, but only if that member's value is of a specific type (or types, in the case of generic drawers). They created by deriving from OdinAttributeDrawer<TAttribute, TValue>, and replacing the "TAttribute" argument with the type of the attribute which is to be drawn, and replacing the "TValue" argument with the type of the value to be drawn.

[OdinDrawer]
public class SomeAttributeFooDrawer : OdinAttributeDrawer<SomeAttribute, Foo>
{
}

All attribute value drawers have a default priority of (0, 0, 1000), and will thus tend to come earlier in the chain than value drawers, which have a default of (0, 0, 1). You can change the priority of a drawer by adding the [DrawerPriority] attribute to it.

Group Drawers

Group drawers are a different sort of beast than the value, attribute, and attribute value drawers. Unlike other drawer types, group drawers don't draw a single property - instead, they are responsible for drawing a group of properties in a certain way.

To create a your own group type, in addition to creating a group drawer, you must also create a group attribute which is derived from the PropertyGroupAttribute class. These attributes function in a peculiar way - when it is initializing the group in the inspector, Odin collects all of the attributes for that group, and combines all of their values into one attribute, which is then used to represent the whole group. If you have your own values in your group property, you need to provide your own custom logic for combining those values by overriding the CombineValuesWith method.

Attributes also need to be decorated with an [AttributeUsage] attribute, that tells the C# compiler where and how that attribute can be applied. It is recommended that you use the arguments as seen in the SomeGroupAttribute example below.

Finally, group attributes must have a group id and a property order number - therefore your group attribute must have a constructor which calls the base constructor in PropertyGroupAttribute.

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class SomeGroupAttribute : PropertyGroupAttribute
{
    public SomeGroupAttribute(string groupId, int order = 0)
        : base(groupId, order)
    {
    }
}

The group drawer itself, much like an attribute drawer, is declared like this:

[OdinDrawer]
public class SomeGroupAttributeDrawer : OdinGroupDrawer<SomeGroupAttribute>
{
}

All group drawers have a default priority of (0, 0, 1). Group drawers are unique in that the drawing chain for any group only contains group drawers for that particular group type. Therefore, the drawing chains of groups are often very uncluttered, and you can use the priorities you wish. You can change the priority of a drawer by adding the [DrawerPriority] attribute to it.

This means that you can easily wrap or completely take over the drawing of any group type, should you so wish. Merely create a drawer for the relevant group attribute, and give it a higher priority than the drawer that already exists for that group type.

Generic drawers

In this section you've learned how to declare basic drawers for specific types and attributes. However, that's often not good enough; sometimes, you want to apply a single drawer to many different types, or perhaps even to all types that are drawn, anywhere! Odin offers a powerful facility for doing this, generic drawers, which lets you specify exactly to which types your drawer should apply. Follow along in the next section, Generic drawers.