Skip to content

Instantly share code, notes, and snippets.

@RedDude
Created July 8, 2018 04:50
Show Gist options
  • Save RedDude/39234c9b6c229601435f3b80a9892b1a to your computer and use it in GitHub Desktop.
Save RedDude/39234c9b6c229601435f3b80a9892b1a to your computer and use it in GitHub Desktop.
ExpandableAttributeDrawer Unity
using UnityEngine;
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using UnityEditor;
#endif
#if UNITY_EDITOR
/// <summary>
/// Draws the property field for any field marked with ExpandableAttribute.
/// </summary>
[CustomPropertyDrawer(typeof(ExpandableAttribute), true)]
public class ExpandableAttributeDrawer : PropertyDrawer
{
// Use the following area to change the style of the expandable ScriptableObject drawers;
#region Style Setup
private enum BackgroundStyles
{
None,
HelpBox,
Darken,
Lighten
}
/// <summary>
/// Whether the default editor Script field should be shown.
/// </summary>
private static bool SHOW_SCRIPT_FIELD = false;
/// <summary>
/// The spacing on the inside of the background rect.
/// </summary>
private static float INNER_SPACING = 6.0f;
/// <summary>
/// The spacing on the outside of the background rect.
/// </summary>
private static float OUTER_SPACING = 4.0f;
/// <summary>
/// The style the background uses.
/// </summary>
private static BackgroundStyles BACKGROUND_STYLE = BackgroundStyles.HelpBox;
/// <summary>
/// The colour that is used to darken the background.
/// </summary>
private static Color DARKEN_COLOUR = new Color(0.0f, 0.0f, 0.0f, 0.2f);
/// <summary>
/// The colour that is used to lighten the background.
/// </summary>
private static Color LIGHTEN_COLOUR = new Color(1.0f, 1.0f, 1.0f, 0.2f);
#endregion
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
float totalHeight = 0.0f;
totalHeight += EditorGUIUtility.singleLineHeight;
if (property.objectReferenceValue == null)
return totalHeight;
if (!property.isExpanded)
return totalHeight;
SerializedObject targetObject = new SerializedObject(property.objectReferenceValue);
if (targetObject == null)
return totalHeight;
SerializedProperty field = targetObject.GetIterator();
field.NextVisible(true);
if (SHOW_SCRIPT_FIELD)
{
totalHeight += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
}
while (field.NextVisible(false))
{
totalHeight += EditorGUI.GetPropertyHeight(field, true) + EditorGUIUtility.standardVerticalSpacing;
}
totalHeight += INNER_SPACING * 2;
totalHeight += OUTER_SPACING * 2;
return totalHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Rect fieldRect = new Rect(position);
fieldRect.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(fieldRect, property, label, true);
if (property.objectReferenceValue == null)
return;
property.isExpanded = EditorGUI.Foldout(fieldRect, property.isExpanded, GUIContent.none, true);
if (!property.isExpanded)
return;
SerializedObject targetObject = new SerializedObject(property.objectReferenceValue);
if (targetObject == null)
return;
#region Format Field Rects
List<Rect> propertyRects = new List<Rect>();
Rect marchingRect = new Rect(fieldRect);
Rect bodyRect = new Rect(fieldRect);
bodyRect.xMin += EditorGUI.indentLevel * 14;
bodyRect.yMin += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing
+ OUTER_SPACING;
SerializedProperty field = targetObject.GetIterator();
field.NextVisible(true);
marchingRect.y += INNER_SPACING + OUTER_SPACING;
if (SHOW_SCRIPT_FIELD)
{
propertyRects.Add(marchingRect);
marchingRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
}
while (field.NextVisible(false))
{
marchingRect.y += marchingRect.height + EditorGUIUtility.standardVerticalSpacing;
marchingRect.height = EditorGUI.GetPropertyHeight(field, true);
propertyRects.Add(marchingRect);
}
marchingRect.y += INNER_SPACING;
bodyRect.yMax = marchingRect.yMax;
#endregion
DrawBackground(bodyRect);
#region Draw Fields
EditorGUI.indentLevel++;
int index = 0;
field = targetObject.GetIterator();
field.NextVisible(true);
if (SHOW_SCRIPT_FIELD)
{
//Show the disabled script field
EditorGUI.BeginDisabledGroup(true);
EditorGUI.PropertyField(propertyRects[index], field, true);
EditorGUI.EndDisabledGroup();
index++;
}
//Replacement for "editor.OnInspectorGUI ();" so we have more control on how we draw the editor
while (field.NextVisible(false))
{
try
{
EditorGUI.PropertyField(propertyRects[index], field, true);
}
catch (StackOverflowException)
{
field.objectReferenceValue = null;
Debug.LogError("Detected self-nesting cauisng a StackOverflowException, avoid using the same " +
"object iside a nested structure.");
}
index++;
}
targetObject.ApplyModifiedProperties();
EditorGUI.indentLevel--;
#endregion
}
/// <summary>
/// Draws the Background
/// </summary>
/// <param name="rect">The Rect where the background is drawn.</param>
private void DrawBackground(Rect rect)
{
switch (BACKGROUND_STYLE)
{
case BackgroundStyles.HelpBox:
EditorGUI.HelpBox(rect, "", MessageType.None);
break;
case BackgroundStyles.Darken:
EditorGUI.DrawRect(rect, DARKEN_COLOUR);
break;
case BackgroundStyles.Lighten:
EditorGUI.DrawRect(rect, LIGHTEN_COLOUR);
break;
}
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment