A game about forced loneliness, made by TACStudios
1using System;
2using UnityEngine;
3using UnityEngine.UIElements;
4
5namespace UnityEditor.Rendering
6{
7 /// <summary> UITK component to display header styled foldout</summary>
8 [UxmlElement]
9 public partial class HeaderFoldout : Foldout
10 {
11 const string k_StylesheetPathFormat = "Packages/com.unity.render-pipelines.core/Editor/StyleSheets/HeaderFoldout{0}.uss";
12 const string k_Class = "header-foldout";
13 const string k_IconName = "header-foldout__icon";
14
15 private string m_DocumentationURL;
16 private Texture2D m_Icon;
17 private Func<GenericMenu> m_ContextMenuGenerator;
18 private VisualElement m_HelpButton;
19 private VisualElement m_ContextMenuButton;
20 private VisualElement m_IconElement;
21
22 /// <summary>URL to use on documentation icon. If null, button don't show.</summary>
23 public string documentationURL
24 {
25 get => m_DocumentationURL;
26 set
27 {
28 if (m_DocumentationURL == value)
29 return;
30
31 m_DocumentationURL = value;
32 m_HelpButton?.SetEnabled(!string.IsNullOrEmpty(m_DocumentationURL));
33 }
34 }
35
36 /// <summary>Context menu to show on click of the context button. If null, button don't show.</summary>
37 public Func<GenericMenu> contextMenuGenerator //Use ImGUI for now
38 {
39 get => m_ContextMenuGenerator;
40 set
41 {
42 if (m_ContextMenuGenerator == value)
43 return;
44
45 m_ContextMenuGenerator = value;
46 m_ContextMenuButton?.SetEnabled(m_ContextMenuGenerator != null);
47 }
48 }
49
50 /// <summary>Optional icon image. If not set, no icon is shown.</summary>
51 public Texture2D icon
52 {
53 get => m_Icon;
54 set
55 {
56 if (m_Icon == value)
57 return;
58
59 m_Icon = value;
60 m_IconElement.style.backgroundImage = Background.FromTexture2D(m_Icon);
61 m_IconElement.style.display = m_Icon != null ? DisplayStyle.Flex : DisplayStyle.None;
62 }
63 }
64
65 /// <summary>Constructor</summary>
66 public HeaderFoldout() : base()
67 {
68 styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(string.Format(k_StylesheetPathFormat, "")));
69 styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(string.Format(k_StylesheetPathFormat, EditorGUIUtility.isProSkin ? "Dark" : "Light")));
70 AddToClassList(k_Class);
71
72 RegisterCallback<AttachToPanelEvent>(DelayedInit);
73
74 var line = hierarchy[0][0]; //pass by herarchy to ignore content redirection
75
76 m_HelpButton = new Button(Background.FromTexture2D(CoreEditorStyles.iconHelp), () => Help.BrowseURL(m_DocumentationURL));
77 m_HelpButton.SetEnabled(!string.IsNullOrEmpty(m_DocumentationURL));
78 line.Add(m_HelpButton);
79
80 m_ContextMenuButton = new Button(Background.FromTexture2D(CoreEditorStyles.paneOptionsIcon), () => ShowMenu());
81 m_ContextMenuButton.SetEnabled(m_ContextMenuGenerator != null);
82 line.Add(m_ContextMenuButton);
83
84 m_IconElement = new Image();
85 m_IconElement.name = k_IconName;
86 m_IconElement.style.display = DisplayStyle.None; // Disable by default, will be enabled if icon is set
87 // Delay insertion of icon to happen after foldout is constructed so we can put it in the right place
88 RegisterCallbackOnce<AttachToPanelEvent>(evt => line.Insert(1, m_IconElement));
89 }
90
91 void DelayedInit(AttachToPanelEvent evt)
92 {
93 //Only show top line if previous item is not a HeaderFoldout to avoid bolder border
94 bool shouldShowTopLine = true;
95 var parent = hierarchy.parent;
96 int posInParent = parent.hierarchy.IndexOf(this);
97 if (posInParent > 0 && parent[posInParent - 1].ClassListContains(k_Class))
98 shouldShowTopLine = false;
99
100 style.borderTopWidth = shouldShowTopLine ? 1 : 0;
101 }
102
103 void ShowMenu()
104 {
105 var menu = m_ContextMenuGenerator.Invoke();
106 menu.DropDown(new Rect(m_ContextMenuButton.worldBound.position + m_ContextMenuButton.worldBound.size.y * Vector2.up, Vector2.zero));
107 }
108 }
109
110 /// <summary> UITK component to display header styled foldout. This variant have an enable checkbox.</summary>
111 public class HeaderToggleFoldout : HeaderFoldout
112 {
113 private Toggle m_Toggle;
114
115 /// <summary>Property to get the enablement state</summary>
116 public bool enabled
117 {
118 get => m_Toggle.value;
119 set => m_Toggle.value = value;
120 }
121
122 /// <summary>Quick access to the enable toggle if one need to register events</summary>
123 public Toggle enableToggle => m_Toggle;
124
125 /// <summary>Constructor</summary>
126 public HeaderToggleFoldout() : base()
127 {
128 var line = hierarchy[0][0]; //pass by herarchy to ignore content redirection
129 m_Toggle = new Toggle()
130 {
131 value = true,
132 name = "enable-checkbox",
133 };
134
135 //Need to delay insertion as foldout will be constructed after and we need to squeeze rigth after
136 RegisterCallbackOnce<AttachToPanelEvent>(evt => line.Insert(1, m_Toggle));
137
138 m_Toggle.RegisterValueChangedCallback(HandleDisabling);
139 }
140
141 void HandleDisabling(ChangeEvent<bool> evt)
142 => contentContainer.SetEnabled(evt.newValue);
143 }
144}