Skip to content

Latest commit

 

History

History
246 lines (195 loc) · 6.08 KB

File metadata and controls

246 lines (195 loc) · 6.08 KB

How to create custom Toolbox Drawers & Editors

Custom Drawer

ToolboxDrawers are divided into 5 sub-types to maximize useability and cover all popular cases.

  • ToolboxDecoratorDrawers:

    Use them to create nice looking controls, icons and optional 'decorators' before or/and after any serialized property.
    There is no limit of usages within single property.

  • ToolboxConditionDrawers:

    Use them to validate the state of any property (even lists), you can easily decide if a property should be disabled or hidden.
    Use it only once per property.

  • ToolboxSelfPropertyDrawers:

    Use them to customize the look of the respective property field.
    Use it only once per property.

  • ToolboxListPropertyDrawers:

    Use them to customize the look of the respective list property.
    Use it only once per property.

  • ToolboxTargetTypeDrawers:

    Use them to specify the look of all dedicated properties based on the chosen type.

Implementation steps:

  • decide what kind of drawer you need
  • implement dedicated ToolboxAttribute class (if drawer is attribute-based)
  • implement dedicated ToolboxDrawer class
  • assign newly created drawer in the featured Settings file
  • use it

Custom Decorator Drawer

using UnityEngine;

public class SampleAttribute : ToolboxDecoratorAttribute
{ }
using UnityEditor;
using Toolbox.Editor.Drawers;

public class SampleDrawer : ToolboxDecoratorDrawer<SampleAttribute>
{
	protected override void OnGuiBeginSafe(SampleAttribute attribute)
	{
		//draw something before property
	}
	
	protected override void OnGuiCloseSafe(SampleAttribute attribute)
	{
		//draw something after property
		
		EditorGUILayout.Space();
		EditorGUILayout.LabelField("Label created in the custom decorator Drawer.");
	}
}

Custom Condition Drawer

using UnityEngine;

public class SampleAttribute : ToolboxConditionAttribute
{ }
using UnityEditor;
using Toolbox.Editor.Drawers;

public class SampleDrawer : ToolboxConditionDrawer<SampleAttribute>
{
	protected override PropertyCondition OnGuiValidateSafe(SerializedProperty property, SampleAttribute attribute)
	{
		return PropertyCondition.Disabled;
	}
}

Custom Self Property Drawer

using UnityEngine;

public class HideLabelAttribute : ToolboxSelfPropertyAttribute
{
	//since we want only to hide the label there is no additional data needed
}
using UnityEditor;
using UnityEngine;
using Toolbox.Editor.Drawers;

public class HideLabelAttributeDrawer : ToolboxSelfPropertyDrawer<HideLabelAttribute>
{
	protected override void OnGuiSafe(SerializedProperty property, GUIContent label, HideLabelAttribute attribute)
	{
		//hide label and draw property in the standard way
		EditorGUILayout.PropertyField(property, GUIContent.none, property.isExpanded);
	}


	public override bool IsPropertyValid(SerializedProperty property)
	{
		//drawer is valid for all properties (for all types)
		return true;
	}
}

Custom List Property Drawer

using UnityEngine;

public class StandardListAttribute : ToolboxListPropertyAttribute
{ }
using UnityEditor;
using UnityEngine;
using Toolbox.Editor.Drawers;

public class StandardListAttributeDrawer : ToolboxListPropertyDrawer<StandardListAttribute>
{
	protected override void OnGuiSafe(SerializedProperty property, GUIContent label, StandardListAttribute attribute)
	{
		EditorGUILayout.LabelField("Custom list drawer example");
		EditorGUILayout.PropertyField(property, label, false);
		if (property.isExpanded)
		{
			EditorGUILayout.PropertyField(property.FindPropertyRelative("Array.size"));
			var size = property.arraySize;
			for (var i = 0; i < size; i++)
			{
				var element = property.GetArrayElementAtIndex(i);
				EditorGUILayout.PropertyField(element, element.isExpanded);
			}
		}
	}
}

Custom Target Type Drawer

using System;
using UnityEditor;
using UnityEngine;

public class IntDrawer : ToolboxTargetTypeDrawer
{
	public override void OnGui(SerializedProperty property, GUIContent label)
	{
		EditorGUILayout.LabelField("You can create a custom drawer for all single types");
		EditorGUILayout.PropertyField(property, label);
	}

	public override Type GetTargetType()
	{
		return typeof(int);
	}
	
	public override bool UseForChildren()
	{
		return false;
	}
}

Custom Editor

If you want to create a custom UnityEditor.Editor for your components and still use Toolbox-related features be sure to inherit from the Toolbox.Editor.ToolboxEditor class.

using UnityEditor;
using UnityEngine;
#if UNITY_2019_1_OR_NEWER
using UnityEditor.UIElements;
using UnityEngine.UIElements;
#endif
using Toolbox.Editor;

[CustomEditor(typeof(SampleBehaviour2))]
public class SampleEditor : ToolboxEditor
{
	private void OnEnable()
	{ }

	private void OnDisable()
	{ }

	public override void DrawCustomInspector()
	{
		base.DrawCustomInspector();
		
		//for custom properties:
		// - ToolboxEditorGui.DrawToolboxProperty(serializedObject.FindProperty("myProperty"));
		
		EditorGUILayout.Space();
		EditorGUILayout.LabelField("This label is created in the custom Editor. You can freely extend Toolbox-based Editors by inheriting from the <b>ToolboxEditor</b> class.", Style.labelStyle);
	}
	
#if UNITY_2019_1_OR_NEWER
	public override VisualElement CreateInspectorGUI()
	{
		//NOTE: create a custom container if you want to use UIElements instead of the standard IMGUI system
		return null;
	}
#endif

	private static void DrawMyCustomProperty(SerializedProperty property)
	{
		EditorGUILayout.PropertyField(property);
	}
		
	/// <summary>
	/// You can override this property with your custom IToolboxEditorDrawer implementation to override the default way how the Editor is drawn.
	/// Additionally, you can assign your custom method directly for the ToolboxEditorDrawer.
	/// </summary>
	public override IToolboxEditorDrawer Drawer { get; } = new ToolboxEditorDrawer(DrawMyCustomProperty);
	
	private static class Style
	{
		internal static readonly GUIStyle labelStyle;

		static Style()
		{
			labelStyle = new GUIStyle(EditorStyles.helpBox)
			{
				richText = true,
				fontSize = 14
			};
		}
	}
}