- Home /
Header attribute and Custom Property Drawer overlap in inspector, repeat header text
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.
Edit Here is sample code of the two attributes used together:
public class TestAsterixLabel : MonoBehaviour
{
[Header ("Header")]
[AsterixLabelAttribute]
public GameObject FieldWithAttributes;
}
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?
https://www.dropbox.com/s/b5rxtltyr5smfhy/Screenshot%202015-04-05%2017.06.30.png?dl=0
Edit I've actually stripped out everything on my attribute drawer, and the problem still exists. Also note this does seem to have to do with the implementation of GetPropertyHeight, either. Or the order of the two attributes on the field.
CustomPropertyDrawer(typeof(RequireWireAttribute))]
public class RequireWireDrawer : PropertyDrawer
{
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.PropertyField(position, property, label);
}
}
Answer by DoTA_KAMIKADzE · Apr 06, 2015 at 01:03 PM
Do you utilize those at start and end of your property drawer?:
If I understood you right - then not, but you should to.
P.S. Here is an updated answer with a "basic" example how to use those^ above:
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(position, property, new GUIContent("*" + label.text));
EditorGUI.EndProperty();
}
I've even tested it on my end just to make sure that it does work, and it does.
P.P.S. Here is an update that explains how to do it with Color:
1) In your code that will be shown in Inspector somewhere:
[Header("I'm header")]
public Color colWithHead;
public Color colWithoutHead;
2.1) Where you add your Custom drawers:
[CustomPropertyDrawer(typeof(HeaderAttribute))]
public class HColorDraw : PropertyDrawer
{
public static GUIStyle HeaderStyle
{
get
{
GUIStyle labelStyle = new GUIStyle(EditorStyles.label);
labelStyle.fontStyle = FontStyle.Bold;
labelStyle.alignment = TextAnchor.UpperCenter;
labelStyle.fontSize = 14;
labelStyle.normal.textColor = new Color32(255, 0, 0, 255);
return labelStyle;
}
}
HeaderAttribute headAttribute { get { return ((HeaderAttribute)attribute); } }
private const float headHeight = 16f;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType == SerializedPropertyType.Color)
{
EditorGUI.BeginProperty(position, label, property);
string labTxt = "*" + label.text;
EditorGUI.LabelField(position, headAttribute.header, HeaderStyle);
position.yMin += headHeight;
property.colorValue =EditorGUI.ColorField(position, labTxt, property.colorValue);
EditorGUI.EndProperty();
}
else
{
//...
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (property.propertyType == SerializedPropertyType.Color)
{
return base.GetPropertyHeight(property, label) + headHeight;
}
else return base.GetPropertyHeight(property, label);
}
}
[CustomPropertyDrawer(typeof(Color))]
public class ColorDraw : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(position, property, new GUIContent("*" +label.text));
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label);
}
}
And that results in:
2.2) Alternatively you could just draw yourself everything, like I have shown with just Header and that will work with default HeaderDrawer:
[CustomPropertyDrawer(typeof(Color))]
public class ColorDraw : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
property.colorValue = EditorGUI.ColorField(position, "*" + label.text, property.colorValue);
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label);
}
}
P.P.P.S. Added color saving for the code above^ just for the sake of completeness. If I've missed something let me know, that kinda lots of coding over here ))
I did on my original drawer (before stripping it down to this line of code) but it doesn't seem to make a difference whether I add it or not, as far as this bug goes.
You're doing something wrong for sure, I'll update my answer with a "basic" example how to add asterisk in few $$anonymous$$.
I appreciate you taking time to help - did you try that on a field that also has a [Header ("TestHeader")] attribute? It still has the overlap issue for me. I'm using Unity 5.0.0f4 (latest)
https://www.dropbox.com/s/5h192jg8t0wgbzl/Screenshot%202015-04-06%2010.47.33.png?dl=0
You should make a [CustomPropertyDrawer(typeof(HeaderAttribute))]
But if you're ok with duplication then you can do something like this:
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label) + 24f;//24f is the height of default HeaderDrawer, if you have a custom DecoratorDrawer for header then use its height
}
P.S. Just in case you didn't know if you'll go with HeaderAttritube property drawer:
You can get the type of "current field" like that:
if (property.propertyType == SerializedPropertyType.String) Debug.Log("I'm string");
//or like that:
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
{
Debug.Log("I'm int");
break;
}
}
Are you getting the correct results from that code? This is all of my script - it's not much but it's a nice example of the issue in action:
// Tester class
public class TestAsterixLabel : $$anonymous$$onoBehaviour
{
[Header ("Header")]
[AsterixLabelAttribute]
public GameObject FieldWithAttributes;
}
// Attribute
[System.AttributeUsage (System.AttributeTargets.Field)]
public class AsterixLabelAttribute : PropertyAttribute {
}
//Custom Drawer
[CustomPropertyDrawer(typeof(AsterixLabelAttribute))]
public class AsterixLabelDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(position, property, new GUIContent("*" + label.text));
EditorGUI.EndProperty();
}
}
Answer by edwardrowe · Apr 08, 2015 at 03:41 PM
Ok I've figured this out. And it was kind of dumb.
So the problem is that I am using EditorGUI.PropertyField and passing in the very property that I'm trying to display. This must in turn re-call the decorators.
When I switched this to EdtiorGUI.ObjectField (which is the type I'm ultimately looking for), it works fine. Thanks for everyone's help.
That's the 2.2 way in my answer )) also don't forget to return the value to the property itself (that is also shown in my 2.2 code example).
Ah I see that now. The signficance of the EditorGUI.PropertyField function was just lost on me and clouded the way I read your response.