XRLoaderInfoManager.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using UnityEngine.XR.Management;
  6. namespace UnityEditor.XR.Management
  7. {
  8. internal class XRLoaderInfoManager : IXRLoaderOrderManager
  9. {
  10. // Simple class to give us updates when the asset database changes.
  11. internal class AssetCallbacks : AssetPostprocessor
  12. {
  13. static bool s_EditorUpdatable = false;
  14. internal static System.Action Callback { get; set; }
  15. static AssetCallbacks()
  16. {
  17. if (!s_EditorUpdatable)
  18. {
  19. EditorApplication.update += EditorUpdatable;
  20. }
  21. EditorApplication.projectChanged += EditorApplicationOnProjectChanged;
  22. }
  23. static void EditorApplicationOnProjectChanged()
  24. {
  25. if (Callback != null)
  26. Callback.Invoke();
  27. }
  28. static void EditorUpdatable()
  29. {
  30. s_EditorUpdatable = true;
  31. EditorApplication.update -= EditorUpdatable;
  32. if (Callback != null)
  33. Callback.Invoke();
  34. }
  35. }
  36. private SerializedObject m_SerializedObject;
  37. SerializedProperty m_RequiresSettingsUpdate = null;
  38. SerializedProperty m_LoaderList = null;
  39. public SerializedObject SerializedObjectData
  40. {
  41. get { return m_SerializedObject; }
  42. set
  43. {
  44. if (m_SerializedObject != value)
  45. {
  46. m_SerializedObject = value;
  47. PopulateProperty("m_RequiresSettingsUpdate", ref m_RequiresSettingsUpdate);
  48. PopulateProperty("m_Loaders", ref m_LoaderList);
  49. ShouldReload = true;
  50. }
  51. }
  52. }
  53. List<XRLoaderInfo> m_AllLoaderInfos = new List<XRLoaderInfo>();
  54. List<XRLoaderInfo> m_AllLoaderInfosForBuildTarget = new List<XRLoaderInfo>();
  55. List<XRLoaderInfo> m_AssignedLoaderInfos = new List<XRLoaderInfo>();
  56. List<XRLoaderInfo> m_UnassignedLoaderInfos = new List<XRLoaderInfo>();
  57. private BuildTargetGroup m_BuildTargetGroup = BuildTargetGroup.Unknown;
  58. internal BuildTargetGroup BuildTarget
  59. {
  60. get { return m_BuildTargetGroup; }
  61. set
  62. {
  63. if (m_BuildTargetGroup != value)
  64. {
  65. m_BuildTargetGroup = value;
  66. ShouldReload = true;
  67. }
  68. }
  69. }
  70. void AssetProcessorCallback()
  71. {
  72. ShouldReload = true;
  73. }
  74. public void OnEnable()
  75. {
  76. AssetCallbacks.Callback += AssetProcessorCallback;
  77. ShouldReload = true;
  78. }
  79. public bool ShouldReload
  80. {
  81. get
  82. {
  83. if (m_RequiresSettingsUpdate != null)
  84. {
  85. SerializedObjectData.Update();
  86. return m_RequiresSettingsUpdate.boolValue;
  87. }
  88. return false;
  89. }
  90. set
  91. {
  92. if (m_RequiresSettingsUpdate != null && m_RequiresSettingsUpdate.boolValue != value)
  93. {
  94. m_RequiresSettingsUpdate.boolValue = value;
  95. SerializedObjectData.ApplyModifiedProperties();
  96. }
  97. }
  98. }
  99. public void OnDisable()
  100. {
  101. AssetCallbacks.Callback -= null;
  102. }
  103. public void ReloadData()
  104. {
  105. if (m_LoaderList == null)
  106. return;
  107. PopulateAllLoaderInfos();
  108. PopulateLoadersForBuildTarget();
  109. PopulateAssignedLoaderInfos();
  110. PopulateUnassignedLoaderInfos();
  111. ShouldReload = false;
  112. }
  113. void PopulateAllLoaderInfos()
  114. {
  115. m_AllLoaderInfos.Clear();
  116. XRLoaderInfo.GetAllKnownLoaderInfos(m_AllLoaderInfos);
  117. }
  118. void CleanupLostAssignedLoaders()
  119. {
  120. var missingLoaders = from info in m_AssignedLoaderInfos
  121. where info.instance == null
  122. select info;
  123. if (missingLoaders.Any())
  124. {
  125. m_AssignedLoaderInfos = m_AssignedLoaderInfos.Except(missingLoaders).ToList();
  126. }
  127. }
  128. void PopulateAssignedLoaderInfos()
  129. {
  130. m_AssignedLoaderInfos.Clear();
  131. for (int i = 0; i < m_LoaderList.arraySize; i++)
  132. {
  133. var prop = m_LoaderList.GetArrayElementAtIndex(i);
  134. XRLoaderInfo info = new XRLoaderInfo();
  135. info.loaderType = (prop.objectReferenceValue == null) ? null : prop.objectReferenceValue.GetType();
  136. info.assetName = AssetNameFromInstance(prop.objectReferenceValue);
  137. info.instance = prop.objectReferenceValue as XRLoader;
  138. m_AssignedLoaderInfos.Add(info);
  139. }
  140. CleanupLostAssignedLoaders();
  141. }
  142. string AssetNameFromInstance(UnityEngine.Object asset)
  143. {
  144. if (asset == null)
  145. return "";
  146. string assetPath = AssetDatabase.GetAssetPath(asset);
  147. return Path.GetFileNameWithoutExtension(assetPath);
  148. }
  149. void PopulateLoadersForBuildTarget()
  150. {
  151. m_AllLoaderInfosForBuildTarget = FilteredLoaderInfos(m_AllLoaderInfos);
  152. }
  153. void PopulateUnassignedLoaderInfos()
  154. {
  155. m_UnassignedLoaderInfos.Clear();
  156. foreach (var info in m_AllLoaderInfosForBuildTarget)
  157. {
  158. var assigned = from ai in m_AssignedLoaderInfos where ai.loaderType == info.loaderType select ai;
  159. if (!assigned.Any()) m_UnassignedLoaderInfos.Add(info);
  160. }
  161. }
  162. void PopulateProperty(string propertyPath, ref SerializedProperty prop)
  163. {
  164. if (SerializedObjectData != null && prop == null) prop = SerializedObjectData.FindProperty(propertyPath);
  165. }
  166. private List<XRLoaderInfo> FilteredLoaderInfos(List<XRLoaderInfo> loaderInfos)
  167. {
  168. List<XRLoaderInfo> ret = new List<XRLoaderInfo>();
  169. foreach (var info in loaderInfos)
  170. {
  171. if (info.loaderType == null)
  172. continue;
  173. object[] attrs;
  174. try
  175. {
  176. attrs = info.loaderType.GetCustomAttributes(typeof(XRSupportedBuildTargetAttribute), true);
  177. }
  178. catch (Exception)
  179. {
  180. attrs = default;
  181. }
  182. if (attrs.Length == 0)
  183. {
  184. // If unmarked we assume it will be applied to all build targets.
  185. ret.Add(info);
  186. }
  187. else
  188. {
  189. foreach (XRSupportedBuildTargetAttribute attr in attrs)
  190. {
  191. if (attr.buildTargetGroup == m_BuildTargetGroup)
  192. {
  193. ret.Add(info);
  194. break;
  195. }
  196. }
  197. }
  198. }
  199. return ret;
  200. }
  201. void UpdateSerializedProperty()
  202. {
  203. if (m_LoaderList != null && m_LoaderList.isArray)
  204. {
  205. m_LoaderList.ClearArray();
  206. int index = 0;
  207. foreach (XRLoaderInfo info in m_AssignedLoaderInfos)
  208. {
  209. m_LoaderList.InsertArrayElementAtIndex(index);
  210. var prop = m_LoaderList.GetArrayElementAtIndex(index);
  211. prop.objectReferenceValue = info.instance;
  212. index++;
  213. }
  214. }
  215. SerializedObjectData.ApplyModifiedProperties();
  216. }
  217. #region IXRLoaderOrderManager
  218. List<XRLoaderInfo> IXRLoaderOrderManager.AssignedLoaders { get { return m_AssignedLoaderInfos; } }
  219. List<XRLoaderInfo> IXRLoaderOrderManager.UnassignedLoaders { get { return m_UnassignedLoaderInfos; } }
  220. void IXRLoaderOrderManager.AssignLoader(XRLoaderInfo assignedInfo)
  221. {
  222. m_AssignedLoaderInfos.Add(assignedInfo);
  223. m_UnassignedLoaderInfos.Remove(assignedInfo);
  224. UpdateSerializedProperty();
  225. ShouldReload = true;
  226. }
  227. void IXRLoaderOrderManager.UnassignLoader(XRLoaderInfo unassignedInfo)
  228. {
  229. m_AssignedLoaderInfos.Remove(unassignedInfo);
  230. m_UnassignedLoaderInfos.Add(unassignedInfo);
  231. UpdateSerializedProperty();
  232. ShouldReload = true;
  233. }
  234. void IXRLoaderOrderManager.Update()
  235. {
  236. UpdateSerializedProperty();
  237. ShouldReload = true;
  238. }
  239. #endregion
  240. }
  241. }