UnityGame/Library/PackageCache/com.unity.render-pipelines.core/Editor/HeaderFoldout.cs
2024-10-27 10:53:47 +03:00

144 lines
5.6 KiB
C#

using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace UnityEditor.Rendering
{
/// <summary> UITK component to display header styled foldout</summary>
[UxmlElement]
public partial class HeaderFoldout : Foldout
{
const string k_StylesheetPathFormat = "Packages/com.unity.render-pipelines.core/Editor/StyleSheets/HeaderFoldout{0}.uss";
const string k_Class = "header-foldout";
const string k_IconName = "header-foldout__icon";
private string m_DocumentationURL;
private Texture2D m_Icon;
private Func<GenericMenu> m_ContextMenuGenerator;
private VisualElement m_HelpButton;
private VisualElement m_ContextMenuButton;
private VisualElement m_IconElement;
/// <summary>URL to use on documentation icon. If null, button don't show.</summary>
public string documentationURL
{
get => m_DocumentationURL;
set
{
if (m_DocumentationURL == value)
return;
m_DocumentationURL = value;
m_HelpButton?.SetEnabled(!string.IsNullOrEmpty(m_DocumentationURL));
}
}
/// <summary>Context menu to show on click of the context button. If null, button don't show.</summary>
public Func<GenericMenu> contextMenuGenerator //Use ImGUI for now
{
get => m_ContextMenuGenerator;
set
{
if (m_ContextMenuGenerator == value)
return;
m_ContextMenuGenerator = value;
m_ContextMenuButton?.SetEnabled(m_ContextMenuGenerator != null);
}
}
/// <summary>Optional icon image. If not set, no icon is shown.</summary>
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;
}
}
/// <summary>Constructor</summary>
public HeaderFoldout() : base()
{
styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(string.Format(k_StylesheetPathFormat, "")));
styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(string.Format(k_StylesheetPathFormat, EditorGUIUtility.isProSkin ? "Dark" : "Light")));
AddToClassList(k_Class);
RegisterCallback<AttachToPanelEvent>(DelayedInit);
var line = hierarchy[0][0]; //pass by herarchy to ignore content redirection
m_HelpButton = new Button(Background.FromTexture2D(CoreEditorStyles.iconHelp), () => Help.BrowseURL(m_DocumentationURL));
m_HelpButton.SetEnabled(!string.IsNullOrEmpty(m_DocumentationURL));
line.Add(m_HelpButton);
m_ContextMenuButton = new Button(Background.FromTexture2D(CoreEditorStyles.paneOptionsIcon), () => ShowMenu());
m_ContextMenuButton.SetEnabled(m_ContextMenuGenerator != null);
line.Add(m_ContextMenuButton);
m_IconElement = new Image();
m_IconElement.name = k_IconName;
m_IconElement.style.display = DisplayStyle.None; // Disable by default, will be enabled if icon is set
// Delay insertion of icon to happen after foldout is constructed so we can put it in the right place
RegisterCallbackOnce<AttachToPanelEvent>(evt => line.Insert(1, m_IconElement));
}
void DelayedInit(AttachToPanelEvent evt)
{
//Only show top line if previous item is not a HeaderFoldout to avoid bolder border
bool shouldShowTopLine = true;
var parent = hierarchy.parent;
int posInParent = parent.hierarchy.IndexOf(this);
if (posInParent > 0 && parent[posInParent - 1].ClassListContains(k_Class))
shouldShowTopLine = false;
style.borderTopWidth = shouldShowTopLine ? 1 : 0;
}
void ShowMenu()
{
var menu = m_ContextMenuGenerator.Invoke();
menu.DropDown(new Rect(m_ContextMenuButton.worldBound.position + m_ContextMenuButton.worldBound.size.y * Vector2.up, Vector2.zero));
}
}
/// <summary> UITK component to display header styled foldout. This variant have an enable checkbox.</summary>
public class HeaderToggleFoldout : HeaderFoldout
{
private Toggle m_Toggle;
/// <summary>Property to get the enablement state</summary>
public bool enabled
{
get => m_Toggle.value;
set => m_Toggle.value = value;
}
/// <summary>Quick access to the enable toggle if one need to register events</summary>
public Toggle enableToggle => m_Toggle;
/// <summary>Constructor</summary>
public HeaderToggleFoldout() : base()
{
var line = hierarchy[0][0]; //pass by herarchy to ignore content redirection
m_Toggle = new Toggle()
{
value = true,
name = "enable-checkbox",
};
//Need to delay insertion as foldout will be constructed after and we need to squeeze rigth after
RegisterCallbackOnce<AttachToPanelEvent>(evt => line.Insert(1, m_Toggle));
m_Toggle.RegisterValueChangedCallback(HandleDisabling);
}
void HandleDisabling(ChangeEvent<bool> evt)
=> contentContainer.SetEnabled(evt.newValue);
}
}