Cesium for Unity 1.15.2
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
244 visualElements.Add(element);
245 }
246
247 return visualElements;
248 }
249
256 private VisualElement CreateDataAttributionElement(VisualElement popupElement)
257 {
258 Label label = new Label();
259 label.text = "<u>Data Attribution</u>";
260 label.AddManipulator(new Clickable(evt =>
261 {
262 if (popupElement.style.display == DisplayStyle.Flex)
263 {
264 popupElement.style.display = DisplayStyle.None;
265 }
266 else
267 {
268 popupElement.style.display = DisplayStyle.Flex;
269 }
270 }));
271
272 return label;
273 }
274
284 private VisualElement CreatePopupCreditElement(bool removeExtraSpace)
285 {
286 VisualElement popupCreditElement = new VisualElement();
287 popupCreditElement.style.flexDirection = FlexDirection.Row;
288 popupCreditElement.style.flexWrap = Wrap.Wrap;
289 popupCreditElement.style.alignItems = Align.Center;
290
291 if (!removeExtraSpace)
292 {
293 popupCreditElement.style.marginTop = new StyleLength(2.5f);
294 }
295 else
296 {
297 popupCreditElement.style.marginTop = new StyleLength(0.0f);
298 popupCreditElement.style.marginBottom = new StyleLength(0.0f);
299 popupCreditElement.style.paddingTop = new StyleLength(0.0f);
300 popupCreditElement.style.paddingBottom = new StyleLength(0.0f);
301 }
302
303 return popupCreditElement;
304 }
305
306 private void SetCredits(List<CesiumCredit> onScreenCredits, List<CesiumCredit> popupCredits)
307 {
308 if (this._onScreenCredits != null && this._popupCredits != null)
309 {
310 this.SetCreditsOnVisualElements(
311 this._onScreenCredits,
312 onScreenCredits,
313 this._popupCredits,
314 popupCredits,
315 true);
316 }
317
318#if UNITY_EDITOR
319 ArrayList sceneViews = SceneView.sceneViews;
320 for (int i = 0; i < sceneViews.Count; i++)
321 {
322 this.UpdateCreditsInSceneView((SceneView)sceneViews[i], onScreenCredits, popupCredits);
323 }
324#endif
325 }
326
338 private void SetCreditsOnVisualElements(
339 VisualElement onScreenElement,
340 List<CesiumCredit> onScreenCredits,
341 VisualElement popupElement,
342 List<CesiumCredit> popupCredits,
343 bool removeExtraSpace)
344 {
345 onScreenElement.Clear();
346 popupElement.Clear();
347
348 for (int i = 0, creditCount = onScreenCredits.Count; i < creditCount; i++)
349 {
350 CesiumCredit credit = onScreenCredits[i];
351 List<VisualElement> visualElements = this.ConvertCreditToVisualElements(credit, removeExtraSpace);
352
353 if (i > 0)
354 {
355 onScreenElement.Add(this.CreateLabelFromText(this._delimiter, false));
356 }
357
358 for (int j = 0, elementCount = visualElements.Count; j < elementCount; j++)
359 {
360 onScreenElement.Add(visualElements[j]);
361 }
362 }
363
364 for (int i = 0, creditCount = popupCredits.Count; i < creditCount; i++)
365 {
366 CesiumCredit credit = popupCredits[i];
367 List<VisualElement> visualElements = this.ConvertCreditToVisualElements(credit, removeExtraSpace);
368
369 // Put the inline credit components in one container so they can be vertically stacked by the popup.
370 VisualElement popupCreditElement = CreatePopupCreditElement(removeExtraSpace);
371
372 for (int j = 0, elementCount = visualElements.Count; j < elementCount; j++)
373 {
374 popupCreditElement.Add(visualElements[j]);
375 }
376
377 popupElement.Add(popupCreditElement);
378 }
379
380 if (popupCredits.Count > 0)
381 {
382 if (onScreenCredits.Count > 0)
383 {
384 onScreenElement.Add(this.CreateLabelFromText(this._delimiter, false));
385 }
386
387 onScreenElement.Add(this.CreateDataAttributionElement(popupElement));
388 }
389 }
390
391 private void OnDisable()
392 {
393#if UNITY_EDITOR
394 ArrayList sceneViews = SceneView.sceneViews;
395 for (int i = 0; i < sceneViews.Count; i++)
396 {
397 this.RemoveCreditsFromSceneView((SceneView)sceneViews[i]);
398 }
399#endif
400 }
401 }
402}