Cesium for Unity 1.23.0
Loading...
Searching...
No Matches
CesiumCreditSystemUI.cs
Go to the documentation of this file.
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using UnityEngine;
5using UnityEngine.EventSystems;
6using UnityEngine.UIElements;
7
8#if ENABLE_INPUT_SYSTEM
9using UnityEngine.InputSystem.UI;
10#endif
11
12#if UNITY_EDITOR
13using UnityEditor;
14#endif
15
16namespace CesiumForUnity
17{
21 [ExecuteInEditMode]
22 [RequireComponent(typeof(UIDocument))]
23 [AddComponentMenu("Cesium/Cesium Credit System UI")]
24 [IconAttribute("Packages/com.cesium.unity/Editor/Resources/Cesium-24x24.png")]
25 internal class CesiumCreditSystemUI : MonoBehaviour
26 {
27 private CesiumCreditSystem _creditSystem;
28
29 private UIDocument _uiDocument;
30
31 private VisualElement _onScreenCredits;
32 private VisualElement _popupCredits;
33
34 // The delimiter refers to the string used to separate credit entries
35 // when they are presented on-screen.
36 private string _delimiter = "\u2022";
37
38 private void OnEnable()
39 {
40 this._creditSystem = this.GetComponent<CesiumCreditSystem>();
41
42 if (this._creditSystem == null)
43 {
44 this._creditSystem = CesiumCreditSystem.GetDefaultCreditSystem();
45 }
46
47 this._creditSystem.OnCreditsUpdate += this.SetCredits;
48
49 this._uiDocument = this.GetComponent<UIDocument>();
50
51 if (this._uiDocument.rootVisualElement != null)
52 {
53 this._onScreenCredits = this._uiDocument.rootVisualElement.Q("OnScreenCredits");
54 this._popupCredits = this._uiDocument.rootVisualElement.Q("PopupCredits");
55 }
56
57#if UNITY_EDITOR
58 if (!EditorApplication.isPlaying)
59 {
60 return;
61 }
62#endif
63
64 // If no EventSystem exists, create one to handle clicking on credit links.
65 if (EventSystem.current == null)
66 {
67 GameObject eventSystemGameObject = new GameObject("EventSystem");
68 eventSystemGameObject.AddComponent<EventSystem>();
69
70#if ENABLE_INPUT_SYSTEM
71 eventSystemGameObject.AddComponent<InputSystemUIInputModule>();
72#elif ENABLE_LEGACY_INPUT_MANAGER
73 eventSystemGameObject.AddComponent<StandaloneInputModule>();
74#endif
75 }
76 }
77
78#if UNITY_EDITOR
79 private void AddCreditsToSceneView(SceneView sceneView)
80 {
81 if (sceneView.rootVisualElement == null)
82 {
83 return;
84 }
85
86 if (sceneView.rootVisualElement.Q("OnScreenCredits") == null)
87 {
88 VisualTreeAsset visualTreeAsset = this._uiDocument.visualTreeAsset;
89 TemplateContainer tree = visualTreeAsset.Instantiate();
90
91 // If we add the tree directly and scale the height to fit the whole screen,
92 // it will block any non-UI mouse inputs, preventing the user from looking
93 // around the scene or selecting objects. Add the individual elements instead.
94 VisualElement onScreenCredits = tree.Q("OnScreenCredits");
95 VisualElement popupCredits = tree.Q("PopupCredits");
96 sceneView.rootVisualElement.Add(onScreenCredits);
97 sceneView.rootVisualElement.Add(popupCredits);
98
99 this.UpdateCreditsInSceneView(
100 sceneView,
101 this._creditSystem.onScreenCredits,
102 this._creditSystem.popupCredits);
103 }
104 }
105
106 private void UpdateCreditsInSceneView(
107 SceneView sceneView,
108 List<CesiumCredit> onScreenCredits,
109 List<CesiumCredit> popupCredits)
110 {
111 if (sceneView.rootVisualElement == null)
112 {
113 return;
114 }
115
116 VisualElement onScreenElement = sceneView.rootVisualElement.Q("OnScreenCredits");
117 VisualElement popupElement = sceneView.rootVisualElement.Q("PopupCredits");
118
119 if (onScreenElement != null && popupElement != null)
120 {
121 this.SetCreditsOnVisualElements(
122 onScreenElement,
123 onScreenCredits,
124 popupElement,
125 popupCredits,
126 false);
127 }
128 }
129
130 private void RemoveCreditsFromSceneView(SceneView sceneView)
131 {
132 if (sceneView.rootVisualElement != null)
133 {
134 VisualElement onScreenElement = sceneView.rootVisualElement.Q("OnScreenCredits");
135 if (onScreenElement != null)
136 {
137 VisualElement parent = onScreenElement.parent;
138 parent.Remove(onScreenElement);
139 }
140
141 VisualElement popupElement = sceneView.rootVisualElement.Q("PopupCredits");
142 if (popupElement != null)
143 {
144 VisualElement parent = popupElement.parent;
145 parent.Remove(popupElement);
146 }
147 }
148 }
149
150#endif
151
152 private void Update()
153 {
154 if (this._creditSystem == null)
155 {
156 return;
157 }
158
159#if UNITY_EDITOR
160 ArrayList sceneViews = SceneView.sceneViews;
161 for (int i = 0; i < sceneViews.Count; i++)
162 {
163 this.AddCreditsToSceneView((SceneView)sceneViews[i]);
164 }
165#endif
166 }
167
175 private Label CreateLabelFromText(string text, bool removeExtraSpace)
176 {
177 Label label = new Label();
178 label.text = text;
179 label.style.whiteSpace = WhiteSpace.Normal;
180
181 if (removeExtraSpace)
182 {
183 label.style.marginLeft = new StyleLength(0.0f);
184 label.style.paddingLeft = new StyleLength(0.0f);
185 label.style.paddingRight = new StyleLength(0.0f);
186 }
187
188 return label;
189 }
190
198 private List<VisualElement> ConvertCreditToVisualElements(CesiumCredit credit, bool removeExtraSpace)
199 {
200 List<VisualElement> visualElements = new List<VisualElement>();
201
202 for (int i = 0, componentCount = credit.components.Count; i < componentCount; i++)
203 {
204 CesiumCreditComponent creditComponent = credit.components[i];
205 VisualElement element;
206
207 bool hasLink = !string.IsNullOrEmpty(creditComponent.link);
208
209 if (creditComponent.imageId >= 0)
210 {
211 Texture2D image = null;
212 if (creditComponent.imageId < this._creditSystem.images.Count)
213 {
214 image = this._creditSystem.images[creditComponent.imageId];
215 }
216
217 if (image == null)
218 {
219 continue;
220 }
221
222 element = new VisualElement();
223 element.style.backgroundImage = new StyleBackground(image);
224 element.style.width = new StyleLength(image.width);
225 element.style.height = new StyleLength(image.height);
226 }
227 else
228 {
229 string text = creditComponent.text;
230
231 if (hasLink)
232 {
233 text = string.Format("<u>{0}</u>", text);
234 }
235
236 element = this.CreateLabelFromText(text, removeExtraSpace);
237 }
238
239 if (hasLink)
240 {
241 element.AddManipulator(new Clickable(evt => Application.OpenURL(creditComponent.link)));
242 }
243 else
244 {
245 element.pickingMode = PickingMode.Ignore;
246 }
247
248 visualElements.Add(element);
249 }
250
251 return visualElements;
252 }
253
260 private VisualElement CreateDataAttributionElement(VisualElement popupElement)
261 {
262 Label label = new Label();
263 label.text = "<u>Data Attribution</u>";
264 label.AddManipulator(new Clickable(evt =>
265 {
266 if (popupElement.style.display == DisplayStyle.Flex)
267 {
268 popupElement.style.display = DisplayStyle.None;
269 }
270 else
271 {
272 popupElement.style.display = DisplayStyle.Flex;
273 }
274 }));
275
276 return label;
277 }
278
288 private VisualElement CreatePopupCreditElement(bool removeExtraSpace)
289 {
290 VisualElement popupCreditElement = new VisualElement();
291 popupCreditElement.style.flexDirection = FlexDirection.Row;
292 popupCreditElement.style.flexWrap = Wrap.Wrap;
293 popupCreditElement.style.alignItems = Align.Center;
294
295 if (!removeExtraSpace)
296 {
297 popupCreditElement.style.marginTop = new StyleLength(2.5f);
298 }
299 else
300 {
301 popupCreditElement.style.marginTop = new StyleLength(0.0f);
302 popupCreditElement.style.marginBottom = new StyleLength(0.0f);
303 popupCreditElement.style.paddingTop = new StyleLength(0.0f);
304 popupCreditElement.style.paddingBottom = new StyleLength(0.0f);
305 }
306
307 return popupCreditElement;
308 }
309
310 private void SetCredits(List<CesiumCredit> onScreenCredits, List<CesiumCredit> popupCredits)
311 {
312 if (this._onScreenCredits != null && this._popupCredits != null)
313 {
314 this.SetCreditsOnVisualElements(
315 this._onScreenCredits,
316 onScreenCredits,
317 this._popupCredits,
318 popupCredits,
319 true);
320 }
321
322#if UNITY_EDITOR
323 ArrayList sceneViews = SceneView.sceneViews;
324 for (int i = 0; i < sceneViews.Count; i++)
325 {
326 this.UpdateCreditsInSceneView((SceneView)sceneViews[i], onScreenCredits, popupCredits);
327 }
328#endif
329 }
330
342 private void SetCreditsOnVisualElements(
343 VisualElement onScreenElement,
344 List<CesiumCredit> onScreenCredits,
345 VisualElement popupElement,
346 List<CesiumCredit> popupCredits,
347 bool removeExtraSpace)
348 {
349 onScreenElement.Clear();
350 popupElement.Clear();
351
352 for (int i = 0, creditCount = onScreenCredits.Count; i < creditCount; i++)
353 {
354 CesiumCredit credit = onScreenCredits[i];
355 List<VisualElement> visualElements = this.ConvertCreditToVisualElements(credit, removeExtraSpace);
356
357 if (i > 0)
358 {
359 onScreenElement.Add(this.CreateLabelFromText(this._delimiter, false));
360 }
361
362 for (int j = 0, elementCount = visualElements.Count; j < elementCount; j++)
363 {
364 onScreenElement.Add(visualElements[j]);
365 }
366 }
367
368 for (int i = 0, creditCount = popupCredits.Count; i < creditCount; i++)
369 {
370 CesiumCredit credit = popupCredits[i];
371 List<VisualElement> visualElements = this.ConvertCreditToVisualElements(credit, removeExtraSpace);
372
373 // Put the inline credit components in one container so they can be vertically stacked by the popup.
374 VisualElement popupCreditElement = CreatePopupCreditElement(removeExtraSpace);
375
376 for (int j = 0, elementCount = visualElements.Count; j < elementCount; j++)
377 {
378 popupCreditElement.Add(visualElements[j]);
379 }
380
381 popupElement.Add(popupCreditElement);
382 }
383
384 if (popupCredits.Count > 0)
385 {
386 if (onScreenCredits.Count > 0)
387 {
388 onScreenElement.Add(this.CreateLabelFromText(this._delimiter, false));
389 }
390
391 onScreenElement.Add(this.CreateDataAttributionElement(popupElement));
392 }
393 }
394
395 private void OnDisable()
396 {
397#if UNITY_EDITOR
398 ArrayList sceneViews = SceneView.sceneViews;
399 for (int i = 0; i < sceneViews.Count; i++)
400 {
401 this.RemoveCreditsFromSceneView((SceneView)sceneViews[i]);
402 }
403#endif
404 }
405 }
406}