- Home /
[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: http://i.imgur.com/wsz83ye.gifv (I can't get the uploader to work to I have to link the gifs, sorry)
But this is what happens: http://i.imgur.com/7cLxeIo.gifv
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!
A few thoughts... What of you put EndFadeGroup within the if statement for the BeginFadeGroup? If this is not possible, perhaps you could wrap each EndFadeGroup inside its own if statement to ensure it is only called for the appropriate BeginFadeGroup? If you need clarification, let me know.
That wouldn't work and wouldn't make sense ^^. BeginFadeGroup opens a group and always need to be paired with EndFadeGroup. Even though the problem is related to EndFadeGroup the actual problem is that BeginFadeGroup doesn't always create a group. See my answer for more details ^^.
Answer by Bunny83 · Nov 23, 2015 at 06:31 AM
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.
Answer by Raresh · May 02, 2018 at 09:39 AM
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