Because arrays in the default inspector are particularly cumbersome, I frequently find myself creating property drawers for them. Mainly, I’m removing the size field and using two buttons to add/remove an entry, and using another property drawer for the entries without drawing the usual ‘Element 0’, Element 1’, etc.
Today, however, I must be doing something horribly wrong because I’m having to change the rect positions in strange ways to get things to look ‘normal’.
In this case, I made a wrapper class that holds an array of a simple class with two fields. The idea is that the two fields will appear on the same line for each array entry, as shown:
The problem, is that in order to produce this result, the rect values are all out of wack and seem to make no sense.
Here is the wrapper property drawer. It simply draws the buttons, and then each line of the array.
[CustomPropertyDrawer (typeof (FS_Detector.EmissionWrapper))]
public class EmissionWrapper : PropertyDrawer {
int lh1 = 18; // line height
public override float GetPropertyHeight( SerializedProperty property, GUIContent label ) {
return lh1 + ( lh1 * property.FindPropertyRelative("emission").arraySize );
}
// Draw the property inside the given rect
public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label ) {
EditorGUI.BeginProperty (position, label, property);
SerializedProperty emissionProp = property.FindPropertyRelative("emission");
Rect textR = new Rect ( position.x, position.y, 100f, lh1 );
Rect ctrlAdd = new Rect ( position.x+70f, position.y+1f, 20f, lh1-6f );
Rect ctrlRem = new Rect ( position.x+93f, position.y+1f, 20f, lh1-6f );
EditorGUI.LabelField( textR, "Emissions", EditorStyles.label );
if ( GUI.Button( ctrlAdd, "+" ) ) {
emissionProp.InsertArrayElementAtIndex( emissionProp.arraySize );
}
if ( GUI.Button( ctrlRem, "-" ) ) {
emissionProp.DeleteArrayElementAtIndex( emissionProp.arraySize-1 );
}
for ( int i=0; i < emissionProp.arraySize; i++ ) {
// draw every element of the array
Rect valueR = new Rect (position.x, position.y + lh1 + (lh1 * i), position.width, lh1 );
EditorGUI.PropertyField( valueR, emissionProp.GetArrayElementAtIndex(i), GUIContent.none );
}
EditorGUI.EndProperty ();
}
}
And here is the property drawer for each array entry:
[CustomPropertyDrawer (typeof (FS_Detector.EmissionBlock))]
public class EmissionBlock : PropertyDrawer {
int lh1 = 18; // line height
// Draw the property inside the given rect
public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label ) {
int indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
Rect textR = new Rect ( position.x+20f, position.y, 100f, lh1 );
Rect typeR = new Rect ( position.x-20f, position.y, 220f, lh1 );
Rect text2R = new Rect ( position.x+135f, position.y, 100f, lh1 );
Rect strengthR = new Rect ( position.x+45f, position.y + lh1, 200f, lh1 );
EditorGUI.LabelField( textR, "Type", EditorStyles.label );
EditorGUI.PropertyField( typeR, property.FindPropertyRelative("type"), GUIContent.none );
EditorGUI.LabelField( text2R, "Strength", EditorStyles.label );
EditorGUI.PropertyField( strengthR, property.FindPropertyRelative("strength"), GUIContent.none );
EditorGUI.indentLevel = indent;
}
}
The problem lines seem to be the rects on lines 11-14.
Compare the rect x-values with where they end up in the picture. For example, according to the code, it looks like typeR (line 12) would be positioned before textR (line 11) based onx location, yet it isn’t.
Also of particular note, is the rect on line 14. The y-value is position.y + lh1, unlike the others (lh1 drops it down a line) yet they all end up on the same line in the pic.
Additionally, changing only the width of these rects also has the side-effect of changing it’s own x location. Somehow.
Any insight as to what’s happening here?