Search Unity

Custom Property Drawers, conditional rendering of fields in a class

Discussion in 'Immediate Mode GUI (IMGUI)' started by eses, Mar 25, 2019.

  1. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Hi,

    I haven't used editor scripting that much, and was trying to do following;
    - I Have a class that contains a definition of attributes some object/weapon/item might have.
    - I Have another class that hosts a list of attributes, used to define item's "levels" for upgrading the item.

    Example:
    Code (CSharp):
    1. [System.Serializable]
    2. public class Attributes
    3. {
    4.     public float speed;
    5.     public float delay;
    6.     public float damage;
    7. }

    Idea was I'd have one class with all attributes, but some objects might use just speed and some delay and damage, so I could toggle visibility of fields, so that list in AttributesLevels only shows speed value or delay and damage value for each list item, depending on bool values:

    Code (CSharp):
    1. [System.Serializable]
    2. public class AttributesLevels
    3. {
    4.     public bool hasSpeed;
    5.     public bool hasDelay;
    6.     public bool hasDamage;
    7.  
    8.     public Attributes[] levels;
    9. }

    I wanted to use Custom Property Drawer not full blown custom editor, so that I only would need drawing of AttributesLevels. I could do:

    Code (CSharp):
    1. foreach (var att in levels)
    2. {
    3.    var item = (SerializedProperty)att;
    4.    // automatic render
    5.    EditorGUI.PropertyField(rect, item, true);
    6.    // Add default height
    7.    rect.y += EditorGUI.GetPropertyHeight(item);
    8. }

    This works great. The problem: to be able to have toggle feature this isn't enough, I will have to basically do custom handling of each field, like this (or at least this is the only way I have found so far):

    Code (CSharp):
    1. if (hasSpeed != null && hasSpeed.boolValue)
    2. {
    3.    EditorGUI.PropertyField(rect, item.FindPropertyRelative("speed"));
    4.    rect.y += 16;
    5. }

    And so on, for each optional field (which I might have many more than in this example) of Attributes class.

    TL;DR
    Is there a good way to handle optional rendering of list element fields? I'm now handling layout of Attributes class in AttributesLevels class custom property drawer and this feels somehow wrong.

    If someone has a better idea how to do this, or if you have an idea how to better handle item with set of attributes and list of upgrade levels, I'm interested in hearing your ideas.

    Thanks!
     
  2. sarynth

    sarynth

    Joined:
    May 16, 2017
    Posts:
    98