using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.Rendering
{
/// UITK component to display header styled foldout
[UxmlElement]
public partial class HeaderFoldout : Foldout
{
const string k_StylesheetPathFormat = "Packages/com.unity.render-pipelines.core/Editor/StyleSheets/HeaderFoldout{0}.uss";
const string k_MainClass = "header-foldout";
const string k_EnableClass = k_MainClass + "__enable";
const string k_IconClass = k_MainClass + "__icon";
const string k_LabelClass = k_MainClass + "__label";
const string k_HelpButtonClass = k_MainClass + "__help-button";
const string k_ContextButtonClass = k_MainClass + "__context-button";
private string m_DocumentationURL;
private Texture2D m_Icon;
private Func m_ContextMenuGenerator;
private VisualElement m_HelpButton;
private VisualElement m_ContextMenuButton;
private VisualElement m_IconElement;
private Toggle m_Toggle;
private Label m_Text;
/// URL to use on documentation icon. If null, button don't show.
public string documentationURL
{
get => m_DocumentationURL;
set
{
if (m_DocumentationURL == value)
return;
m_DocumentationURL = value;
m_HelpButton?.SetEnabled(!string.IsNullOrEmpty(m_DocumentationURL));
}
}
/// Context menu to show on click of the context button. If null, button don't show.
public Func contextMenuGenerator //Use ImGUI for now
{
get => m_ContextMenuGenerator;
set
{
if (m_ContextMenuGenerator == value)
return;
m_ContextMenuGenerator = value;
m_ContextMenuButton?.SetEnabled(m_ContextMenuGenerator != null);
}
}
/// Optional icon image. If not set, no icon is shown.
public Texture2D icon
{
get => m_Icon;
set
{
if (m_Icon == value)
return;
m_Icon = value;
m_IconElement.style.backgroundImage = Background.FromTexture2D(m_Icon);
m_IconElement.style.display = m_Icon != null ? DisplayStyle.Flex : DisplayStyle.None;
}
}
/// Property to get the enablement state
public bool enabled
{
get => m_Toggle.value;
set => m_Toggle.value = value;
}
/// Property to get the enablement visibility state
public bool showEnableCheckbox
{
get => m_Toggle.style.display == DisplayStyle.Flex;
set => m_Toggle.style.display = value ? DisplayStyle.Flex : DisplayStyle.None;
}
/// Quick access to the enable toggle if one need to register events
public Toggle enableToggle => m_Toggle;
/// Property to get the title
public new string text
{
get => m_Text.text;
set => m_Text.text = value;
}
/// Constructor
public HeaderFoldout() : base()
{
styleSheets.Add(AssetDatabase.LoadAssetAtPath(string.Format(k_StylesheetPathFormat, "")));
styleSheets.Add(AssetDatabase.LoadAssetAtPath(string.Format(k_StylesheetPathFormat, EditorGUIUtility.isProSkin ? "Dark" : "Light")));
AddToClassList(k_MainClass);
RegisterCallback(DelayedInit);
var line = hierarchy[0][0]; //pass by herarchy to ignore content redirection
m_IconElement = new Image()
{
style =
{
display = DisplayStyle.None // hidden by default, will be enabled if icon is set
}
};
m_IconElement.AddToClassList(k_IconClass);
line.Add(m_IconElement);
m_Toggle = new Toggle()
{
value = true
};
m_Toggle.AddToClassList(k_EnableClass);
m_Toggle.RegisterValueChangedCallback(HandleDisabling);
m_Toggle.style.display = DisplayStyle.None; // hidden by default
line.Add(m_Toggle);
m_Text = new Label();
m_Text.AddToClassList(k_LabelClass);
line.Add(m_Text);
m_HelpButton = new Button(Background.FromTexture2D(CoreEditorStyles.iconHelp), () => Help.BrowseURL(m_DocumentationURL));
m_HelpButton.AddToClassList(k_HelpButtonClass);
m_HelpButton.SetEnabled(!string.IsNullOrEmpty(m_DocumentationURL));
line.Add(m_HelpButton);
m_ContextMenuButton = new Button(Background.FromTexture2D(CoreEditorStyles.paneOptionsIcon), () => ShowMenu());
m_ContextMenuButton.AddToClassList(k_ContextButtonClass);
m_ContextMenuButton.SetEnabled(m_ContextMenuGenerator != null);
line.Add(m_ContextMenuButton);
}
void DelayedInit(AttachToPanelEvent evt)
{
//Only show top line if previous item is not a HeaderFoldout to avoid bolder border
var parent = hierarchy.parent;
int posInParent = parent.hierarchy.IndexOf(this);
if (posInParent == 0 || !parent[posInParent - 1].ClassListContains(k_MainClass))
AddToClassList("first-in-collection");
//fix to transfer label assigned in UXML from base label to new label
if (!string.IsNullOrEmpty(base.text))
{
if (string.IsNullOrEmpty(m_Text.text))
m_Text.text = base.text;
base.text = null;
}
}
void ShowMenu()
{
var menu = m_ContextMenuGenerator.Invoke();
menu.DropDown(new Rect(m_ContextMenuButton.worldBound.position + m_ContextMenuButton.worldBound.size.y * Vector2.up, Vector2.zero));
}
void HandleDisabling(ChangeEvent evt)
=> contentContainer.SetEnabled(evt.newValue);
}
/// UITK component to display header styled foldout. This variant have an enable checkbox.
[Obsolete("Please directly use HeaderFoldout now #from(6000.2) (UnityUpgradable) -> HeaderFoldout", false)]
public class HeaderToggleFoldout : HeaderFoldout
{
/// Constructor
public HeaderToggleFoldout() : base()
=> showEnableCheckbox = true;
}
}