/// <summary> Draw a foldout header </summary> /// <param name="title"> The title of the header </param> /// <param name="state"> The state of the header </param> /// <param name="isBoxed"> [optional] is the eader contained in a box style ? </param> /// <param name="hasMoreOptions"> [optional] Delegate used to draw the right state of the advanced button. If null, no button drawn. </param> /// <param name="toggleMoreOptions"> [optional] Callback call when advanced button clicked. Should be used to toggle its state. </param> /// <returns>return the state of the foldout header</returns> public static bool DrawSubHeaderFoldout(GUIContent title, bool state, bool isBoxed = false, Func<bool> hasMoreOptions = null, Action toggleMoreOptions = null) { const float height = 17f; var backgroundRect = GUILayoutUtility.GetRect(1f, height); var labelRect = backgroundRect; labelRect.xMin += 16f; labelRect.xMax -= 20f; var foldoutRect = backgroundRect; foldoutRect.y += 1f; foldoutRect.x += 15 * EditorGUI.indentLevel; //GUI do not handle indent. Handle it here foldoutRect.width = 13f; foldoutRect.height = 13f; // More options var advancedRect = new Rect(); if (hasMoreOptions != null) { advancedRect = backgroundRect; advancedRect.x += advancedRect.width - 16 - 1; advancedRect.height = 16; advancedRect.width = 16; bool moreOptions = hasMoreOptions(); bool newMoreOptions = Styles.DrawMoreOptions(advancedRect, moreOptions); if (moreOptions ^ newMoreOptions) toggleMoreOptions?.Invoke(); } // Background rect should be full-width backgroundRect.xMin = 0f; backgroundRect.width += 4f; if (isBoxed) { labelRect.xMin += 5; foldoutRect.xMin += 5; backgroundRect.xMin = EditorGUIUtility.singleLineHeight; backgroundRect.width -= 3; } // Title EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel); // Active checkbox state = GUI.Toggle(foldoutRect, state, GUIContent.none, EditorStyles.foldout); var e = Event.current; if (e.type == EventType.MouseDown && backgroundRect.Contains(e.mousePosition) && !advancedRect.Contains(e.mousePosition) && e.button == 0) { state = !state; e.Use(); } return state; }
/// <summary>Draw a header toggle like in Volumes</summary> /// <param name="title"> The title of the header </param> /// <param name="group"> The group of the header </param> /// <param name="activeField">The active field</param> /// <param name="contextAction">The context action</param> /// <param name="hasMoreOptions">Delegate saying if we have MoreOptions</param> /// <param name="toggleMoreOptions">Callback called when the MoreOptions is toggled</param> /// <returns>return the state of the foldout header</returns> public static bool DrawHeaderToggle(GUIContent title, SerializedProperty group, SerializedProperty activeField, Action <Vector2> contextAction = null, Func <bool> hasMoreOptions = null, Action toggleMoreOptions = null) { var backgroundRect = GUILayoutUtility.GetRect(1f, 17f); var labelRect = backgroundRect; labelRect.xMin += 32f; labelRect.xMax -= 20f + 16 + 5; var foldoutRect = backgroundRect; foldoutRect.y += 1f; foldoutRect.width = 13f; foldoutRect.height = 13f; var toggleRect = backgroundRect; toggleRect.x += 16f; toggleRect.y += 2f; toggleRect.width = 13f; toggleRect.height = 13f; // More options 1/2 var moreOptionsRect = new Rect(); if (hasMoreOptions != null) { moreOptionsRect = backgroundRect; moreOptionsRect.x += moreOptionsRect.width - 16 - 1 - 16 - 5; moreOptionsRect.height = 15; moreOptionsRect.width = 16; } // Background rect should be full-width backgroundRect.xMin = 0f; backgroundRect.width += 4f; // Background float backgroundTint = EditorGUIUtility.isProSkin ? 0.1f : 1f; EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f)); // Title using (new EditorGUI.DisabledScope(!activeField.boolValue)) EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel); // Foldout group.serializedObject.Update(); group.isExpanded = GUI.Toggle(foldoutRect, group.isExpanded, GUIContent.none, EditorStyles.foldout); group.serializedObject.ApplyModifiedProperties(); // Active checkbox activeField.serializedObject.Update(); activeField.boolValue = GUI.Toggle(toggleRect, activeField.boolValue, GUIContent.none, CoreEditorStyles.smallTickbox); activeField.serializedObject.ApplyModifiedProperties(); // More options 2/2 if (hasMoreOptions != null) { bool moreOptions = hasMoreOptions(); bool newMoreOptions = Styles.DrawMoreOptions(moreOptionsRect, moreOptions); if (moreOptions ^ newMoreOptions) { toggleMoreOptions?.Invoke(); } } // Context menu var menuIcon = CoreEditorStyles.paneOptionsIcon; var menuRect = new Rect(labelRect.xMax + 3f + 16 + 5, labelRect.y + 1f, menuIcon.width, menuIcon.height); if (contextAction != null) { GUI.DrawTexture(menuRect, menuIcon); } // Handle events var e = Event.current; if (e.type == EventType.MouseDown) { if (contextAction != null && menuRect.Contains(e.mousePosition)) { contextAction(new Vector2(menuRect.x, menuRect.yMax)); e.Use(); } else if (labelRect.Contains(e.mousePosition)) { if (e.button == 0) { group.isExpanded = !group.isExpanded; } else if (contextAction != null) { contextAction(e.mousePosition); } e.Use(); } } return(group.isExpanded); }
/// <summary> Draw a foldout header </summary> /// <param name="title"> The title of the header </param> /// <param name="state"> The state of the header </param> /// <param name="isBoxed"> [optional] is the eader contained in a box style ? </param> /// <param name="hasMoreOptions"> [optional] Delegate used to draw the right state of the advanced button. If null, no button drawn. </param> /// <param name="toggleMoreOptions"> [optional] Callback call when advanced button clicked. Should be used to toggle its state. </param> /// <returns>return the state of the foldout header</returns> public static bool DrawHeaderFoldout(GUIContent title, bool state, bool isBoxed = false, Func <bool> hasMoreOptions = null, Action toggleMoreOptions = null) { const float height = 17f; var backgroundRect = GUILayoutUtility.GetRect(1f, height); var labelRect = backgroundRect; labelRect.xMin += 16f; labelRect.xMax -= 20f; var foldoutRect = backgroundRect; foldoutRect.y += 1f; foldoutRect.width = 13f; foldoutRect.height = 13f; foldoutRect.x = labelRect.xMin + 15 * (EditorGUI.indentLevel - 1); //fix for presset // More options 1/2 var moreOptionsRect = new Rect(); if (hasMoreOptions != null) { moreOptionsRect = backgroundRect; moreOptionsRect.x += moreOptionsRect.width - 16 - 1; moreOptionsRect.height = 15; moreOptionsRect.width = 16; } // Background rect should be full-width backgroundRect.xMin = 0f; backgroundRect.width += 4f; if (isBoxed) { labelRect.xMin += 5; foldoutRect.xMin += 5; backgroundRect.xMin = EditorGUIUtility.singleLineHeight; backgroundRect.width -= 1; } // Background float backgroundTint = EditorGUIUtility.isProSkin ? 0.1f : 1f; EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f)); // More options 2/2 if (hasMoreOptions != null) { EditorGUI.BeginChangeCheck(); Styles.DrawMoreOptions(moreOptionsRect, hasMoreOptions()); if (EditorGUI.EndChangeCheck() && toggleMoreOptions != null) { toggleMoreOptions(); } } // Title EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel); // Active checkbox state = GUI.Toggle(foldoutRect, state, GUIContent.none, EditorStyles.foldout); var e = Event.current; if (e.type == EventType.MouseDown && backgroundRect.Contains(e.mousePosition) && !moreOptionsRect.Contains(e.mousePosition) && e.button == 0) { state = !state; e.Use(); } return(state); }