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;
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");
}
}
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.