XRPackageInitialization.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor.XR.Management.Metadata;
  5. namespace UnityEditor.XR.Management
  6. {
  7. /// <summary>Interface for specifying package initialization information</summary>
  8. public interface XRPackageInitializationBase
  9. {
  10. /// <summary>Package name property</summary>
  11. /// <value>The name of the package</value>
  12. string PackageName { get; }
  13. /// <summary>The loader full type name for this package</summary>
  14. /// <value>Loader fulltype name</value>
  15. string LoaderFullTypeName { get; }
  16. /// <summary>The loader type name for this package</summary>
  17. /// <value>Loader type name</value>
  18. string LoaderTypeName { get; }
  19. /// <summary>The settings full type name for this package</summary>
  20. /// <value>Settings full type name</value>
  21. string SettingsFullTypeName { get; }
  22. /// <summary>The settings type name for this package</summary>
  23. /// <value>Settings type name</value>
  24. string SettingsTypeName { get; }
  25. /// <summary>Package initialization key</summary>
  26. /// <value>The init key for the package</value>
  27. string PackageInitKey { get; }
  28. /// <summary>Initialize package settings</summary>
  29. /// <param name="obj">The scriptable object instance to initialize</param>
  30. /// <returns>True if successful, false if not.</returns>
  31. bool PopulateSettingsOnInitialization(ScriptableObject obj);
  32. }
  33. [InitializeOnLoad]
  34. class XRPackageInitializationBootstrap
  35. {
  36. static XRPackageInitializationBootstrap()
  37. {
  38. if (!EditorApplication.isPlayingOrWillChangePlaymode)
  39. {
  40. EditorApplication.update += BeginPackageInitialization;
  41. }
  42. EditorApplication.playModeStateChanged += PlayModeStateChanged;
  43. }
  44. private static void PlayModeStateChanged(PlayModeStateChange state)
  45. {
  46. switch (state)
  47. {
  48. case PlayModeStateChange.EnteredPlayMode:
  49. BeginPackageInitialization();
  50. break;
  51. case PlayModeStateChange.EnteredEditMode:
  52. BeginPackageInitialization();
  53. break;
  54. }
  55. }
  56. internal static void BeginPackageInitialization()
  57. {
  58. EditorApplication.update -= BeginPackageInitialization;
  59. foreach (var t in TypeLoaderExtensions.GetAllTypesWithInterface<IXRPackage>())
  60. {
  61. if (t.IsInterface || t.FullName.Contains("Unity.XR.Management.TestPackage") || t.FullName.Contains("UnityEditor.XR.Management.Metadata.KnownPackages"))
  62. continue;
  63. IXRPackage package = Activator.CreateInstance(t) as IXRPackage;
  64. if (package == null)
  65. {
  66. Debug.LogError($"Unable to find an implementation for expected package type {t.FullName}.");
  67. continue;
  68. }
  69. InitPackage(package);
  70. }
  71. foreach (var t in TypeLoaderExtensions.GetAllTypesWithInterface<XRPackageInitializationBase>())
  72. {
  73. if (t.IsInterface)
  74. continue;
  75. XRPackageInitializationBase packageInit = Activator.CreateInstance(t) as XRPackageInitializationBase;
  76. if (packageInit == null)
  77. {
  78. Debug.LogError($"Unable to find an implementation for expected package type {t.FullName}.");
  79. continue;
  80. }
  81. InitPackage(packageInit);
  82. }
  83. if (XRSettingsManager.Instance != null) XRSettingsManager.Instance.ResetUi = true;
  84. }
  85. internal static void InitPackage(IXRPackage package)
  86. {
  87. var packageMetadata = package.metadata;
  88. if (packageMetadata == null)
  89. {
  90. Debug.LogError($"Package {package.GetType().Name} has a package definition but has no metadata. Skipping initialization.");
  91. return;
  92. }
  93. XRPackageMetadataStore.AddPluginPackage(package);
  94. if (!InitializePackageFromMetadata(package, packageMetadata))
  95. {
  96. Debug.LogWarning(
  97. String.Format("{0} package Initialization not completed. You will need to create any instances of the loaders and settings manually before you can use the intended XR Plug-in Package.", packageMetadata.packageName));
  98. }
  99. }
  100. static bool InitializePackageFromMetadata(IXRPackage package, IXRPackageMetadata packageMetadata)
  101. {
  102. bool ret = true;
  103. ret = ret && InitializeLoaderFromMetadata(packageMetadata.packageName, packageMetadata.loaderMetadata);
  104. ret = ret && InitializeSettingsFromMetadata(package, packageMetadata.packageName, packageMetadata.settingsType);
  105. return ret;
  106. }
  107. static bool InitializeLoaderFromMetadata(string packageName, List<IXRLoaderMetadata> loaderMetadatas)
  108. {
  109. if (String.IsNullOrEmpty(packageName))
  110. return false;
  111. if (loaderMetadatas == null || loaderMetadatas.Count == 0)
  112. {
  113. Debug.LogWarning($"Package {packageName} has no loader metadata. Skipping loader initialization.");
  114. return true;
  115. }
  116. bool ret = true;
  117. foreach (var loader in loaderMetadatas)
  118. {
  119. bool hasInstance = EditorUtilities.AssetDatabaseHasInstanceOfType(loader.loaderType);
  120. if (!hasInstance)
  121. {
  122. var obj = EditorUtilities.CreateScriptableObjectInstance(loader.loaderType,
  123. EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultLoaderPath));
  124. hasInstance = (obj != null);
  125. if (!hasInstance)
  126. {
  127. Debug.LogError($"Error creating instance of loader {loader.loaderName} for package {packageName}");
  128. }
  129. }
  130. ret |= hasInstance;
  131. }
  132. return ret;
  133. }
  134. static bool InitializeSettingsFromMetadata(IXRPackage package, string packageName, string settingsType)
  135. {
  136. if (String.IsNullOrEmpty(packageName))
  137. return false;
  138. if (settingsType == null)
  139. {
  140. Debug.LogWarning($"Package {packageName} has no settings metadata. Skipping settings initialization.");
  141. return true;
  142. }
  143. bool ret = EditorUtilities.AssetDatabaseHasInstanceOfType(settingsType);
  144. if (!ret)
  145. {
  146. var obj = EditorUtilities.CreateScriptableObjectInstance( settingsType,
  147. EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultSettingsPath));
  148. ret = package.PopulateNewSettingsInstance(obj);
  149. }
  150. return ret;
  151. }
  152. static void InitPackage(XRPackageInitializationBase packageInit)
  153. {
  154. if (!InitializeLoaderInstance(packageInit))
  155. {
  156. Debug.LogWarning(
  157. String.Format("{0} Loader Initialization not completed. You will need to create an instance of the loader manually before you can use the intended XR Plug-in Package.", packageInit.PackageName));
  158. }
  159. if (!InitializeSettingsInstance(packageInit))
  160. {
  161. Debug.LogWarning(
  162. String.Format("{0} Settings Initialization not completed. You will need to create an instance of settings to customize options specific to this package.", packageInit.PackageName));
  163. }
  164. }
  165. static bool InitializeLoaderInstance(XRPackageInitializationBase packageInit)
  166. {
  167. bool ret = EditorUtilities.AssetDatabaseHasInstanceOfType(packageInit.LoaderTypeName);
  168. if (!ret)
  169. {
  170. var obj = EditorUtilities.CreateScriptableObjectInstance(packageInit.LoaderFullTypeName,
  171. EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultLoaderPath));
  172. ret = (obj != null);
  173. }
  174. return ret;
  175. }
  176. static bool InitializeSettingsInstance(XRPackageInitializationBase packageInit)
  177. {
  178. bool ret = EditorUtilities.AssetDatabaseHasInstanceOfType(packageInit.SettingsTypeName);
  179. if (!ret)
  180. {
  181. var obj = EditorUtilities.CreateScriptableObjectInstance(packageInit.SettingsFullTypeName,
  182. EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultSettingsPath));
  183. ret = packageInit.PopulateSettingsOnInitialization(obj);
  184. }
  185. return ret;
  186. }
  187. }
  188. }