Call EditorGUILayout.PropertyField of an element of an array

Hi, Since I haven’t got any response on the following link, I’m re-posting the problem here at the forums, hoping that somebody point me to the right direction.

http://answers.unity3d.com/questions/825992/call-editorguilayoutpropertyfield-of-an-element-of.html

I have a class A that inherits from Monobehaviour, with public variables:

    publicclass A :MonoBehaviour
    {
      publicint num;
      publicstring s;
    }

When you add A component to a gameobject, you can easily modify the variables, since it has its inspector drawn automatically.

But I have another class B

    publicclass B :MonoBehaviour
    {
      publicList<A> vars;
    }

Now I want to create a custom editor for B:

    [CustomEditor(typeof(B))]
    publicBEditor:Editor
    {
     publicoverridevoidOnInspectorGUI()
     {
      var t = target as B;
      for(int i =0; i < t.vars.Count; i++)
      {
        // Here I want to DrawDefaultInspector for t.vars[i]
        // or in other words the default inspector for an object
        // of class A
      }
     DrawDefaultInspector();
     }
    }

How do I draw the default inspector of an object inherited from class A, within custom editor of class B?

How can I do this with minimum pain? (Note: I can go reflection, I consider that to be no pain)

Use Editor.serializedObject and GetArrayElementAtIndex. This way you get a SerializedProperty that can be used with the EditorGUI.PropertyField.

Or use Property drawers so you don’t have to fiddle with the list size

//Assets/classA.cs
using UnityEngine;
using System.Collections;

public class classA: MonoBehaviour {
    public int someInt;
    public string someString;
}

//Assets/classB.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class classB: MonoBehaviour {
    public List<classA> myList;
}

//Assets/Editor/DrawA.cs
using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomPropertyDrawer( typeof( classA ) )]
public class DrawA : PropertyDrawer {

    public override float GetPropertyHeight ( SerializedProperty property, GUIContent label ) {
        return 32; //2 lines of fields
    }

    public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label ) {
        EditorGUI.BeginProperty( position, label, property );
        position = EditorGUI.PrefixLabel( position, GUIUtility.GetControlID( FocusType.Passive ), label );

        //store current indent and label width
        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
        float oldWidth = EditorGUIUtility.labelWidth;
        EditorGUIUtility.labelWidth = 80;

        position.height = 16;

        //get reference to the class object
        classA theObject = (classA) property.objectReferenceValue;

        //adjust position Rect for controls
        Rect r = position;
        theObject.someInt = EditorGUI.IntField( r, "Some Int", theObject.someInt );
        r.y += r.height;
        r.x += 80; //text areas dont come with labels, so make your own and offset next control
        GUI.Label( r, "Some String" );
        r.width -= 80;
        theObject.someString = EditorGUI.TextArea( r, theObject.someString );

        //reset indent and label width
        EditorGUI.indentLevel = indent;
        EditorGUIUtility.labelWidth = oldWidth;
        EditorGUI.EndProperty();
    }
}

This doesn’t give me the field’s correct inspector, it simply gives you the array element presentation of that. It’s no difference from drawing the array itself.

Don’t you mean class B ?

If not, how does this affect the array drawing with the type of element A ?

Nah it’s changing how any occurrance of a public variable of type A is drawn.
I just realised i didn’t include a field for assign the actual objects though:

//Assets/Editor/DrawA.cs
using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomPropertyDrawer( typeof( classA ) )]
public class DrawA : PropertyDrawer {

   public override float GetPropertyHeight ( SerializedProperty property, GUIContent label ) {
     if ( property.objectReferenceValue != null ) return 46; //3 Lines of fields
     return 16; //1 line of fields
   }

   public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label ) {
     EditorGUI.BeginProperty( position, label, property );
     //position = EditorGUI.PrefixLabel( position, GUIUtility.GetControlID( FocusType.Passive ), label );

     //store current indent and label width
     int indent = EditorGUI.indentLevel;
     EditorGUI.indentLevel = 0;
     float oldWidth = EditorGUIUtility.labelWidth;
     EditorGUIUtility.labelWidth = 80;


     Rect r = position;
     r.height = 16;

     EditorGUI.PropertyField( r, property );

     //get reference to the class object
     if ( property.objectReferenceValue != null ) {
       classA theObject = (classA) property.objectReferenceValue;

       r.x += 60;
       r.y += r.height;
       theObject.someInt = EditorGUI.IntField( r, "Some Int", theObject.someInt );
       r.y += r.height;
       GUI.Label( r, "Some String" );
       r.x += 80; //text areas dont come with labels, so make your own and offset next control
       r.width -= 80;
       theObject.someString = EditorGUI.TextArea( r, theObject.someString );
     }
     //reset indent and label width
     EditorGUI.indentLevel = indent;
     EditorGUIUtility.labelWidth = oldWidth;
     EditorGUI.EndProperty();
   }
}

Is there a way to call the public property drawing of A without re-writing the GUI from scratch? Because I can also do this within the Editor code.