04. Creating New Drawers

  10. Extending Power Inspector No Comments

Basic Requirements of a Drawer

When creating your own drawer for use in Power Inspector, your class needs to fulfill the following requirements:

  1. The class should be decorated with an attribute that derives from DrawerForBase attribute. This lets Power Inspector know what elements inside the inspector should be handled by the drawer.
  2. The class should implement one of the interfaces that derives from IDrawer that corresponds with the used attribute.

List of DrawerFor* Attributes

Here are all the available attributes, and the IDrawer-derived interfaces that can be chosen by the classes that have them:

    1. DrawerForField attribute
      • IFieldDrawer – Implemented by drawers that represent a value-backed class member such as a field or a property.
      • ITextFieldDrawer – An extension of IFieldDrawer for drawers that include a text field.
    2. DrawerForComponent attribute
      • IEditorlessComponentDrawer – Implemented by drawers of Components when an Editor is not used to draw its class members.
      • ICustomEditorComponentDrawer – Implemented by drawers of Components when an Editor is used to draw its class members.
    3. DrawerForAsset attribute
      • IEditorlessAssetDrawer – Implemented by drawers of asset-type Unity Object when an Editor is not used to draw its class members.
      • ICustomEditorAssetDrawer – Implemented by drawers of asset-type Unity Object when an Editor is used to draw its class members.
    4. DrawerByExtension attribute
      • IEditorlessAssetDrawer – Implemented by drawers of asset-type Unity Object when an Editor is not used to draw its class members.
      • ICustomEditorAssetDrawer – Implemented by drawers of asset-type Unity Object when an Editor is used to draw its class members.
    5. DrawerForPropertyDrawer
    6. DrawerForDecoratorDrawer

Manually Instantiated Drawers

If you don’t need Power Inspector to automatically use your drawers inside the inspector, but instead plan to manually create instances of your drawers (this can happen for example when drawers are only used as members of another drawer), then you don’t need to decorate your drawer with any attributes. The only minimum requirement then is that the class implements IDrawer or an interface that derives from it.

However, drawers in Power Inspector can make use of object pooling to reduce garbage generation. In order to make use of this feature, you’ll need to create a method that can be used to get an instance of your drawer, which handles retrieving existing instances from the drawer pool when they exist and calling the Setup and LateSetup methods on the existing instance. Here is an example of such an implementation for a simple field drawer:

/// <summary> Creates a new instance of the drawer or returns a reusable instance from the pool. </summary>
/// <param name="value"> The starting cached value of the drawer. </param>
/// <param name="memberInfo"> LinkedMemberInfo for the field, property or parameter that the drawer represents. Can be null. </param>
/// <param name="parent"> The parent drawer of created drawer. Can be null. </param>
/// <param name="label"> The prefix label. </param>
/// <param name="readOnly"> True if control should be read only. </param>
/// <returns> The instance, ready to be used. </returns>
public static MyDrawer Create(bool value, [CanBeNull]LinkedMemberInfo memberInfo, [CanBeNull]IParentDrawer parent, [CanBeNull]GUIContent label, bool readOnly)
{
	MyDrawer result;
	if(!DrawerPool.TryGet(out result))
	{
		result = new MyDrawer();
	}
	result.Setup(value, typeof(bool), memberInfo, parent, label, readOnly);
	result.LateSetup();
	return result;
}

Implementing IDrawer

The IDrawer interface includes a large number of properties and methods that must be implemented, and as such, you usually don’t want to create new implementations of it from scratch unless absolutely necessary. Instead you should extend one of the included base classes, so that most of the functionality is already implemented for you. The base class you should extend depends on what type of content the drawer will represent: