AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
AtlasReferenceUpdater.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 using System.Collections.Generic;
4 using System.Linq;
5 using UnityEditor;
6 using UnityEngine;
7 using UnityEngine.UI;
8 
9 namespace HoloToolkit.Unity
10 {
11  [InitializeOnLoad]
12  public class AtlasReferenceUpdater : UnityEditor.AssetModificationProcessor
13  {
14 #if UNITY_2017_1_OR_NEWER
15  private static readonly List<AtlasPrefabReference> References = new List<AtlasPrefabReference>();
16 
17  static AtlasReferenceUpdater()
18  {
19  FindAtlasPrefabReferences();
20  UpdateAllReferences();
21  PrefabUtility.prefabInstanceUpdated += PrefabInstanceUpdated;
22  }
23 
24  private static void FindAtlasPrefabReferences()
25  {
26  References.Clear();
27  foreach (var reference in FindAllAssets<AtlasPrefabReference>())
28  {
29  if (reference.Atlas == null)
30  {
31  Debug.LogWarning("No sprite atlas referenced: " + reference.name);
32  continue;
33  }
34  if (reference.Prefabs.Any(o => o == null))
35  {
36  Debug.LogWarning("One or more prefab references are null: " + reference.name);
37  continue;
38  }
39  References.Add(reference);
40  }
41  }
42 
43  private static void UpdateAllReferences()
44  {
45  foreach (var atlasPrefabReference in References)
46  {
47  UpdateAtlasReferences(atlasPrefabReference);
48  }
49  }
50 
51  private static void PrefabInstanceUpdated(GameObject instance)
52  {
53  var prefab = PrefabUtility.GetPrefabParent(instance) as GameObject;
54  foreach (var atlasPrefabReference in References)
55  {
56  if (atlasPrefabReference.Prefabs.Contains(prefab))
57  {
58  UpdateAtlasReferences(atlasPrefabReference);
59  }
60  }
61  }
62  private static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions options)
63  {
64  var atlasReference = AssetDatabase.LoadAssetAtPath<AtlasPrefabReference>(assetPath);
65  if (atlasReference != null)
66  {
67  EditorApplication.delayCall += FindAtlasPrefabReferences;
68  return AssetDeleteResult.DidNotDelete;
69  }
70 
71  var deletedSprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
72  if (deletedSprite != null)
73  {
74  foreach (var reference in References.Where(_ref => _ref.Atlas.ContainsSprite(deletedSprite)))
75  {
76  var localRef = reference;
77  EditorApplication.delayCall += () => UpdateAtlasReferences(localRef);
78  }
79  return AssetDeleteResult.DidNotDelete;
80  }
81 
82  return AssetDeleteResult.DidNotDelete;
83  }
84 
85  private static string[] OnWillSaveAssets(string[] paths)
86  {
87  if (paths.Select(AssetDatabase.LoadAssetAtPath<AtlasPrefabReference>).Any(_ref => _ref != null))
88  {
89  EditorApplication.delayCall += FindAtlasPrefabReferences;
90  EditorApplication.delayCall += UpdateAllReferences;
91  }
92  return paths;
93  }
94 
95  private static IEnumerable<T> FindAllAssets<T>() where T : UnityEngine.Object
96  {
97  var type = typeof(T).FullName;
98  foreach (var assetGuid in AssetDatabase.FindAssets("t:" + type))
99  {
100  var obj = AssetDatabase.LoadAssetAtPath<T>(AssetDatabase.GUIDToAssetPath(assetGuid));
101  if (obj != null)
102  {
103  yield return obj;
104  }
105  }
106  }
107 
108  public static void UpdateAtlasReferences(AtlasPrefabReference reference)
109  {
110  var uniqueSprites = GetDistinctSprites(reference.Prefabs).ToList();
111  reference.Atlas.SetSprites(uniqueSprites);
112  }
113 
114  private static IEnumerable<Sprite> GetDistinctSprites(IEnumerable<GameObject> prefabs)
115  {
116  return prefabs.SelectMany(p => p.GetComponentsInChildren<Image>())
117  .Select(img => img.sprite).Where(img => img != null).Distinct();
118  }
119 #endif // UNITY_2017_1_OR_NEWER
120  }
121 }