Assignment for RMIT Mixed Reality in 2020
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.

443 lines
16 KiB

  1. namespace Oculus.Platform
  2. {
  3. using System;
  4. using System.IO;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using UnityEngine.Networking;
  8. // This classes implements a UI to edit the PlatformSettings class.
  9. // The UI is accessible from a the menu bar via: Oculus Platform -> Edit Settings
  10. [CustomEditor(typeof(PlatformSettings))]
  11. public class OculusPlatformSettingsEditor : Editor
  12. {
  13. private bool isUnityEditorSettingsExpanded;
  14. private bool isBuildSettingsExpanded;
  15. private UnityWebRequest getAccessTokenRequest;
  16. private void OnEnable()
  17. {
  18. isUnityEditorSettingsExpanded = true;
  19. isBuildSettingsExpanded = true;
  20. }
  21. [UnityEditor.MenuItem("Oculus/Platform/Edit Settings")]
  22. public static void Edit()
  23. {
  24. UnityEditor.Selection.activeObject = PlatformSettings.Instance;
  25. }
  26. public override void OnInspectorGUI()
  27. {
  28. //
  29. // Application IDs section
  30. //
  31. EditorGUILayout.LabelField("Application ID:");
  32. GUIContent riftAppIDLabel = new GUIContent("Oculus Rift [?]", "This AppID will be used when building to the Windows target.");
  33. GUIContent mobileAppIDLabel = new GUIContent("Oculus Go/Quest or Gear VR [?]", "This AppID will be used when building to the Android target");
  34. PlatformSettings.AppID = MakeTextBox(riftAppIDLabel, PlatformSettings.AppID);
  35. PlatformSettings.MobileAppID = MakeTextBox(mobileAppIDLabel, PlatformSettings.MobileAppID);
  36. if (GUILayout.Button("Create / Find your app on https://dashboard.oculus.com"))
  37. {
  38. UnityEngine.Application.OpenURL("https://dashboard.oculus.com/");
  39. }
  40. #if UNITY_ANDROID
  41. if (String.IsNullOrEmpty(PlatformSettings.MobileAppID))
  42. {
  43. EditorGUILayout.HelpBox("Please enter a valid Oculus Go/Quest or Gear VR App ID.", MessageType.Error);
  44. }
  45. else
  46. {
  47. var msg = "Configured to connect with App ID " + PlatformSettings.MobileAppID;
  48. EditorGUILayout.HelpBox(msg, MessageType.Info);
  49. }
  50. #else
  51. if (String.IsNullOrEmpty(PlatformSettings.AppID))
  52. {
  53. EditorGUILayout.HelpBox("Please enter a valid Oculus Rift App ID.", MessageType.Error);
  54. }
  55. else
  56. {
  57. var msg = "Configured to connect with App ID " + PlatformSettings.AppID;
  58. EditorGUILayout.HelpBox(msg, MessageType.Info);
  59. }
  60. #endif
  61. EditorGUILayout.Separator();
  62. //
  63. // Unity Editor Settings section
  64. //
  65. isUnityEditorSettingsExpanded = EditorGUILayout.Foldout(isUnityEditorSettingsExpanded, "Unity Editor Settings");
  66. if (isUnityEditorSettingsExpanded)
  67. {
  68. GUIHelper.HInset(6, () =>
  69. {
  70. bool HasTestAccessToken = !String.IsNullOrEmpty(StandalonePlatformSettings.OculusPlatformTestUserAccessToken);
  71. if (PlatformSettings.UseStandalonePlatform)
  72. {
  73. if (!HasTestAccessToken &&
  74. (String.IsNullOrEmpty(StandalonePlatformSettings.OculusPlatformTestUserEmail) ||
  75. String.IsNullOrEmpty(StandalonePlatformSettings.OculusPlatformTestUserPassword)))
  76. {
  77. EditorGUILayout.HelpBox("Please enter a valid user credentials.", MessageType.Error);
  78. }
  79. else
  80. {
  81. var msg = "The Unity editor will use the supplied test user credentials and operate in standalone mode. Some user data will be mocked.";
  82. EditorGUILayout.HelpBox(msg, MessageType.Info);
  83. }
  84. }
  85. else
  86. {
  87. var msg = "The Unity editor will use the user credentials from the Oculus application.";
  88. EditorGUILayout.HelpBox(msg, MessageType.Info);
  89. }
  90. var useStandaloneLabel = "Use Standalone Platform [?]";
  91. var useStandaloneHint = "If this is checked your app will use a debug platform with the User info below. "
  92. + "Otherwise your app will connect to the Oculus Platform. This setting only applies to the Unity Editor";
  93. PlatformSettings.UseStandalonePlatform =
  94. MakeToggle(new GUIContent(useStandaloneLabel, useStandaloneHint), PlatformSettings.UseStandalonePlatform);
  95. GUI.enabled = PlatformSettings.UseStandalonePlatform;
  96. if (!HasTestAccessToken)
  97. {
  98. var emailLabel = "Test User Email: ";
  99. var emailHint = "Test users can be configured at " +
  100. "https://dashboard.oculus.com/organizations/<your org ID>/testusers " +
  101. "however any valid Oculus account email may be used.";
  102. StandalonePlatformSettings.OculusPlatformTestUserEmail =
  103. MakeTextBox(new GUIContent(emailLabel, emailHint), StandalonePlatformSettings.OculusPlatformTestUserEmail);
  104. var passwdLabel = "Test User Password: ";
  105. var passwdHint = "Password associated with the email address.";
  106. StandalonePlatformSettings.OculusPlatformTestUserPassword =
  107. MakePasswordBox(new GUIContent(passwdLabel, passwdHint), StandalonePlatformSettings.OculusPlatformTestUserPassword);
  108. var isLoggingIn = (getAccessTokenRequest != null);
  109. var loginLabel = (!isLoggingIn) ? "Login" : "Logging in...";
  110. GUI.enabled = !isLoggingIn;
  111. if (GUILayout.Button(loginLabel))
  112. {
  113. WWWForm form = new WWWForm();
  114. form.AddField("email", StandalonePlatformSettings.OculusPlatformTestUserEmail);
  115. form.AddField("password", StandalonePlatformSettings.OculusPlatformTestUserPassword);
  116. // Start the WWW request to get the access token
  117. getAccessTokenRequest = UnityWebRequest.Post("https://graph.oculus.com/login", form);
  118. getAccessTokenRequest.SetRequestHeader("Authorization", "Bearer OC|1141595335965881|");
  119. getAccessTokenRequest.SendWebRequest();
  120. EditorApplication.update += GetAccessToken;
  121. }
  122. GUI.enabled = true;
  123. }
  124. else
  125. {
  126. var loggedInMsg = "Currently using the credentials associated with " + StandalonePlatformSettings.OculusPlatformTestUserEmail;
  127. EditorGUILayout.HelpBox(loggedInMsg, MessageType.Info);
  128. var logoutLabel = "Clear Credentials";
  129. if (GUILayout.Button(logoutLabel))
  130. {
  131. StandalonePlatformSettings.OculusPlatformTestUserAccessToken = "";
  132. }
  133. }
  134. GUI.enabled = true;
  135. });
  136. }
  137. EditorGUILayout.Separator();
  138. //
  139. // Build Settings section
  140. //
  141. isBuildSettingsExpanded = EditorGUILayout.Foldout(isBuildSettingsExpanded, "Build Settings");
  142. if (isBuildSettingsExpanded)
  143. {
  144. GUIHelper.HInset(6, () => {
  145. if (!PlayerSettings.virtualRealitySupported)
  146. {
  147. EditorGUILayout.HelpBox("VR Support isn't enabled in the Player Settings", MessageType.Warning);
  148. }
  149. else
  150. {
  151. EditorGUILayout.HelpBox("VR Support is enabled", MessageType.Info);
  152. }
  153. PlayerSettings.virtualRealitySupported = MakeToggle(new GUIContent("Virtual Reality Support"), PlayerSettings.virtualRealitySupported);
  154. PlayerSettings.bundleVersion = MakeTextBox(new GUIContent("Bundle Version"), PlayerSettings.bundleVersion);
  155. #if UNITY_5_3 || UNITY_5_4 || UNITY_5_5
  156. PlayerSettings.bundleIdentifier = MakeTextBox(new GUIContent("Bundle Identifier"), PlayerSettings.bundleIdentifier);
  157. #else
  158. BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
  159. PlayerSettings.SetApplicationIdentifier(
  160. buildTargetGroup,
  161. MakeTextBox(
  162. new GUIContent("Bundle Identifier"),
  163. PlayerSettings.GetApplicationIdentifier(buildTargetGroup)));
  164. #endif
  165. bool canEnableARM64Support = false;
  166. #if UNITY_2018_1_OR_NEWER
  167. canEnableARM64Support = true;
  168. #endif
  169. if (!canEnableARM64Support)
  170. {
  171. var msg = "Update your Unity Editor to 2018.1.x or newer to enable Arm64 support";
  172. EditorGUILayout.HelpBox(msg, MessageType.Warning);
  173. if (IsArm64PluginPlatformEnabled())
  174. {
  175. DisablePluginPlatform(PluginPlatform.Android64);
  176. }
  177. }
  178. else
  179. {
  180. if (!IsArm64PluginPlatformEnabled())
  181. {
  182. EnablePluginPlatform(PluginPlatform.Android64);
  183. }
  184. }
  185. GUI.enabled = true;
  186. });
  187. }
  188. EditorGUILayout.Separator();
  189. }
  190. // Asyncronously fetch the access token with the given credentials
  191. private void GetAccessToken()
  192. {
  193. if (getAccessTokenRequest != null && getAccessTokenRequest.isDone)
  194. {
  195. // Clear the password
  196. StandalonePlatformSettings.OculusPlatformTestUserPassword = "";
  197. if (String.IsNullOrEmpty(getAccessTokenRequest.error))
  198. {
  199. var Response = JsonUtility.FromJson<OculusStandalonePlatformResponse>(getAccessTokenRequest.downloadHandler.text);
  200. StandalonePlatformSettings.OculusPlatformTestUserAccessToken = Response.access_token;
  201. }
  202. GUI.changed = true;
  203. EditorApplication.update -= GetAccessToken;
  204. getAccessTokenRequest.Dispose();
  205. getAccessTokenRequest = null;
  206. }
  207. }
  208. private string MakeTextBox(GUIContent label, string variable)
  209. {
  210. return GUIHelper.MakeControlWithLabel(label, () => {
  211. GUI.changed = false;
  212. var result = EditorGUILayout.TextField(variable);
  213. SetDirtyOnGUIChange();
  214. return result;
  215. });
  216. }
  217. private string MakePasswordBox(GUIContent label, string variable)
  218. {
  219. return GUIHelper.MakeControlWithLabel(label, () => {
  220. GUI.changed = false;
  221. var result = EditorGUILayout.PasswordField(variable);
  222. SetDirtyOnGUIChange();
  223. return result;
  224. });
  225. }
  226. private bool MakeToggle(GUIContent label, bool variable)
  227. {
  228. return GUIHelper.MakeControlWithLabel(label, () => {
  229. GUI.changed = false;
  230. var result = EditorGUILayout.Toggle(variable);
  231. SetDirtyOnGUIChange();
  232. return result;
  233. });
  234. }
  235. private void SetDirtyOnGUIChange()
  236. {
  237. if (GUI.changed)
  238. {
  239. EditorUtility.SetDirty(PlatformSettings.Instance);
  240. GUI.changed = false;
  241. }
  242. }
  243. // TODO: Merge this with core utilities plugin updater functionality. Piggybacking here to avoid an orphaned delete in the future.
  244. private const string PluginSubPathAndroid32 = @"/Plugins/Android32/libovrplatformloader.so";
  245. private const string PluginSubPathAndroid64 = @"/Plugins/Android64/libovrplatformloader.so";
  246. private const string PluginDisabledSuffix = @".disabled";
  247. public enum PluginPlatform
  248. {
  249. Android32,
  250. Android64
  251. }
  252. private static string GetCurrentProjectPath()
  253. {
  254. return Directory.GetParent(UnityEngine.Application.dataPath).FullName;
  255. }
  256. private static string GetPlatformRootPath()
  257. {
  258. // use the path to OculusPluginUpdaterStub as a relative path anchor point
  259. var so = ScriptableObject.CreateInstance(typeof(OculusPluginUpdaterStub));
  260. var script = MonoScript.FromScriptableObject(so);
  261. string assetPath = AssetDatabase.GetAssetPath(script);
  262. string editorDir = Directory.GetParent(assetPath).FullName;
  263. string platformDir = Directory.GetParent(editorDir).FullName;
  264. return platformDir;
  265. }
  266. private static string GetPlatformPluginPath(PluginPlatform platform)
  267. {
  268. string path = GetPlatformRootPath();
  269. switch (platform)
  270. {
  271. case PluginPlatform.Android32:
  272. path += PluginSubPathAndroid32;
  273. break;
  274. case PluginPlatform.Android64:
  275. path += PluginSubPathAndroid64;
  276. break;
  277. default:
  278. throw new ArgumentException("Attempted to enable platform support for unsupported platform: " + platform);
  279. }
  280. return path;
  281. }
  282. //[UnityEditor.MenuItem("Oculus/Platform/EnforcePluginPlatformSettings")]
  283. public static void EnforcePluginPlatformSettings()
  284. {
  285. EnforcePluginPlatformSettings(PluginPlatform.Android32);
  286. EnforcePluginPlatformSettings(PluginPlatform.Android64);
  287. }
  288. public static void EnforcePluginPlatformSettings(PluginPlatform platform)
  289. {
  290. string path = GetPlatformPluginPath(platform);
  291. if (!Directory.Exists(path) && !File.Exists(path))
  292. {
  293. path += PluginDisabledSuffix;
  294. }
  295. if ((Directory.Exists(path)) || (File.Exists(path)))
  296. {
  297. string basePath = GetCurrentProjectPath();
  298. string relPath = path.Substring(basePath.Length + 1);
  299. PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter;
  300. if (pi == null)
  301. {
  302. return;
  303. }
  304. // Disable support for all platforms, then conditionally enable desired support below
  305. pi.SetCompatibleWithEditor(false);
  306. pi.SetCompatibleWithAnyPlatform(false);
  307. pi.SetCompatibleWithPlatform(BuildTarget.Android, false);
  308. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false);
  309. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false);
  310. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false);
  311. #if !UNITY_2019_2_OR_NEWER
  312. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux, false);
  313. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneLinuxUniversal, false);
  314. #endif
  315. #if UNITY_2017_3_OR_NEWER
  316. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, false);
  317. #else
  318. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSXUniversal, false);
  319. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSXIntel, false);
  320. pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSXIntel64, false);
  321. #endif
  322. switch (platform)
  323. {
  324. case PluginPlatform.Android32:
  325. pi.SetCompatibleWithPlatform(BuildTarget.Android, true);
  326. pi.SetPlatformData(BuildTarget.Android, "CPU", "ARMv7");
  327. break;
  328. case PluginPlatform.Android64:
  329. pi.SetCompatibleWithPlatform(BuildTarget.Android, true);
  330. pi.SetPlatformData(BuildTarget.Android, "CPU", "ARM64");
  331. break;
  332. default:
  333. throw new ArgumentException("Attempted to enable platform support for unsupported platform: " + platform);
  334. }
  335. AssetDatabase.ImportAsset(relPath, ImportAssetOptions.ForceUpdate);
  336. AssetDatabase.SaveAssets();
  337. AssetDatabase.Refresh();
  338. AssetDatabase.SaveAssets();
  339. }
  340. }
  341. public static bool IsArm64PluginPlatformEnabled()
  342. {
  343. string path = GetPlatformPluginPath(PluginPlatform.Android64);
  344. bool pathAlreadyExists = Directory.Exists(path) || File.Exists(path);
  345. return pathAlreadyExists;
  346. }
  347. public static void EnablePluginPlatform(PluginPlatform platform)
  348. {
  349. string path = GetPlatformPluginPath(platform);
  350. string disabledPath = path + PluginDisabledSuffix;
  351. bool pathAlreadyExists = Directory.Exists(path) || File.Exists(path);
  352. bool disabledPathDoesNotExist = !Directory.Exists(disabledPath) && !File.Exists(disabledPath);
  353. if (pathAlreadyExists || disabledPathDoesNotExist)
  354. {
  355. return;
  356. }
  357. string basePath = GetCurrentProjectPath();
  358. string relPath = path.Substring(basePath.Length + 1);
  359. string relDisabledPath = relPath + PluginDisabledSuffix;
  360. AssetDatabase.MoveAsset(relDisabledPath, relPath);
  361. AssetDatabase.ImportAsset(relPath, ImportAssetOptions.ForceUpdate);
  362. AssetDatabase.SaveAssets();
  363. AssetDatabase.Refresh();
  364. AssetDatabase.SaveAssets();
  365. // Force reserialization of platform settings meta data
  366. EnforcePluginPlatformSettings(platform);
  367. }
  368. public static void DisablePluginPlatform(PluginPlatform platform)
  369. {
  370. string path = GetPlatformPluginPath(platform);
  371. string disabledPath = path + PluginDisabledSuffix;
  372. bool pathDoesNotExist = !Directory.Exists(path) && !File.Exists(path);
  373. bool disabledPathAlreadyExists = Directory.Exists(disabledPath) || File.Exists(disabledPath);
  374. if (pathDoesNotExist || disabledPathAlreadyExists)
  375. {
  376. return;
  377. }
  378. string basePath = GetCurrentProjectPath();
  379. string relPath = path.Substring(basePath.Length + 1);
  380. string relDisabledPath = relPath + PluginDisabledSuffix;
  381. AssetDatabase.MoveAsset(relPath, relDisabledPath);
  382. AssetDatabase.ImportAsset(relDisabledPath, ImportAssetOptions.ForceUpdate);
  383. AssetDatabase.SaveAssets();
  384. AssetDatabase.Refresh();
  385. AssetDatabase.SaveAssets();
  386. }
  387. }
  388. }