SteamVR_AutoEnableVR.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Prompt developers to use settings most compatible with SteamVR.
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using UnityEditor;
  8. using System.IO;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System;
  12. using System.Reflection;
  13. using Valve.VR.InteractionSystem;
  14. #if OPENVR_XR_API
  15. using UnityEditor.XR.Management.Metadata;
  16. using UnityEngine.XR.Management;
  17. #endif
  18. #if UNITY_2018_2_OR_NEWER
  19. #pragma warning disable CS0618
  20. #pragma warning disable CS0219
  21. #pragma warning disable CS0414
  22. #endif
  23. namespace Valve.VR
  24. {
  25. [InitializeOnLoad]
  26. public class SteamVR_AutoEnableVR
  27. {
  28. static SteamVR_AutoEnableVR()
  29. {
  30. EditorApplication.update += Update;
  31. }
  32. protected const string openVRString = "OpenVR";
  33. protected const string unityOpenVRPackageString = "com.unity.xr.openvr.standalone";
  34. protected const string valveOpenVRPackageString = "com.valvesoftware.unity.openvr";
  35. #if UNITY_2020_1_OR_NEWER || OPENVR_XR_API
  36. protected const string valveEnabledLoaderKeyTemplate = "valve.enablexddrloader.{0}";
  37. protected const string valveOpenVRLoaderType = "Unity.XR.OpenVR.OpenVRLoader";
  38. #endif
  39. #if UNITY_2018_2_OR_NEWER
  40. private enum PackageStates
  41. {
  42. None,
  43. WaitingForList,
  44. WaitingForAdd,
  45. WaitingForAddConfirm,
  46. Installed,
  47. Failed,
  48. }
  49. private static UnityEditor.PackageManager.Requests.ListRequest listRequest;
  50. private static UnityEditor.PackageManager.Requests.AddRequest addRequest;
  51. private static PackageStates packageState = PackageStates.None;
  52. private static System.Diagnostics.Stopwatch addingPackageTime = new System.Diagnostics.Stopwatch();
  53. private static System.Diagnostics.Stopwatch addingPackageTimeTotal = new System.Diagnostics.Stopwatch();
  54. private static float estimatedTimeToInstall = 80;
  55. private static int addTryCount = 0;
  56. private static string enabledLoaderKey = null;
  57. private static MethodInfo isLoaderAssigned;
  58. private static MethodInfo installPackageAndAssignLoaderForBuildTarget;
  59. private static Type[] isLoaderAssignedMethodParameters;
  60. private static object[] isLoaderAssignedCallParameters;
  61. #endif
  62. public static void Update()
  63. {
  64. if (SteamVR_Settings.instance.autoEnableVR)
  65. {
  66. bool enabledVR = false;
  67. #if UNITY_2020_1_OR_NEWER || OPENVR_XR_API
  68. #if !UNITY_2020_2_OR_NEWER
  69. if (UnityEditor.PlayerSettings.virtualRealitySupported == true)
  70. {
  71. UnityEditor.PlayerSettings.virtualRealitySupported = false;
  72. enabledVR = true;
  73. Debug.Log("<b>[SteamVR Setup]</b> Disabled virtual reality support in Player Settings. <b>Because you're using XR Manager. Make sure OpenVR Loader is enabled in XR Manager UI.</b> (you can disable this by unchecking Assets/SteamVR/SteamVR_Settings.autoEnableVR)");
  74. }
  75. #endif
  76. #if OPENVR_XR_API
  77. //little hacky, but the public methods weren't working.
  78. if (isLoaderAssignedMethodParameters == null)
  79. isLoaderAssignedMethodParameters = new Type[] { typeof(string), typeof(BuildTargetGroup) };
  80. if (isLoaderAssignedCallParameters == null)
  81. isLoaderAssignedCallParameters = new object[] { valveOpenVRLoaderType, BuildTargetGroup.Standalone };
  82. if (isLoaderAssigned == null)
  83. isLoaderAssigned = GetMethod("IsLoaderAssigned", isLoaderAssignedMethodParameters);
  84. if (installPackageAndAssignLoaderForBuildTarget == null)
  85. installPackageAndAssignLoaderForBuildTarget = GetMethod("InstallPackageAndAssignLoaderForBuildTarget");
  86. if (isLoaderAssigned != null && installPackageAndAssignLoaderForBuildTarget != null)
  87. {
  88. bool isAssigned = (bool)isLoaderAssigned.Invoke(null, isLoaderAssignedCallParameters);
  89. if (isAssigned == false)
  90. {
  91. if (enabledLoaderKey == null)
  92. enabledLoaderKey = string.Format(valveEnabledLoaderKeyTemplate, SteamVR_Settings.instance.editorAppKey);
  93. if (EditorPrefs.HasKey(enabledLoaderKey) == false)
  94. {
  95. installPackageAndAssignLoaderForBuildTarget.Invoke(null, new object[] { valveOpenVRPackageString, valveOpenVRLoaderType, BuildTargetGroup.Standalone });
  96. isAssigned = (bool)isLoaderAssigned.Invoke(null, isLoaderAssignedCallParameters);
  97. if (isAssigned)
  98. {
  99. EditorPrefs.SetBool(enabledLoaderKey, true);
  100. Debug.Log("<b>[SteamVR Setup]</b> Enabled OpenVR Loader in XR Management");
  101. UnityEditor.EditorApplication.update -= Update;
  102. }
  103. }
  104. else
  105. {
  106. UnityEditor.EditorApplication.update -= Update;
  107. }
  108. }
  109. else
  110. {
  111. UnityEditor.EditorApplication.update -= Update;
  112. }
  113. }
  114. #elif UNITY_2020_1_OR_NEWER
  115. StartAutoUpdater();
  116. #endif
  117. #else
  118. if (UnityEditor.PlayerSettings.virtualRealitySupported == false)
  119. {
  120. UnityEditor.PlayerSettings.virtualRealitySupported = true;
  121. enabledVR = true;
  122. Debug.Log("<b>[SteamVR Setup]</b> Enabled virtual reality support in Player Settings. (you can disable this by unchecking Assets/SteamVR/SteamVR_Settings.autoEnableVR)");
  123. }
  124. UnityEditor.BuildTargetGroup currentTarget = UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup;
  125. #if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
  126. string[] devices = UnityEditorInternal.VR.VREditor.GetVREnabledDevices(currentTarget);
  127. #else
  128. string[] devices = UnityEditorInternal.VR.VREditor.GetVREnabledDevicesOnTargetGroup(currentTarget);
  129. #endif
  130. bool hasOpenVR = devices.Any(device => string.Equals(device, openVRString, System.StringComparison.CurrentCultureIgnoreCase));
  131. if (hasOpenVR == false || enabledVR)
  132. {
  133. string[] newDevices;
  134. if (enabledVR && hasOpenVR == false)
  135. {
  136. newDevices = new string[] { openVRString }; //only list openvr if we enabled it
  137. }
  138. else
  139. {
  140. List<string> devicesList = new List<string>(devices); //list openvr as the first option if it wasn't in the list.
  141. if (hasOpenVR)
  142. devicesList.Remove(openVRString);
  143. devicesList.Insert(0, openVRString);
  144. newDevices = devicesList.ToArray();
  145. }
  146. #if (UNITY_5_6 || UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
  147. UnityEditorInternal.VR.VREditor.SetVREnabledDevices(currentTarget, newDevices);
  148. #else
  149. UnityEditorInternal.VR.VREditor.SetVREnabledDevicesOnTargetGroup(currentTarget, newDevices);
  150. #endif
  151. Debug.Log("<b>[SteamVR Setup]</b> Added OpenVR to supported VR SDKs list.");
  152. }
  153. #if UNITY_2018_2_OR_NEWER
  154. //2018+ requires us to manually add the OpenVR package
  155. //2020.1+ has a separate script that does installs
  156. switch (packageState)
  157. {
  158. case PackageStates.None:
  159. //see if we have the package
  160. listRequest = UnityEditor.PackageManager.Client.List(true);
  161. packageState = PackageStates.WaitingForList;
  162. break;
  163. case PackageStates.WaitingForList:
  164. if (listRequest.IsCompleted)
  165. {
  166. if (listRequest.Error != null || listRequest.Status == UnityEditor.PackageManager.StatusCode.Failure)
  167. {
  168. packageState = PackageStates.Failed;
  169. break;
  170. }
  171. string packageName = null;
  172. packageName = unityOpenVRPackageString;
  173. bool hasPackage = listRequest.Result.Any(package => package.name == packageName);
  174. if (hasPackage == false)
  175. {
  176. //if we don't have the package - then install it
  177. addRequest = UnityEditor.PackageManager.Client.Add(packageName);
  178. packageState = PackageStates.WaitingForAdd;
  179. addTryCount++;
  180. Debug.Log("<b>[SteamVR Setup]</b> Installing OpenVR package...");
  181. addingPackageTime.Start();
  182. addingPackageTimeTotal.Start();
  183. }
  184. else
  185. {
  186. //if we do have the package, do nothing
  187. packageState = PackageStates.Installed; //already installed
  188. }
  189. }
  190. break;
  191. case PackageStates.WaitingForAdd:
  192. if (addRequest.IsCompleted)
  193. {
  194. if (addRequest.Error != null || addRequest.Status == UnityEditor.PackageManager.StatusCode.Failure)
  195. {
  196. packageState = PackageStates.Failed;
  197. break;
  198. }
  199. else
  200. {
  201. //if the package manager says we added it then confirm that with the list
  202. listRequest = UnityEditor.PackageManager.Client.List(true);
  203. packageState = PackageStates.WaitingForAddConfirm;
  204. }
  205. }
  206. else
  207. {
  208. if (addingPackageTimeTotal.Elapsed.TotalSeconds > estimatedTimeToInstall)
  209. estimatedTimeToInstall *= 2; // :)
  210. string dialogText;
  211. if (addTryCount == 1)
  212. dialogText = "Installing OpenVR from Unity Package Manager...";
  213. else
  214. dialogText = "Retrying OpenVR install from Unity Package Manager...";
  215. bool cancel = UnityEditor.EditorUtility.DisplayCancelableProgressBar("SteamVR", dialogText, (float)addingPackageTimeTotal.Elapsed.TotalSeconds / estimatedTimeToInstall);
  216. if (cancel)
  217. packageState = PackageStates.Failed;
  218. if (addingPackageTime.Elapsed.TotalSeconds > 10)
  219. {
  220. Debug.Log("<b>[SteamVR Setup]</b> Waiting for package manager to install OpenVR package...");
  221. addingPackageTime.Stop();
  222. addingPackageTime.Reset();
  223. addingPackageTime.Start();
  224. }
  225. }
  226. break;
  227. case PackageStates.WaitingForAddConfirm:
  228. if (listRequest.IsCompleted)
  229. {
  230. if (listRequest.Error != null)
  231. {
  232. packageState = PackageStates.Failed;
  233. break;
  234. }
  235. string packageName = unityOpenVRPackageString;
  236. bool hasPackage = listRequest.Result.Any(package => package.name == packageName);
  237. if (hasPackage == false)
  238. {
  239. if (addTryCount == 1)
  240. {
  241. addRequest = UnityEditor.PackageManager.Client.Add(packageName);
  242. packageState = PackageStates.WaitingForAdd;
  243. addTryCount++;
  244. Debug.Log("<b>[SteamVR Setup]</b> Retrying OpenVR package install...");
  245. }
  246. else
  247. {
  248. packageState = PackageStates.Failed;
  249. }
  250. }
  251. else
  252. {
  253. packageState = PackageStates.Installed; //installed successfully
  254. Debug.Log("<b>[SteamVR Setup]</b> Successfully installed OpenVR package.");
  255. }
  256. }
  257. break;
  258. }
  259. if (packageState == PackageStates.Failed || packageState == PackageStates.Installed)
  260. {
  261. addingPackageTime.Stop();
  262. addingPackageTimeTotal.Stop();
  263. UnityEditor.EditorUtility.ClearProgressBar();
  264. UnityEditor.EditorApplication.update -= Update; //we're done trying to auto-enable vr
  265. if (packageState == PackageStates.Failed)
  266. {
  267. string failtext = "The Unity Package Manager failed to automatically install the OpenVR package. Please open the Package Manager Window and try to install it manually.";
  268. UnityEditor.EditorUtility.DisplayDialog("SteamVR", failtext, "Ok");
  269. Debug.Log("<b>[SteamVR Setup]</b> " + failtext);
  270. }
  271. }
  272. #else
  273. UnityEditor.EditorApplication.update -= Update;
  274. #endif
  275. #endif
  276. }
  277. }
  278. private static void StartAutoUpdater()
  279. {
  280. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  281. for (int assemblyIndex = 0; assemblyIndex < assemblies.Length; assemblyIndex++)
  282. {
  283. Assembly assembly = assemblies[assemblyIndex];
  284. Type type = assembly.GetType("Unity.XR.OpenVR.OpenVRAutoUpdater");
  285. if (type != null)
  286. {
  287. MethodInfo preinitMethodInfo = type.GetMethod("Start");
  288. if (preinitMethodInfo != null)
  289. {
  290. preinitMethodInfo.Invoke(null, null);
  291. return;
  292. }
  293. }
  294. }
  295. }
  296. private static Type xrMetadataStoreType;
  297. private static MethodInfo GetMethod(string methodName, Type[] parameters = null)
  298. {
  299. if (xrMetadataStoreType == null)
  300. xrMetadataStoreType = SteamVR_Utils.FindType("UnityEditor.XR.Management.Metadata.XRPackageMetadataStore");
  301. if (parameters == null)
  302. return xrMetadataStoreType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic);
  303. else
  304. return xrMetadataStoreType.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic, null, parameters, null);
  305. }
  306. }
  307. }