PICOFeature.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. using System.Collections.Generic;
  2. using UnityEngine.XR.OpenXR;
  3. using UnityEngine.XR.OpenXR.Features;
  4. using Object = System.Object;
  5. using UnityEngine.XR.OpenXR.Features.Interactions;
  6. using System;
  7. using System.Runtime.InteropServices;
  8. using UnityEngine;
  9. using AOT;
  10. #if UNITY_EDITOR
  11. using UnityEditor.PackageManager;
  12. using UnityEditor.PackageManager.Requests;
  13. using UnityEditor;
  14. using UnityEditor.XR.OpenXR.Features;
  15. #endif
  16. #if AR_FOUNDATION
  17. using UnityEngine.XR.ARSubsystems;
  18. #endif
  19. namespace Unity.XR.OpenXR.Features.PICOSupport
  20. {
  21. /// <summary>
  22. /// Enables the PICO mobile OpenXR Loader for Android, and modifies the AndroidManifest to be compatible with Neo3.
  23. /// </summary>
  24. #if UNITY_EDITOR
  25. [OpenXRFeature(UiName = "PICO Support",
  26. Desc = "Necessary to deploy an PICO compatible app.",
  27. Company = "PICO",
  28. Version = "1.0.0",
  29. BuildTargetGroups = new[] { BuildTargetGroup.Android },
  30. CustomRuntimeLoaderBuildTargets = new[] { BuildTarget.Android },
  31. OpenxrExtensionStrings = PicoExtensionList,
  32. FeatureId = featureId
  33. )]
  34. #endif
  35. [System.Serializable]
  36. public class PICOFeature : OpenXRFeature
  37. {
  38. public const string PicoExtensionList = "";
  39. public static string SDKVersion = "Unity_OpenXR_1.2.0";
  40. public static Action<bool> onAppFocusedAction;
  41. public bool isCameraSubsystem;
  42. #if AR_FOUNDATION
  43. static List<XRHumanBodySubsystemDescriptor> s_HumanBodyDescriptors = new List<XRHumanBodySubsystemDescriptor>();
  44. static List<XRFaceSubsystemDescriptor> s_FaceDescriptors = new List<XRFaceSubsystemDescriptor>();
  45. static List<XRCameraSubsystemDescriptor> s_CameraDescriptors = new List<XRCameraSubsystemDescriptor>();
  46. #endif
  47. /// <summary>
  48. /// The feature id string. This is used to give the feature a well known id for reference.
  49. /// </summary>
  50. public const string featureId = "com.unity.openxr.feature.pico";
  51. private static ulong xrSession = 0ul;
  52. #if UNITY_EDITOR
  53. static AddRequest request;
  54. protected override void GetValidationChecks(List<ValidationRule> rules, BuildTargetGroup targetGroup)
  55. {
  56. OpenXRSettings settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
  57. var AdditionalRules = new ValidationRule[]
  58. {
  59. new ValidationRule(this)
  60. {
  61. message = "Only the PICO Touch Interaction Profile is supported right now.",
  62. checkPredicate = () =>
  63. {
  64. if (null == settings)
  65. return false;
  66. bool touchFeatureEnabled = false;
  67. bool otherInteractionFeatureEnabled = false;
  68. foreach (var feature in settings.GetFeatures<OpenXRInteractionFeature>())
  69. {
  70. if (feature.enabled)
  71. {
  72. if ((feature is PICONeo3ControllerProfile) || (feature is PICO4ControllerProfile) || (feature is EyeGazeInteraction)|| (feature is PICOG3ControllerProfile))
  73. touchFeatureEnabled = true;
  74. else
  75. otherInteractionFeatureEnabled = true;
  76. }
  77. }
  78. return touchFeatureEnabled && !otherInteractionFeatureEnabled;
  79. },
  80. fixIt = () =>
  81. {
  82. if (null == settings)
  83. return;
  84. foreach (var feature in settings.GetFeatures<OpenXRInteractionFeature>())
  85. {
  86. feature.enabled = ((feature is PICONeo3ControllerProfile) || (feature is PICO4ControllerProfile));
  87. }
  88. },
  89. error = true,
  90. },
  91. new ValidationRule(this)
  92. {
  93. message = "Only Unity OpenXR Plugin prior to version 1.9.1 is supported right now.",
  94. checkPredicate = () =>
  95. {
  96. #if OPENXR_1_9_1
  97. return false;
  98. #else
  99. return true;
  100. #endif
  101. },
  102. fixIt = () =>
  103. {
  104. if (request == null)
  105. {
  106. request = Client.Add("com.unity.xr.openxr@1.8.2");
  107. }
  108. EditorApplication.update += Progress;
  109. },
  110. error = true,
  111. fixItMessage = "Unity OpenXR plugin will be downgraded to 1.8.2."
  112. }
  113. };
  114. rules.AddRange(AdditionalRules);
  115. }
  116. static void Progress()
  117. {
  118. if (request != null && request.IsCompleted)
  119. {
  120. if (request.Status == StatusCode.Success)
  121. Debug.Log("Installed: " + request.Result.packageId);
  122. else if (request.Status >= StatusCode.Failure)
  123. Debug.Log(request.Error.message);
  124. EditorApplication.update -= Progress;
  125. request = null;
  126. }
  127. }
  128. internal class PICOFeatureEditorWindow : EditorWindow
  129. {
  130. private Object feature;
  131. private Editor featureEditor;
  132. public static EditorWindow Create(Object feature)
  133. {
  134. var window = EditorWindow.GetWindow<PICOFeatureEditorWindow>(true, "PICO Feature Configuration", true);
  135. window.feature = feature;
  136. window.featureEditor = Editor.CreateEditor((UnityEngine.Object)feature);
  137. return window;
  138. }
  139. private void OnGUI()
  140. {
  141. featureEditor.OnInspectorGUI();
  142. }
  143. }
  144. #endif
  145. protected override void OnSubsystemCreate()
  146. {
  147. base.OnSubsystemCreate();
  148. #if AR_FOUNDATION
  149. // PICOProjectSetting projectConfig = PICOProjectSetting.GetProjectConfig();
  150. isCameraSubsystem = isCameraSubsystem && OpenXRRuntime.IsExtensionEnabled("XR_FB_passthrough");
  151. if (isCameraSubsystem)
  152. {
  153. CreateSubsystem<XRCameraSubsystemDescriptor, XRCameraSubsystem>(
  154. s_CameraDescriptors,
  155. PICOCameraSubsystem.k_SubsystemId);
  156. }
  157. #endif
  158. }
  159. protected override void OnSubsystemStart()
  160. {
  161. #if AR_FOUNDATION
  162. if (isCameraSubsystem)
  163. {
  164. StartSubsystem<XRCameraSubsystem>();
  165. }
  166. #endif
  167. }
  168. protected override void OnSubsystemStop()
  169. {
  170. #if AR_FOUNDATION
  171. if (isCameraSubsystem)
  172. {
  173. StopSubsystem<XRCameraSubsystem>();
  174. }
  175. #endif
  176. }
  177. protected override void OnSubsystemDestroy()
  178. {
  179. #if AR_FOUNDATION
  180. if (isCameraSubsystem)
  181. {
  182. DestroySubsystem<XRCameraSubsystem>();
  183. }
  184. #endif
  185. }
  186. protected override bool OnInstanceCreate(ulong xrInstance)
  187. {
  188. OpenXRExtensions.isPicoSupport = true;
  189. return base.OnInstanceCreate(xrInstance);
  190. }
  191. protected override void OnSessionStateChange(int oldState, int newState)
  192. {
  193. base.OnSessionStateChange(oldState, newState);
  194. if (onAppFocusedAction != null)
  195. {
  196. onAppFocusedAction(newState == 5);
  197. }
  198. if (newState == 1)
  199. {
  200. #if AR_FOUNDATION
  201. if (isCameraSubsystem)
  202. {
  203. StopSubsystem<XRCameraSubsystem>();
  204. }
  205. #endif
  206. }
  207. else if (newState == 5)
  208. {
  209. #if AR_FOUNDATION
  210. if (isCameraSubsystem)
  211. {
  212. StartSubsystem<XRCameraSubsystem>();
  213. }
  214. #endif
  215. }
  216. }
  217. protected override void OnSessionCreate(ulong xrSessionId)
  218. {
  219. xrSession = xrSessionId;
  220. base.OnSessionCreate(xrSessionId);
  221. //log level
  222. float logLevel = 0;
  223. if (GetLogLevel(xrSession, ref logLevel))
  224. {
  225. PLog.logLevel = (PLog.LogLevel)logLevel;
  226. }
  227. PLog.i($"OpenXR SDK Version:{SDKVersion}, logLevel:{(int)PLog.logLevel}");
  228. LogLevelCallback(OnMessage);
  229. }
  230. private delegate void OnChangeDelegate(int level);
  231. [MonoPInvokeCallback(typeof(OnChangeDelegate))]
  232. private static void OnMessage(int level)
  233. {
  234. if (level > 0)
  235. {
  236. PLog.logLevel = (PLog.LogLevel)level;
  237. }
  238. PLog.i($"OpenXR level:{level}, logLevel:{(int)PLog.logLevel}");
  239. }
  240. /// <inheritdoc/>
  241. protected override void OnSessionDestroy(ulong xrSessionId)
  242. {
  243. base.OnSessionDestroy(xrSessionId);
  244. xrSession = 0ul;
  245. }
  246. internal delegate void ReceiveLogLevelChangeDelegate(int level);
  247. const string extLib = "openxr_pico";
  248. [DllImport(extLib, EntryPoint = "PICO_GetLogLevel", CallingConvention = CallingConvention.Cdecl)]
  249. private static extern bool GetLogLevel(ulong xrSpace, ref float ret);
  250. [DllImport(extLib, EntryPoint = "PICO_LogLevelCallback")]
  251. private static extern void LogLevelCallback(ReceiveLogLevelChangeDelegate callback);
  252. }
  253. }