- Home /
EditorGUI.Foldout: docs wrong?
I have created a very simple property drawer to test this: I use the position passed into the property drawer to both draw a foldout, and to draw a box styled label. The same position RECT is used to draw both, and I expected the result to look similar to the position as defined in the docs:
Note that in this image (from https://docs.unity3d.com/ScriptReference/EditorGUI.Foldout.html), the position.xMin is to the left of the triangle indicator.
However, my tests show the position differently! In this test, the position.XMin is to the RIGHT of the triangle indicator. So, it appears, the indicator is NOT actually drawn inside the specified position Rect.
Below is the entirety of my test project. Can someone else confirm they get the same results, and/or explain what I'm misunderstanding?
TestMono.cs
using UnityEngine;
[System.Serializable]
public class PropTestClass
{
string a;
}
public class TestMono : MonoBehaviour {
public PropTestClass p;
}
Editor\ TestMonoPropertDrawer.cs
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(PropTestClass))]
public class TestMonoPropertDrawer : PropertyDrawer
{
bool showDetailsFlag;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Debug.Log("foldout position" + position.ToString());
showDetailsFlag = EditorGUI.Foldout(position, showDetailsFlag, new GUIContent("test Label"), false);
Debug.Log("box position" + position.ToString());
EditorGUI.LabelField(position, GUIContent.none, GUI.skin.box);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return 20;
}
}
Edit: Both Debug.Log calls, in the property drawer, show the exact same position Rect value.
Answer by Bunny83 · Mar 03, 2017 at 07:31 PM
Well, it's not entirely "wrong". That's because the Foldout behaves differently depending on the state of "EditorGUIUtility.hierarchyMode". If hierarchyMode is true it adds the padding of the foldoutstyle to the left of the given position. If it's false it does not. The following lines are right at the beginning of the Foldout method:
if (EditorGUIUtility.hierarchyMode)
{
int num = EditorStyles.foldout.padding.left - EditorStyles.label.padding.left;
position.xMin -= (float)num;
}
The inspector is pretty much the only one who is setting the hierarchyMode to true. In most other cases if should be false.
So yes, then used in a custom inspector it will offset itself to the left to give space for the "triangle". If rendered anywhere else (like in the example they rendered it in a custom EditorWindow) the triangle would be inside the given rect.
So the docs aren't wrong, but missed to mention that polymorph behaviour ^^.
You are much more generous than me: I would have to classify that position box in the docs as "just-plain-wrong".
Good idea to look up the decompiled code (sad that it is necessary)! I followed your lead on that, and found some more "position mucking with" stuff, in that same function down where it handles repaint events. Apparently, it ALSO adjusts the position using GUI.indent.
So it looks like, if one wants the control to draw in the ACTUAL position RECT passed to the function, without additional layout formatting (like the pic in the docs): one must manually set:
EditorGUI.indet=0;
and
EditorGUIUtility.hierarchy$$anonymous$$ode= false;
before calling the EditorGUI.Layout function. Does that sound right to you @Bunny83? Any others I missed?
Just to clarify: "The inspector is pretty much the only one who is setting the hierarchy$$anonymous$$ode to true." So, this is the case for all custom PropertyDrawers and all CustomEditors? Or do I misunderstand? Thanks, as always, for your help!
Yes, everything that is called from the inspector of course is also affected. So yes it includes all Editors and PropertyDrawers.
I think the point here is that the Inspector has this "reserved" column at the front. The actual usable space starts to the right of that column. Inside that "column" the Foldout (any maybe some other controls) draw those "expanding" handles, but only when drawn from the inspector.
As i said this "special behaviour" just isn't documented. The example they used in the docs didn't use the inspector but an editor window. So everything is correct in the docs-example (at least this time ^^).
btw: EditorGUI.indent is internal and a read-only property:
internal static float indent { get { return (float)EditorGUI.indentLevel * 15f; } }
indentLevel on the other hand can be set. It usually is set to 0. Only when the inspector is showing nested objects (like custom serializable classes or array items) it will increase it for each nested level. When you mess around with those in a PropertyDrawer you might want to store the current values and reset them at the end of your code.
There is even an internal class that does this ^^. "UnityEditorInternal.VR.PlayerSettingsEditorVR" inside the "DrawVRDeviceElement" method they have:
bool hierarchy$$anonymous$$ode = EditorGUIUtility.hierarchy$$anonymous$$ode;
EditorGUIUtility.hierarchy$$anonymous$$ode = false;
vRCustomOptions.IsExpanded = EditorGUI.Foldout(position, vRCustomOptions.IsExpanded, "", false, EditorStyles.foldout);
EditorGUIUtility.hierarchy$$anonymous$$ode = hierarchy$$anonymous$$ode;
btw: That's the perfect example why global state is evil ^^. Some static state that is read somewhere inside a little nested helper function changes the behaviour and you have no idea what's going on ^^.
"That's the perfect example why global state is evil ^^. Some static state that is read somewhere inside a little nested helper function changes the behaviour and you have no idea what's going on ^^"
Here here! For a while, I was sitting there wondering why I couldn't do basic addition anymore.
Hmm, so is that "reserved" column you mentioned defined by EditorStyles.label.padding.left? Looking at the EditorGUI source code, I do not see where the other control types, like say.. Label, are applying that offset (nor the indent offset). (Even when I try to account for the above stuff, something seems to be messing up positions if I do NOT override those two state values: starting to suspect this "reserved" space.)
Your answer
![](https://koobas.hobune.stream/wayback/20220612112352im_/https://answers.unity.com/themes/thub/images/avi.jpg)