Custom Editor for embedded ScriptableObjects list
If I have a custom editor for a ScriptableObject, and the ScriptableObject has a list of interfaces inside it, what would be the best way to draw the default inspector for those objects?
--More Description Below--
I have a custom editor for a ScriptableObject asset in my project hierarchy. The asset script contains a list of ScriptableObjects that also inherit from IModuleComponent. What I want to do is display the default inspector for the embedded scriptableobjects/IModuleComponents in my custom inspector, to essentially treat the scriptableobject asset like a gameobject and then get all the components in the list to look like monobehaviors do on a gameobject.
I can get something like what I want to work by looping through the embedded components and calling an inherited function, but that requires me to write a custom IModuleComponent.DrawInInspector function for every new component.
Is there a way to get Unity to draw an inspector for each module without writing custom draw code for every module? Or if not, how would I get the custom function to look more like what Unity has?
Here is some of my code. This first snippet is my custom editor.
if (showPosition[i])
{
GUILayout.Space(10);
//EditorGUILayout.ObjectField(myTarget.componentModules[i] as ScriptableObject, typeof(ScriptableObject), false);
(myTarget.componentModules[i] as IComponentModule).DrawInInspector();
}
And in my component code I have this
public void DrawInInspector()
{
#if UNITY_EDITOR
suckItUnity = EditorGUILayout.Toggle("Suck it Unity", suckItUnity);
#endif
}
Answer by syscrusher · Sep 04, 2016 at 06:27 PM
@Gamingdrake, I know it's been a long time since your post, but I think I have your answer. I stumbled upon your question while trying to solve the same problem here. :)
Disclaimer: The following pattern is working for me in a prototype, but I have not fully tested this code for production. Also, I've "filed off the serial numbers" in this example to make it more generic, so there may be some syntax errors. I'm working in Unity 5.4.0.
The class MyOuterObject is a traditional GameObject with a custom editor as shown below:
[CustomEditor(typeof(MyOuterObject), true)]
public class MyOuterObjectEditor : Editor {
SerializedProperty myInnerObjectSO;
private static GUIContent innerObjectPrompt = new GUIContent("Inner Object", "Provide an Inner Object asset to define the Outer Object's appearance");
public override void OnInspectorGUI() {
serializedObject.Update();
MyOuterObject targetOuter = (MyOuterObject) target;
myInnerObjectSO = serializedObject.FindProperty("innerObject");
EditorGUILayout.PropertyField(myInnerObjectSO, innerObjectPrompt);
MyInnerObject inner = targetInner.innerObject;
Editor innerEditor = MyInnerClassEditor.CreateEditor(inner);
innerEditor.DrawDefaultInspector();
serializedObject.ApplyModifiedProperties();
}
}
The custom editor for the inner object (a ScriptableObject saved as an asset file) looks like this:
public class MyInnerClassEditor : Editor {
GUIContent myColorPrompt = new GUIContent("Color", "Pick a color for this asset");
public override void OnInspectorGUI() {
serializedObject.Update();
SerializedProperty myColor = serializedObject.FindProperty("myColor");
EditorGUILayout.PropertyField(myColor, myColorPrompt);
// Draw your other fields here
serializedObject.ApplyModifiedProperties();
}
}
The myColor property of the inner class is just a Color value.
With this code, you can inspect any of the .asset files of the MyInnerObject type. You can drag and drop (or popup select) a file into the innerObject field in the outer object's Inspector. Changes made in the asset file's Inspector are reflected in all instances of MyOuterObject that use the particular MyInnerObject asset, and vice versa.
Again, I note that I've created this code about half an hour ago, so it is emphatically not tested to production-ready standards, but the underlying technique seems to work in my prototype sandbox.
I hope this is helpful to the original poster and to others. Since my own code is still under development, suggested improvements would be most welcome.
Update: The concept is sound, but I've made some improvements to the details. In particular, it was helpful to put the inner object's editor GUI into a "foldout" when it's embedded by the outer object. The good news, though, is that I've spent most of the day today testing this further, and so far the basic pattern has worked well.
In "$$anonymous$$yInnerObject inner = targetInner.innerObject;" where does targetInner come from? what variable is it referring to?
This helped me a lot, but I replaced the function call innerEditor.DrawDefaultInspector() with innerEditor.OnIspectorGUI() in order to get the custom inspector to be drawn ins$$anonymous$$d of the default one (like what can be seen on https://stackoverflow.com/a/16060171/2593324) - I hope this helps others that run into this.
Answer by Spy-Shifty · Nov 05, 2016 at 10:05 PM
What does EditorMarkerTypeEditor do?
Can you post that source pls?
Oh, sorry!
When I was genericizing the names of classes in my example code, the intent was to decouple them from my real application. I missed a change or two!
I have edited the code in my answer to fix it. Sorry about that!