/// <summary> /// Creates a material header scope to display the foldout in the material UI. /// </summary> /// <param name="title">GUI Content of the header.</param> /// <param name="bitExpanded">Bit index which specifies the state of the header (whether it is open or collapsed) inside Editor Prefs.</param> /// <param name="materialEditor">The current material editor.</param> /// <param name="spaceAtEnd">Set this to true to make the block include space at the bottom of its UI. Set to false to not include any space.</param> /// <param name="subHeader">Set to true to make this into a sub-header. This affects the style of the header. Set to false to make this use the standard style.</param> /// <param name="defaultExpandedState">The default state if the header is not present</param> /// <param name="documentationURL">[optional] Documentation page</param> public MaterialHeaderScope(GUIContent title, uint bitExpanded, MaterialEditor materialEditor, bool spaceAtEnd = true, bool subHeader = false, uint defaultExpandedState = uint.MaxValue, string documentationURL = "") { if (title == null) { throw new ArgumentNullException(nameof(title)); } bool beforeExpanded = materialEditor.IsAreaExpanded(bitExpanded, defaultExpandedState); #if !UNITY_2020_1_OR_NEWER oldIndentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = subHeader ? 1 : 0; //fix for preset in 2019.3 (preset are one more indentation depth in material) #endif this.spaceAtEnd = spaceAtEnd; if (!subHeader) { CoreEditorUtils.DrawSplitter(); } GUILayout.BeginVertical(); bool saveChangeState = GUI.changed; expanded = subHeader ? CoreEditorUtils.DrawSubHeaderFoldout(title, beforeExpanded, isBoxed: false) : CoreEditorUtils.DrawHeaderFoldout(title, beforeExpanded, documentationURL: documentationURL); if (expanded ^ beforeExpanded) { materialEditor.SetIsAreaExpanded((uint)bitExpanded, expanded); saveChangeState = true; } GUI.changed = saveChangeState; }
// This one is private as we do not want to have unhandled advanced switch. Change it if necessary. static IDrawer FoldoutGroup <TEnum, TState>(GUIContent title, TEnum mask, ExpandedState <TEnum, TState> state, FoldoutOption options, Enabler showAdditionalProperties, SwitchEnabler switchAdditionalProperties, params ActionDrawer[] contentDrawers) where TEnum : struct, IConvertible { return(Group((data, owner) => { bool isBoxed = (options & FoldoutOption.Boxed) != 0; bool isIndented = (options & FoldoutOption.Indent) != 0; bool isSubFoldout = (options & FoldoutOption.SubFoldout) != 0; bool noSpaceAtEnd = (options & FoldoutOption.NoSpaceAtEnd) != 0; bool expended = state[mask]; bool newExpended = expended; if (isSubFoldout) { newExpended = CoreEditorUtils.DrawSubHeaderFoldout(title, expended, isBoxed); } else { CoreEditorUtils.DrawSplitter(isBoxed); newExpended = CoreEditorUtils.DrawHeaderFoldout(title, expended, isBoxed, showAdditionalProperties == null ? (Func <bool>)null : () => showAdditionalProperties(data, owner), switchAdditionalProperties == null ? (Action)null : () => switchAdditionalProperties(data, owner), GetHelpURL <TEnum>(mask)); } if (newExpended ^ expended) { state[mask] = newExpended; } if (newExpended) { if (isIndented) { ++EditorGUI.indentLevel; } for (var i = 0; i < contentDrawers.Length; i++) { contentDrawers[i](data, owner); } if (isIndented) { --EditorGUI.indentLevel; } if (!noSpaceAtEnd) { EditorGUILayout.Space(); } } })); }
/// <summary> /// Creates a material header scope to display the foldout in the material UI. /// </summary> /// <param name="title">GUI Content of the header.</param> /// <param name="bitExpanded">Bit index which specifies the state of the header (whether it is open or collapsed) inside Editor Prefs.</param> /// <param name="materialEditor">The current material editor.</param> /// <param name="spaceAtEnd">Set this to true to make the block include space at the bottom of its UI. Set to false to not include any space.</param> /// <param name="colorDot">Specify a color to display a dot, like in the layered UI.</param> /// <param name="subHeader">Set to true to make this into a sub-header. This affects the style of the header. Set to false to make this use the standard style.</param> /// <param name="defaultExpandedState">The default state if the header is not present</param> internal MaterialHeaderScope(GUIContent title, uint bitExpanded, MaterialEditor materialEditor, bool spaceAtEnd = true, Color colorDot = default, bool subHeader = false, uint defaultExpandedState = uint.MaxValue) { bool beforeExpanded = materialEditor.IsAreaExpanded(bitExpanded, defaultExpandedState); #if !UNITY_2020_1_OR_NEWER oldIndentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = subHeader ? 1 : 0; //fix for preset in 2019.3 (preset are one more indentation depth in material) #endif this.spaceAtEnd = spaceAtEnd; if (!subHeader) { CoreEditorUtils.DrawSplitter(); } GUILayout.BeginVertical(); bool saveChangeState = GUI.changed; string text = title.text; if (colorDot != default) { text = " " + text; } expanded = subHeader ? CoreEditorUtils.DrawSubHeaderFoldout(text, beforeExpanded, isBoxed: false) : CoreEditorUtils.DrawHeaderFoldout(text, beforeExpanded); if (colorDot != default) { Rect dotRect = GUILayoutUtility.GetLastRect(); dotRect.width = 5; dotRect.height = 5; dotRect.y += 7; dotRect.x += 17; EditorGUI.DrawRect(dotRect, colorDot); } if (expanded ^ beforeExpanded) { materialEditor.SetIsAreaExpanded((uint)bitExpanded, expanded); saveChangeState = true; } GUI.changed = saveChangeState; if (expanded) { ++EditorGUI.indentLevel; } }
void IDrawer.Draw(TData data, Editor owner) { bool expended = m_State[m_Mask]; bool newExpended; if (m_IsSubFoldout) { newExpended = CoreEditorUtils.DrawSubHeaderFoldout(m_Title, expended, m_IsBoxed); } else { CoreEditorUtils.DrawSplitter(m_IsBoxed); newExpended = CoreEditorUtils.DrawHeaderFoldout(m_Title, expended, m_IsBoxed, m_Enabler == null ? (Func <bool>)null : () => m_Enabler(data, owner), m_SwitchEnabler == null ? (Action)null : () => m_SwitchEnabler(data, owner), m_HelpUrl); } if (newExpended ^ expended) { m_State[m_Mask] = newExpended; } if (!newExpended) { return; } if (m_IsIndented) { ++EditorGUI.indentLevel; } for (var i = 0; i < m_ActionDrawers.Length; i++) { m_ActionDrawers[i](data, owner); } if (m_IsIndented) { --EditorGUI.indentLevel; } if (!m_NoSpaceAtEnd) { EditorGUILayout.Space(); } }
public void OnGUI() { if (asset == null) { return; } if (asset.isDirty) { RefreshEditors(); asset.isDirty = false; } bool isEditable = !VersionControl.Provider.isActive || AssetDatabase.IsOpenForEdit(asset, StatusQueryOptions.UseCachedIfPossible); using (new EditorGUI.DisabledScope(!isEditable)) { // Component list for (int i = 0; i < m_Editors.Count; i++) { var editor = m_Editors[i]; string title = editor.GetDisplayTitle(); int id = i; // Needed for closure capture below CoreEditorUtils.DrawSplitter(); bool displayContent = CoreEditorUtils.DrawHeaderToggle( title, editor.baseProperty, editor.activeProperty, pos => OnContextClick(pos, editor.target, id) ); if (displayContent) { using (new EditorGUI.DisabledScope(!editor.activeProperty.boolValue)) editor.OnInternalInspectorGUI(); } } if (m_Editors.Count > 0) { CoreEditorUtils.DrawSplitter(); } else { EditorGUILayout.HelpBox("This Volume Profile contains no overrides.", MessageType.Info); } EditorGUILayout.Space(); using (var hscope = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(EditorGUIUtility.TrTextContent("Add Override"), EditorStyles.miniButton)) { var r = hscope.rect; var pos = new Vector2(r.x + r.width / 2f, r.yMax + 18f); FilterWindow.Show(pos, new VolumeComponentProvider(asset, this)); } } } }
/// <summary> /// Draws the editor. /// </summary> public void OnGUI() { if (asset == null) { return; } // Even if the asset is not dirty, the list of component may have been changed by another inspector. // In this case, only the hash will tell us that we need to refresh. if (asset.isDirty || asset.GetComponentListHashCode() != m_CurrentHashCode) { RefreshEditors(); m_CurrentHashCode = asset.GetComponentListHashCode(); asset.isDirty = false; } bool isEditable = !VersionControl.Provider.isActive || AssetDatabase.IsOpenForEdit(asset, StatusQueryOptions.UseCachedIfPossible); using (new EditorGUI.DisabledScope(!isEditable)) { // Component list for (int i = 0; i < m_Editors.Count; i++) { var editor = m_Editors[i]; var title = editor.GetDisplayTitle(); int id = i; // Needed for closure capture below m_EditorDocumentationURLs.TryGetValue(editor.target.GetType(), out var documentationURL); CoreEditorUtils.DrawSplitter(); bool displayContent = CoreEditorUtils.DrawHeaderToggle( title, editor.baseProperty, editor.activeProperty, pos => OnContextClick(pos, editor, id), editor.hasAdditionalProperties ? () => editor.showAdditionalProperties : (Func <bool>)null, () => editor.showAdditionalProperties ^= true, documentationURL ); if (displayContent) { using (new EditorGUI.DisabledScope(!editor.activeProperty.boolValue)) editor.OnInternalInspectorGUI(); } } if (m_Editors.Count > 0) { CoreEditorUtils.DrawSplitter(); } else { EditorGUILayout.HelpBox("This Volume Profile contains no overrides.", MessageType.Info); } EditorGUILayout.Space(); using (var hscope = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(EditorGUIUtility.TrTextContent("Add Override"), EditorStyles.miniButton)) { var r = hscope.rect; var pos = new Vector2(r.x + r.width / 2f, r.yMax + 18f); FilterWindow.Show(pos, new VolumeComponentProvider(asset, this)); } } } }