[Custom Editor] Fade group inside fade group

Hi

I’m working on a custom editor and I am trying to use a fade group inside another fade group. When I did this it kinda broke. This is what I want to happen: Imgur (I can’t get the uploader to work to I have to link the gifs, sorry)
But this is what happens: Imgur

If you can’t tell what is happening, when I click the “Is Light” toggle is should close the whole thing pretty much but it stops as the first “EndFadeGroup()” and then jumps to the closed state.

Here’s my code for this part of the editor.

if(EditorGUILayout.BeginFadeGroup(showLightSettings.faded))
{
    EditorGUILayout.BeginVertical("Box");

    script.isLight = EditorGUILayout.Toggle("Is Light", script.isLight);

    if(EditorGUILayout.BeginFadeGroup(isLight.faded))
    {
        script.allowLightIntensity = EditorGUILayout.Toggle("Allow Light Intensity", script.allowLightIntensity);
        if (EditorGUILayout.BeginFadeGroup(allowLightIntensity.faded))
        {
            script.minLightInten = EditorGUILayout.FloatField("Minimum Light Intensity", script.minLightInten);
            script.maxLightInten = EditorGUILayout.FloatField("Maximum Light Intensity", script.maxLightInten);
            EditorGUILayout.Space();
        }
        EditorGUILayout.EndFadeGroup();

        script.allowLightRange = EditorGUILayout.Toggle("Allow Light Range", script.allowLightRange);
        if (EditorGUILayout.BeginFadeGroup(allowLightRange.faded))
        {
            script.minLightRange = EditorGUILayout.FloatField("Minimum Light Range", script.minLightRange);
            script.maxLightRange = EditorGUILayout.FloatField("Maximum Light Intensity", script.maxLightRange);
            EditorGUILayout.Space();
        }
        EditorGUILayout.EndFadeGroup();
    }
    EditorGUILayout.EndFadeGroup();

    EditorGUILayout.EndVertical();
    EditorGUILayout.Space();
}

The “isLight.faded” and such are being set in the bottom using this code.

isLight.target = script.isLight;
allowLightIntensity.target = script.allowLightIntensity;
allowLightRange.target = script.allowLightRange;

Any help is greatly appreciated!

Thanks in advance!

The FadeGroup is actually a quite hacky approach. As far as i can tell it’s not ment to be nested. It uses a hybrid approach. It creates a special layout group which scales it’s calculated values by the current fade value and creates an additional GUI.BeginGroup with the scaled rect to clip the content. This most likely messes up the layout hierarchy.

The problem is most likely the two early exits at the beginning:

public static bool BeginFadeGroup(float value)
{
	if (value == 0f)
	{
		return false;
	}
	if (value == 1f)
	{
		return true;
	}
	GUILayoutFadeGroup gUILayoutFadeGroup = (GUILayoutFadeGroup)GUILayoutUtility.BeginLayoutGroup(GUIStyle.none, null, typeof(GUILayoutFadeGroup));
	gUILayoutFadeGroup.isVertical = true;
	gUILayoutFadeGroup.resetCoords = true;
	gUILayoutFadeGroup.fadeValue = value;
	gUILayoutFadeGroup.wasGUIEnabled = GUI.enabled;
	gUILayoutFadeGroup.guiColor = GUI.color;
	if (value != 0f && value != 1f && Event.current.type == EventType.MouseDown)
	{
		Event.current.Use();
	}
	EditorGUIUtility.LockContextWidth();
	GUI.BeginGroup(gUILayoutFadeGroup.rect);
	return value != 0f;
}

They prevent the creation of the layout group and the GUI group when it’s fully visible or fully collapsed. I first thought that should throw some errors, however “EndFadeGroup” is implemented like this

public static void EndFadeGroup()
{
	GUILayoutFadeGroup gUILayoutFadeGroup = EditorGUILayoutUtilityInternal.topLevel as GUILayoutFadeGroup;
	if (gUILayoutFadeGroup != null)
	{
		GUI.EndGroup();
		EditorGUIUtility.UnlockContextWidth();
		GUI.enabled = gUILayoutFadeGroup.wasGUIEnabled;
		GUI.color = gUILayoutFadeGroup.guiColor;
		GUILayoutUtility.EndGroup("GUILayout.EndVertical");
		GUILayoutUtility.EndLayoutGroup();
	}
}

So it simply grabs the top group and if it’s a fade group it closes it. However since the collapsed and fully visible groups don’t actually create any groups the EndFadeGroup of the nested group will actually close the outer group since that’s the last group on the layout stack.

With the early exits they seem to try to save some processing, however they can’t reliable derive the state of the group inside “EndFadeGroup”-

So in short: This is a bug or at least a situation they didn’t think of. One solution would be to replace all EndFadeGroup calls with a “custom” EndFadeGroup like this:

public static void FixedEndFadeGroup(float aValue)
{
    if (aValue == 0f || aValue == 1f)
        return;
    EditorGUILayout.EndFadeGroup();
}

Just pass in the same float value you passed in to BeginFadeGroup.

If I find the time I’ll file a bug report about this ^^. Though the priority of this issue is most likely very low since it only affects editor gui in rare circumstances.

For future reference, the fix Bunny posted won’t be needed anymore from 2018.3, as the groups always remain active, even when fade is 0 or 1. So simply calling EditorGUILayout.EndFadeGroup() will do the trick.

Otherwise you will get a lot of GUI Error: You are pushing more GUIClips than you are popping errors