Search Unity

Header attribute and Custom Property Drawer overlap in inspector, repeat header text

Discussion in 'Immediate Mode GUI (IMGUI)' started by edwardrowe, Apr 6, 2015.

  1. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    This is a crosspost to a question I asked on Unity Answers, but have so far not resolved. That post is here:
    http://answers.unity3d.com/questions/940970/header-attribute-and-custom-property-drawer-overla.html

    I've created my own custom PropertyDrawer for an attribute - I simply want it to display the same label only with an '*' preceding it. I think I've built it correctly, but when I use this attribute in conjunction with the [Header] DecoratorDrawer attribute, my property is sized strangely in the inspector and gets the Header text twice.

    Here is sample code of the two attributes used together - the order does not seem to matter:

    Code (CSharp):
    1. using UnityEngine;
    2. public class TestAsterixLabel : MonoBehaviour
    3. {
    4.     [Header ("Header")]
    5.     [AsterixLabelAttribute]
    6.     public GameObject FieldWithAttributes;
    7. }
    8.  
    Has anyone else seen this? I've output my label text in the OnGui and it's simply "Custom Property Drawer" (no Header text in there at all). Is this a Unity bug?

    Here is code for my custom attribute and drawer:

    Code (CSharp):
    1.  
    2. [System.AttributeUsage (System.AttributeTargets.Field)]
    3. publicclassAsterixLabelAttribute : PropertyAttribute {
    4. }
    5.  
    Code (CSharp):
    1. [CustomPropertyDrawer(typeof(AsterixLabelAttribute))]
    2. public class AsterixLabelDrawer : PropertyDrawer
    3. {
    4.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    5.     {
    6.         EditorGUI.BeginProperty(position, label, property);
    7.         EditorGUI.PropertyField(position, property, new GUIContent("*" + label.text));
    8.         EditorGUI.EndProperty();
    9.     }
    10. }
    It looks like this (text is different):
    https://www.dropbox.com/s/b5rxtltyr5smfhy/Screenshot 2015-04-05 17.06.30.png?dl=0
     
  2. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    186
    Hey there,

    The issues is the fact that you are using position twice. You are defining both the gui objects to be placed in the same space. Try using the code below


    Code (CSharp):
    1. [CustomPropertyDrawer(typeof(AsterixLabelAttribute))]
    2. public class AsterixLabelDrawer : PropertyDrawer
    3. {
    4.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    5.     {
    6.         //So the first element only uses half our height (since we set it to 2X below)
    7.         position.height = EditorGUIUtility.singleLineHeight;
    8.         EditorGUI.BeginProperty(position, label, property);
    9.         position.y += EditorGUIUtility.singleLineHeight;
    10.         EditorGUI.PropertyField(position, property, new GUIContent("*" + label.text));
    11.         EditorGUI.EndProperty();
    12.     }
    13.  
    14.     public override float GetPropertyHeight (SerializedProperty property, GUIContent label)
    15.     {
    16.         //Since you need two spaces for your two elements
    17.         return EditorGUIUtility.singleLineHeight * 2f;
    18.     }
    19. }
    Cheers,
     
  3. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    That does add room for a potential header element, but I'm still seeing the issue.

    Using the following monobehaviour code:
    Code (CSharp):
    1.  
    2.     public float x;
    3.     public float y;
    4.     [Header ("Header")]
    5.     public bool checkbox;
    6.     public bool anotherCheckbox;
    7.     [AsterixLabelAttribute]
    8.     public float asterixFloat;
    9.     public int z;
    10.  
    11.     [Header ("Test Header")]
    12.     [AsterixLabelAttribute]
    13.     public float floatWithHeader;
    It looks like this in the inspector (Notice "Test Header" appears twice - once as a header, once in the label):
    https://www.dropbox.com/s/4vri2ny0mmhcpty/Screenshot 2015-04-07 08.49.14.png?dl=0


    I believe the Header decorator drawer doesn't interact nicely with other attributes (*edit* "attributes" used to say "properties"). I'm starting to consider writing a workaround of a "HeaderAndAsterix" attribute that adds in my own header.
     
    Last edited: Apr 8, 2015
  4. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    186
    Hey there,

    Your are also using property twice. It points to the same element that has the test header. This is why it draws twice. Remove one of the editor properties and you will be good to go.
     
  5. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    Hmm sorry, I'm not quite clear on what you are saying
    - what exactly are you referring to? It is true that I have two attributes associated with the "floatWithHeader" member, though I *thought* that was valid (certainly an annoying shortcoming of the Header attribute if it's not).

    If you are referring to the OnGUI script, this display issue occurs even with a super simple drawer:
    Code (CSharp):
    1.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    2.     {
    3.         EditorGUI.PropertyField(position, property, new GUIContent("*" + label.text));
    4.     }
    Anyway I'm about at the end of my rope on this one. The fact that the header text reappears in the label of my attribute tells me something whacky is going on. I'm probably going to just workaround it by adding an optional Header string into my attribute, and displaying it as a separate line if it's included.
     
  6. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    Oh and I just tried to use [Header] in conjunction with Unity's built in PropertyDrawer [Range (min,max)] and it does display properly. Which *suggests* that there is something I can do to fix it.
     
  7. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    Ok yeah, now I see what you were saying @BMayne -- I'm using EditorGUI.PropertyField and passing it my property that I'm trying to render (the entire thing). Therefore it probably recalls the decorator all over again...

    My actual attribute can be applied only to Object references, so I can use EditorGui.ObjectField.

    Ugh! Finally got it. Thanks for your help and patience!
     
    BMayne likes this.
  8. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    186
    No problem :)