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

已标记关键词 清除标记
相关推荐
Version 1.7 ----------- - ADD: Delphi/CBuilder 10.2 Tokyo now supported. - ADD: Delphi/CBuilder 10.1 Berlin now supported. - ADD: Delphi/CBuilder 10 Seattle now supported. - ADD: Delphi/CBuilder XE8 now supported. - ADD: Delphi/CBuilder XE7 now supported. - ADD: Delphi/CBuilder XE6 now supported. - ADD: Delphi/CBuilder XE5 now supported. - ADD: Delphi/CBuilder XE4 now supported. - ADD: Delphi/CBuilder XE3 now supported. - ADD: Delphi/CBuilder XE2 now supported. - ADD: Delphi/CBuilder XE now supported. - ADD: Delphi/CBuilder 2010 now supported. - ADD: Delphi/CBuilder 2009 now supported. - ADD: New demo project FlexCADImport. - FIX: The height of the TFlexRegularPolygon object incorrectly changes with its rotation. - FIX: Added division by zero protect in method TFlexControl.MovePathSegment. - FIX: The background beyond docuemnt wasn't filled when TFlexPanel.DocClipping=True. - FIX: In "Windows ClearType" font rendering mode (OS Windows mode) the "garbage" pixels can appear from the right and from the bottom sides of the painted rectangle of the TFlexText object. - FIX: The result rectangle incorrectly calculated in the TFlexText.GetRefreshRect method. - FIX: Added FPaintCache.rcPaint cleanup in the TFlexPanel.WMPaint method. Now it is possible to define is the drawing take place via WMPaint or via the PaintTo direct call (if rcPaint contain non-empty rectangle then WMPaint in progress). - FIX: The TFlexPanel.FPaintCache field moved in the protected class section. Added rcPaint field in FPaintCache that represents drawing rectangle. - ADD: In the text prcise mode (TFlexText.Precise=True) takes into account the rotation angle (TFlexText.Angle). - FIX: Removed FG_NEWTEXTROTATE directive (the TFlexText Precise mode should be used instead). - FIX: The TFlexRegularPolygon object clones incorrectly drawed in case when TFlexRegularPolygon have alternative brush (gradient, texture). - ADD: Add TFlexPanel.InvalidateControl virtual method which calls from TFle
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页