Indenting Foldouts in the Editor

Hey all…

I’m working on a custom inspector and in an effort to tidy up the interface, I was wondering how to do staggered sublevels with the foldouts. Here’s an example clip from the scene hierarchy:

And here’s what I have in my inspector:

I’m using the EditorGUILayout classes and there doesn’t seem to be a way to indent things a fixed amount (you can fake it with labels by adding spaces, but the controls are still aligned with the left edge, and the foldout arrows don’t have integrated labels to pad).

I’ve been experimenting with the BeginHorizontal() calls but these seem to evenly space the controls across the inspector, with no ability to control the spacing. Any ideas?

thanks!

Untested, but you can probably use something like:

EditorGUILayout.BeginVertical();
  EditorGUILayout.Foldout(...); // parent foldout
  EditorGUILayout.BeginHorizontal();
    EditorGUILayout.Space();
    EditorGUILayout.Foldout(...); // child foldout
  EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();

I tried that-- it ends up spacing like this:

…the elements are spaced evenly across the horizontal. It’s possible to chain a bunch together like so:

EditorGUILayout.BeginVertical();
  EditorGUILayout.Foldout(...); // parent foldout
  EditorGUILayout.BeginHorizontal();
    EditorGUILayout.Space();
    EditorGUILayout.Foldout(...); // child foldout
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
    EditorGUILayout.Space();
  EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();

so that the foldout occurs at the 1/12 mark… But I feel like there must be a better way than that.

This is kind of old now, but it looks like the foldouts are right aligned (rather than left). It would explain the behavior in both code samples.

Isn’t the problem that it is a horizontal group instead of a vertical one?

Up~,I also have this problem

Sorry for necroposting.
Answer for question is using GUILayout.Space(10) instead EditorGUILayout.Space(); in Molix code… may be this help some one

So, one Space() is then enough per tree row. Then:

A
|—B
…|—C

Try having some descriptor struct, that contains both depth and content, like:

public struct Descriptor {
    public int Depth;
    public string Text;
}

Then your nodes are:

A {Depth = 0}
B {Depth = 1}
C {Depth = 2}

And you have to loop through the array of descriptors, and for each:

EditorGUILayout.BeginHorizontal();
    EditorGUILayout.Space(descriptor.Depth * 10); // or even GUILayout.Label("", GUILayout.Width(10));
    EditorGUILayout.Foldout(...);
EditorGUILayout.EndHorizontal();

I use EditorGUI.indentLevel. Unity - Scripting API: EditorGUI.indentLevel

When I build my custom project, i just loop all folders and adjust the level based on their depth.

FYI, unfortunately indentLevel doesn’t apply to buttons. If you want them indented (ex: advanced operations), this works:

EditorGUILayout.BeginHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();

if(GUILayout.Button(“MyButton”))
{
// Do stuff.
}

EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();

The space is forced to be to the left of whatever is in the vertical group on the right.

Old thread, but…

So far as I can tell, the indent width seems to be about (exactly?) 15 pixels, and there’s a 4 pixel margin at the edge of windows. So, you should be able to use:

GUILayout.Space(indentLevel * 15 + 4);

to get the indent spacing you need for GUILayout controls (such as Button()).

Edit: Corrected the pixel count to 15 (had previously stated it was 16, but I’ve checked the source code and know better now).

Edit2: Corrected the formula to always add an additional 4 pixels to compensate for the EditorWindow margin (which is also ignored by GUILayout).

1 Like

“Old thread, but…”
This thing here says - “To maximize future compatibility, do not make assumptions about what a specific indent level means…

Now lets do just that:

EditorGUI.indentLevel++;

        var texPreviewRect = EditorGUILayout.GetControlRect(false, 40);
        texPreviewRect = EditorGUI.IndentedRect(texPreviewRect);
        if(_prop_colorDistiortion.objectReferenceValue != null)
        {
            EditorGUI.DrawPreviewTexture(new Rect(texPreviewRect.x, texPreviewRect.y, 40, texPreviewRect.height), _prop_tex.objectReferenceValue as Texture);
        }
        else
        {
            EditorGUI.DrawPreviewTexture(new Rect(texPreviewRect.x, texPreviewRect.y, 40, texPreviewRect.height), Texture2D.whiteTexture);
        }

        EditorGUI.indentLevel--;

The key function in the above snippet is: recalculating the texPreviewRect using EditorGUI.IndentedRect(Rect source), for which i dont seem to find reference around the API, maybe its a new undocumented thing :), but basically it seems to applies the indentation to the passed rect value

4 Likes

I’m back! So, here’s what I ultimately decided is the most convenient way to do buttons in the Editor layout (short of Unity actually adding EditorGUILayout.Button):

    private bool EditorButton(string label, params GUILayoutOption[] options)
    {
        bool clickedState = false;

        EditorGUILayout.BeginHorizontal();
        {
            var reservedSpace = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(options));

            if (GUI.Button(reservedSpace, label))
            {
                clickedState = true;
            }
        }

        EditorGUILayout.EndHorizontal();

        return clickedState;
    }
2 Likes