SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
6.4 KiB

4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. #if !UNITY_2019_2_OR_NEWER
  4. using UnityEngine.Experimental;
  5. #endif
  6. #if USE_XR_MANAGEMENT
  7. using UnityEngine.XR.Management;
  8. #endif
  9. namespace UnityEngine.XR.ARFoundation
  10. {
  11. /// <summary>
  12. /// A base class for subsystems whose lifetime is managed by a <c>MonoBehaviour</c>.
  13. /// </summary>
  14. /// <typeparam name="TSubsystem">The <c>Subsystem</c> which provides this manager data.</typeparam>
  15. /// <typeparam name="TSubsystemDescriptor">The <c>SubsystemDescriptor</c> required to create the Subsystem.</typeparam>
  16. public class SubsystemLifecycleManager<TSubsystem, TSubsystemDescriptor> : MonoBehaviour
  17. where TSubsystem : Subsystem<TSubsystemDescriptor>
  18. where TSubsystemDescriptor : SubsystemDescriptor<TSubsystem>
  19. {
  20. /// <summary>
  21. /// Get the <c>TSubsystem</c> whose lifetime this component manages.
  22. /// </summary>
  23. public TSubsystem subsystem { get; private set; }
  24. /// <summary>
  25. /// The descriptor for the subsystem.
  26. /// </summary>
  27. /// <value>
  28. /// The descriptor for the subsystem.
  29. /// </value>
  30. public TSubsystemDescriptor descriptor
  31. {
  32. get { return (subsystem == null) ? null : subsystem.SubsystemDescriptor; }
  33. }
  34. bool m_CleanupSubsystemOnDestroy = true;
  35. /// <summary>
  36. /// Creates a <c>TSubsystem</c>.
  37. /// </summary>
  38. /// <returns>The first Subsystem of matching the <c>TSubsystemDescriptor</c>, or <c>null</c> if there aren't any.</returns>
  39. protected virtual TSubsystem CreateSubsystem()
  40. {
  41. SubsystemManager.GetSubsystemDescriptors(s_SubsystemDescriptors);
  42. if (s_SubsystemDescriptors.Count > 0)
  43. {
  44. var descriptor = s_SubsystemDescriptors[0];
  45. if (s_SubsystemDescriptors.Count > 1)
  46. {
  47. Debug.LogWarningFormat("Multiple {0} found. Using {1}",
  48. typeof(TSubsystem).Name,
  49. descriptor.id);
  50. }
  51. return descriptor.Create();
  52. }
  53. else
  54. {
  55. return null;
  56. }
  57. }
  58. /// <summary>
  59. /// Creates a subsystem if subsystem is <c>null</c>.
  60. /// </summary>
  61. protected void CreateSubsystemIfNecessary()
  62. {
  63. // Use the subsystem that has been instantiated by XR Management
  64. // if available, otherwise create the subsystem.
  65. if (subsystem == null)
  66. {
  67. subsystem = GetActiveSubsystemInstance();
  68. // If the subsystem has already been created by XR management, it controls the lifetime
  69. // of the subsystem.
  70. if (subsystem != null)
  71. m_CleanupSubsystemOnDestroy = false;
  72. }
  73. if (subsystem == null)
  74. subsystem = CreateSubsystem();
  75. }
  76. /// <summary>
  77. /// Returns the active <c>TSubsystem</c> instance if present, otherwise returns null.
  78. /// </summary>
  79. protected TSubsystem GetActiveSubsystemInstance()
  80. {
  81. TSubsystem activeSubsystem = null;
  82. #if USE_XR_MANAGEMENT
  83. // If the XR management package has been included, query the currently
  84. // active loader for the created subsystem, if one exists.
  85. if (XRGeneralSettings.Instance != null && XRGeneralSettings.Instance.Manager != null)
  86. {
  87. XRLoader loader = XRGeneralSettings.Instance.Manager.activeLoader;
  88. if (loader != null)
  89. activeSubsystem = loader.GetLoadedSubsystem<TSubsystem>();
  90. }
  91. #endif
  92. // If XR management is not used or no loader has been set, check for
  93. // any active subsystem instances in the SubsystemManager.
  94. if (activeSubsystem == null)
  95. {
  96. SubsystemManager.GetInstances(s_SubsystemInstances);
  97. #if !UNITY_2019_3_OR_NEWER
  98. foreach (var instance in s_SubsystemInstances)
  99. {
  100. if (!s_DestroyedSubsystemTypes.Contains(instance))
  101. {
  102. return instance;
  103. }
  104. }
  105. #else
  106. if (s_SubsystemInstances.Count > 0)
  107. {
  108. activeSubsystem = s_SubsystemInstances[0];
  109. }
  110. #endif
  111. }
  112. return activeSubsystem;
  113. }
  114. /// <summary>
  115. /// Creates the <c>TSubsystem</c>.
  116. /// </summary>
  117. protected virtual void OnEnable()
  118. {
  119. CreateSubsystemIfNecessary();
  120. if (subsystem != null)
  121. {
  122. OnBeforeStart();
  123. // The derived class may disable the
  124. // component if it has invalid state
  125. if (enabled)
  126. {
  127. subsystem.Start();
  128. OnAfterStart();
  129. }
  130. }
  131. }
  132. /// <summary>
  133. /// Stops the <c>TSubsystem</c>.
  134. /// </summary>
  135. protected virtual void OnDisable()
  136. {
  137. if (subsystem != null)
  138. subsystem.Stop();
  139. }
  140. /// <summary>
  141. /// Destroys the <c>TSubsystem</c>.
  142. /// </summary>
  143. protected virtual void OnDestroy()
  144. {
  145. if (m_CleanupSubsystemOnDestroy && subsystem != null)
  146. {
  147. #if !UNITY_2019_3_OR_NEWER
  148. s_DestroyedSubsystemTypes.Add(subsystem);
  149. #endif
  150. subsystem.Destroy();
  151. }
  152. subsystem = null;
  153. }
  154. /// <summary>
  155. /// Invoked after creating the subsystem and before calling Start on it.
  156. /// The <see cref="subsystem"/> is not <c>null</c>.
  157. /// </summary>
  158. protected virtual void OnBeforeStart()
  159. { }
  160. /// <summary>
  161. /// Invoked after calling Start on it the Subsystem.
  162. /// The <see cref="subsystem"/> is not <c>null</c>.
  163. /// </summary>
  164. protected virtual void OnAfterStart()
  165. { }
  166. static List<TSubsystemDescriptor> s_SubsystemDescriptors =
  167. new List<TSubsystemDescriptor>();
  168. static List<TSubsystem> s_SubsystemInstances =
  169. new List<TSubsystem>();
  170. #if !UNITY_2019_3_OR_NEWER
  171. static HashSet<TSubsystem> s_DestroyedSubsystemTypes =
  172. new HashSet<TSubsystem>();
  173. #endif
  174. }
  175. }