Tanoda
LeapGraphicRendererEditorApi.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using System;
10using System.Collections.Generic;
11using UnityEngine;
12using UnityEngine.Assertions;
13#if UNITY_EDITOR
14using UnityEditor;
15#endif
16using Leap.Unity.Space;
17
19
20 public partial class LeapGraphicRenderer : MonoBehaviour {
21
22 //Need to keep this outside of the #if guards or else Unity will throw a fit
23 //about the serialized format changing between editor and build
24 [SerializeField]
25#pragma warning disable 0414
26 private int _selectedGroup = 0;
27#pragma warning restore 0414
28
29#if UNITY_EDITOR
30 public readonly EditorApi editor;
31
32 [ContextMenu("Show all hidden objects (INTERNAL)")]
33 private void showAllHiddenObjects() {
34 foreach (var obj in FindObjectsOfType<UnityEngine.Object>()) {
35 obj.hideFlags = HideFlags.None;
36 }
37 }
38
39 public class EditorApi {
40 private LeapGraphicRenderer _renderer;
41
42 [NonSerialized]
43 private Hash _previousHierarchyHash;
44
45 public EditorApi(LeapGraphicRenderer renderer) {
46 _renderer = renderer;
47 InternalUtility.OnAnySave += onAnySave;
48 }
49
50 public void OnValidate() {
51 Assert.IsFalse(InternalUtility.IsPrefab(_renderer), "Should never run editor validation on a prefab");
52
53 for (int i = _renderer._groups.Count; i-- > 0;) {
54 if (_renderer._groups[i] == null) {
55 _renderer._groups.RemoveAt(i);
56 }
57 }
58
59 _renderer.validateSpaceComponent();
60
61 foreach (var group in _renderer._groups) {
62 group.editor.OnValidate();
63 }
64 }
65
66 public void OnDestroy() {
67 InternalUtility.OnAnySave -= onAnySave;
68
69 foreach (var group in _renderer._groups) {
70 group.editor.OnDestroy();
71 }
72 }
73
79 public void CreateGroup(Type rendererType) {
80 AssertHelper.AssertEditorOnly();
81 Assert.IsNotNull(rendererType);
82
83 var group = new LeapGraphicGroup(_renderer, rendererType);
84
85 _renderer._selectedGroup = _renderer._groups.Count;
86 _renderer._groups.Add(group);
87 }
88
93 public void DestroySelectedGroup() {
94 AssertHelper.AssertEditorOnly();
95
96 var toDestroy = _renderer._groups[_renderer._selectedGroup];
97 _renderer._groups.RemoveAt(_renderer._selectedGroup);
98
99 toDestroy.editor.OnDestroy();
100
101 if (_renderer._selectedGroup >= _renderer._groups.Count && _renderer._selectedGroup != 0) {
102 _renderer._selectedGroup--;
103 }
104 }
105
111 public LeapRenderingMethod GetSelectedRenderingMethod() {
112 return _renderer._groups[_renderer._selectedGroup].renderingMethod;
113 }
114
123 public void ScheduleRebuild() {
124 AssertHelper.AssertEditorOnly();
125
126 //Dirty the hash by changing it to something else
127 _previousHierarchyHash++;
128 }
129
135 public void RebuildEditorPickingMeshes() {
136 //No picking meshes for prefabs
137 if (InternalUtility.IsPrefab(_renderer)) {
138 return;
139 }
140
141 if (!Application.isPlaying) {
142 if (_renderer._space != null) {
143 _renderer._space.RebuildHierarchy();
144 _renderer._space.RecalculateTransformers();
145 }
146
147 validateGraphics();
148
149 foreach (var group in _renderer._groups) {
150 group.editor.ValidateGraphicList();
151 group.RebuildFeatureData();
152 group.RebuildFeatureSupportInfo();
153 group.editor.RebuildEditorPickingMeshes();
154 }
155 }
156
157 foreach (var group in _renderer._groups) {
158 group.editor.RebuildEditorPickingMeshes();
159 }
160 }
161
166 public void ChangeRenderingMethodOfSelectedGroup(Type renderingMethod, bool addFeatures) {
167 _renderer._groups[_renderer._selectedGroup].editor.ChangeRenderingMethod(renderingMethod, addFeatures);
168 }
169
174 public void AddFeatureToSelectedGroup(Type featureType) {
175 _renderer._groups[_renderer._selectedGroup].editor.AddFeature(featureType);
176 }
177
182 public void RemoveFeatureFromSelectedGroup(int featureIndex) {
183 _renderer._groups[_renderer._selectedGroup].editor.RemoveFeature(featureIndex);
184 }
185
186 public void DoLateUpdateEditor() {
187 Undo.RecordObject(_renderer, "Update graphic renderer.");
188 Assert.IsFalse(InternalUtility.IsPrefab(_renderer), "Should never do editor updates for prefabs");
189
190 _renderer.validateSpaceComponent();
191
192 bool needsRebuild = false;
193
194 using (new ProfilerSample("Calculate Should Rebuild")) {
195 foreach (var group in _renderer._groups) {
196#if UNITY_EDITOR
197 if (!Application.isPlaying) {
198 group.editor.ValidateGraphicList();
199 }
200#endif
201
202 foreach (var graphic in group.graphics) {
203 if (graphic.isRepresentationDirty) {
204 needsRebuild = true;
205 break;
206 }
207 }
208
209 foreach (var feature in group.features) {
210 if (feature.isDirty) {
211 needsRebuild = true;
212 break;
213 }
214 }
215 }
216
217 Hash hierarchyHash = Hash.GetHierarchyHash(_renderer.transform);
218
219 if (_renderer._space != null) {
220 hierarchyHash.Add(_renderer._space.GetSettingHash());
221 }
222
223 if (_previousHierarchyHash != hierarchyHash) {
224 _previousHierarchyHash = hierarchyHash;
225 needsRebuild = true;
226 }
227 }
228
229 DoEditorUpdateLogic(needsRebuild);
230 }
231
232 public void DoEditorUpdateLogic(bool fullRebuild) {
233 Undo.RecordObject(_renderer, "Do Editor Update Logic");
234
235 Assert.IsFalse(InternalUtility.IsPrefab(_renderer), "Should never do editor updates for prefabs");
236
237 using (new ProfilerSample("Validate Space Component")) {
238 _renderer.validateSpaceComponent();
239 }
240
241 if (fullRebuild) {
242 if (_renderer._space != null) {
243 using (new ProfilerSample("Rebuild Space")) {
244 _renderer._space.RebuildHierarchy();
245 _renderer._space.RecalculateTransformers();
246 }
247 }
248
249 using (new ProfilerSample("Validate graphics")) {
250 validateGraphics();
251 }
252
253 foreach (var group in _renderer._groups) {
254 using (new ProfilerSample("Validate Graphic List")) {
255 group.editor.ValidateGraphicList();
256 }
257
258 using (new ProfilerSample("Rebuild Feature Data")) {
259 group.RebuildFeatureData();
260 }
261
262 using (new ProfilerSample("Rebuild Feature Support Info")) {
263 group.RebuildFeatureSupportInfo();
264 }
265
266 using (new ProfilerSample("Update Renderer Editor")) {
267 group.editor.UpdateRendererEditor();
268 }
269 }
270 }
271
272 using (new ProfilerSample("Update Renderer")) {
273 foreach (var group in _renderer._groups) {
274 group.UpdateRenderer();
275 }
276 }
277
278 Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
279 }
280
281 private void onAnySave() {
282 if (_renderer == null || InternalUtility.IsPrefab(_renderer)) {
283 InternalUtility.OnAnySave -= onAnySave;
284 return;
285 }
286
287 DoEditorUpdateLogic(fullRebuild: true);
288 }
289
290 [NonSerialized]
291 private List<LeapGraphic> _tempGraphicList = new List<LeapGraphic>();
292 private void validateGraphics() {
293 Assert.IsFalse(InternalUtility.IsPrefab(_renderer), "Should never validate graphics for prefabs");
294
295 _renderer.GetComponentsInChildren(includeInactive: true, result: _tempGraphicList);
296
297 HashSet<LeapGraphic> graphicsInGroup = Pool<HashSet<LeapGraphic>>.Spawn();
298 try {
299 foreach (var group in _renderer._groups) {
300
301 for (int i = group.graphics.Count; i-- != 0;) {
302 if (group.graphics[i] == null) {
303 group.graphics.RemoveAt(i);
304 } else {
305 graphicsInGroup.Add(group.graphics[i]);
306 }
307 }
308
309 foreach (var graphic in _tempGraphicList) {
310 if (graphic.isAttachedToGroup) {
311 //If the graphic claims it is attached to this group, but it really isn't, remove
312 //it and re-add it.
313 bool graphicThinksItsInGroup = graphic.attachedGroup == group;
314 bool isActuallyInGroup = graphicsInGroup.Contains(graphic);
315
316 //Also re add it if it is attached to a completely different renderer!
317 if (graphicThinksItsInGroup != isActuallyInGroup ||
318 graphic.attachedGroup.renderer != _renderer) {
319 if (!group.TryRemoveGraphic(graphic)) {
320 //If we fail, detach using force!!
321 graphic.OnDetachedFromGroup();
322 }
323
324 group.TryAddGraphic(graphic);
325 }
326 }
327 }
328
329 graphicsInGroup.Clear();
330 }
331 } finally {
332 graphicsInGroup.Clear();
333 Pool<HashSet<LeapGraphic>>.Recycle(graphicsInGroup);
334 }
335
336 foreach (var graphic in _tempGraphicList) {
337 if (graphic.isAttachedToGroup) {
338 //procede to validate
339
340 //If the graphic is anchored to the wrong anchor, detach and reattach
341 var anchor = _renderer._space == null ? null : LeapSpaceAnchor.GetAnchor(graphic.transform);
342 if (graphic.anchor != anchor) {
343 var group = graphic.attachedGroup;
344
345 if (group.TryRemoveGraphic(graphic)) {
346 group.TryAddGraphic(graphic);
347 }
348 }
349 }
350 }
351 }
352 }
353#endif
354 }
355}
bool TryAddGraphic(LeapGraphic graphic)
Tries to add the given graphic to any group attached to this graphic. First, it will try to be attach...
static LeapSpaceAnchor GetAnchor(Transform root)
abstract Hash GetSettingHash()
Get a hash of all features in this space. This is useful if you want to know if anything has changed ...
void RecalculateTransformers()
Call to update all transformers in the space. Call this whenever any anchor or parent of an anchor ch...
Definition: LeapSpace.cs:85
void RebuildHierarchy()
Call to traverse the entire hierarchy and rebuild the relationship between anchors....
Definition: LeapSpace.cs:71
static Hash GetHierarchyHash(Transform root)
Definition: Hash.cs:44
A utility struct for ease of use when you want to wrap a piece of code in a Profiler....