The last blog post didn't cover a certain nifty method in PropertyDrawer, which is the GetPropertyHeight.
- GetPropertyHeight: Determines the height in pixel of the property field.
Overriding GetPropertyHeight therefore allows you to determine the height of your property field, instead of using the default property height.
The following examples shows how you can use GetPropertyHeight. I'll be using the WeaponType enum to determine weapon type on a character as an example. Every example will add/modify the behaviour of the Example 1.
public enum WeaponType : byte { None, Bazooka };
public WeaponType type = WeaponType.None;
Example 1:
This example shows our base for drawing an enum popup. This is also the default Unity behaviour.
[CustomPropertyDrawer(typeof(WeaponType))]
public class WeaponTypeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
{
// Label
position = EditorGUI.PrefixLabel(position, label);
// Child objects shouldn't be indented
int indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
// Enum
property.enumValueIndex = EditorGUI.Popup(position, property.enumValueIndex, property.enumNames);
// Reset indenting
EditorGUI.indentLevel = indent;
}
EditorGUI.EndProperty();
}
}
Example 2:
Next we adjust the height of our property field, such that we can add a catch phrase to our weapon type.
[CustomPropertyDrawer(typeof(WeaponType))]
public class WeaponTypeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
{
// Label
position = EditorGUI.PrefixLabel(position, label);
// Child objects shouldn't be indented
int indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
// Create rects that specifies position of our enum popup and our catch phrase
Rect pos0 = new Rect(position.x, position.y, position.width, position.height * 0.5f);
Rect pos1 = new Rect(position.x, pos0.yMax, position.width, position.height * 0.5f);
// Enum
property.enumValueIndex = EditorGUI.Popup(pos0, property.enumValueIndex, property.enumNames);
// Catch phrase
switch ((WeaponType)property.enumValueIndex)
{
case WeaponType.None:
EditorGUI.LabelField(pos1, "Ahh... Where is my weapon?");
break;
case WeaponType.Bazooka:
EditorGUI.LabelField(pos1, "Only reasonable choice!");
break;
}
// Reset indenting
EditorGUI.indentLevel = indent;
}
EditorGUI.EndProperty();
}
// Overriding the GetPropertyHeight gives us the possibility to specify the property height
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
// Twice as high as a default property height
return base.GetPropertyHeight(property, label) * 2.0f;
}
}
Example 3:
Lastly, we modify the height given WeaponType such that only Bazooka has a catch phrase.
[CustomPropertyDrawer(typeof(WeaponType))]
public class WeaponTypeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
{
// Label
position = EditorGUI.PrefixLabel(position, label);
// Child objects shouldn't be indented
int indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
WeaponType type = (WeaponType)property.enumValueIndex;
if (type == WeaponType.None)
{
property.enumValueIndex = EditorGUI.Popup(position, property.enumValueIndex, property.enumNames);
}
else
{
Rect pos0 = new Rect(position.x, position.y, position.width, position.height * 0.5f);
Rect pos1 = new Rect(position.x, pos0.yMax, position.width, position.height * 0.5f);
// Enum
property.enumValueIndex = EditorGUI.Popup(pos0, property.enumValueIndex, property.enumNames);
// Catch phrase
switch ((WeaponType)property.enumValueIndex)
{
case WeaponType.Bazooka:
EditorGUI.LabelField(pos1, "Only reasonable choice!");
break;
default:
EditorGUI.LabelField(pos1, "What is this!?");
break;
}
}
// Reset indenting
EditorGUI.indentLevel = indent;
}
EditorGUI.EndProperty();
}
// Overriding the GetPropertyHeight gives us the possibility to specify the property height
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
WeaponType type = (WeaponType)property.enumValueIndex;
float height = base.GetPropertyHeight(property, label);
// If anything else then empty, then give enough height to add a catch phrase
if (type != WeaponType.None)
height *= 2.0f;
return height;
}
}
When to use?
The first usage is when you need more space for your property drawer, which can be due to having a lot of fields that needs to be drawn.
The second reason could be because an object has different states. E.g. if we had the following Weapon class:
public class Weapon
{
public WeaponType type = WeaponType.Bazooka;
public float damage = 10.0f;
public float radius = 1.0f;
}
Splash radius might only be usable when having a bazooka, where as agun wouldn't need the splash damage field. We could then hide splash damage, when we have the type: Gun. This would also help the designers, since you could hide "useless" fields in certain states.
原文地址:http://www.ejlersen.info/index.php?page=blog&id=65