CustomPropertyDrawer-Change the height of Property field

The last blog post didn't cover a certain nifty method in PropertyDrawer, which is the GetPropertyHeight.

 

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值