Using custom editor for an inherited class

Hello,

I have a class A, with its own variables. I made a FoldoutGroup for it and it works:

using UnityEditor;
// ....
[CustomEditor(typeof(A))]
[CanEditMultipleObjects]
public class AEditor : Editor
{
    public bool state = true;
    public override void OnInspectorGUI()
    {
        state = EditorGUILayout.BeginFoldoutHeaderGroup(state, "A Stuff");
        if (state)
            base.OnInspectorGUI();
        EditorGUILayout.EndFoldoutHeaderGroup();
    }
}

I made a second class B that inherits from A. What I want to achieve:
In the Inspector, B shows 2 foldout groups: “A Stuff” which contains the public members of A, and “B Stuff” which contains the public members of B (without the members of A).

I know it is complex (I managed to crash the Editor trying to do it!), but is there is a way?
I could make B use a FoldoutGroup, but because I am calling “base” it calls its parent (A) and calls its OnInspectorGUI(), which results in drawing the members of A inside B.
The good about base.OnInspectorGUI(); is that I don’t have to build a full custom editor, I can only build the Foldout my self and call base.OnInspectorGUI(); to handle the normal stuff;

Is there a simpler way?

Your Inherited class would just need to derive from the base class editor, like so

public class ClassA : MonoBehaviour
{
}

[CustomEditor(typeof(ClassA),true)]
public class ClassAEditor : Editor
{
    public override void OnInspectorGUI()
    {
        EditorGUILayout.LabelField("I'm a Label From Class A");
    }
}
public class ClassB : ClassA
{
}

[CustomEditor(typeof(ClassB))]
public class ClassBEditor : ClassAEditor
{
    private bool ShowA;

    public override void OnInspectorGUI()
    {
        ShowA = EditorGUILayout.BeginFoldoutHeaderGroup(ShowA, "A Stuff");
        if (ShowA)
            base.OnInspectorGUI();
        EditorGUILayout.EndFoldoutHeaderGroup();

        EditorGUILayout.LabelField("I'm a Label From Class B");
    }
}
2 Likes

With a mix from this answer and C# reflection, I managed to make 2 Foldouts in the child Inspector: one for the parent members and one for the child members:
Parent Code:

using UnityEditor;
using UnityEngine;
using System.Reflection;
using System.Collections.Generic;

public class A : MonoBehaviour
{
    public int A1 = 0;
    public Texture A2;
    public Vector3 V3;
}

[CustomEditor(typeof(A), true)]
[CanEditMultipleObjects]
public class AEditor : Editor
{
    bool s1 = true;
    List<SerializedProperty> sp;

    protected void OnEnable()
    {
        sp = new List<SerializedProperty>();
        A x = new A();
        MemberInfo[] mi = x.GetType().GetFields();
        foreach(MemberInfo m in mi)
        {
            sp.Add(serializedObject.FindProperty(m.Name));
        }
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        s1 = EditorGUILayout.BeginFoldoutHeaderGroup(s1, "A Stuff");
        if (s1)
            foreach (SerializedProperty s in sp)
                EditorGUILayout.PropertyField(s);
        EditorGUILayout.EndFoldoutHeaderGroup();
    }
}

Child Code:

using UnityEditor;
using UnityEngine;
using System.Reflection;
using System.Collections.Generic;

public class B : A
{
    public int B1 = 50;
    public Animator B2;
}

[CustomEditor(typeof(B))]
[CanEditMultipleObjects]
public class BEditor : AEditor
{
    bool s2 = true;
    List<SerializedProperty> sp;

    private new void OnEnable()
    {
        base.OnEnable();

        sp = new List<SerializedProperty>();
        // Get members
        A a = new A(); MemberInfo[] ma = a.GetType().GetFields();
        B b = new B(); MemberInfo[] mb = b.GetType().GetFields();
        foreach (MemberInfo m in mb)
        {
            // Exclude parent members
            if (ArrayUtility.Find(ma, e => e.Name == m.Name) == null)
                sp.Add(serializedObject.FindProperty(m.Name));
        }
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        s2 = EditorGUILayout.BeginFoldoutHeaderGroup(s2, "B Stuff");
        if (s2)
            foreach (SerializedProperty s in sp)
                EditorGUILayout.PropertyField(s);
        EditorGUILayout.EndFoldoutHeaderGroup();
    }
}

Thanks, this solves the inheritance issue.
Adding labels for members one by one would not scale, so using EditorGUILayout.PropertyField(s); was better.