OVRPlatformTool.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Text.RegularExpressions;
  7. using System.Threading;
  8. using UnityEditor;
  9. using UnityEngine;
  10. using UnityEngine.Networking;
  11. namespace Assets.Oculus.VR.Editor
  12. {
  13. public class OVRPlatformTool : EditorWindow
  14. {
  15. public enum TargetPlatform
  16. {
  17. Rift,
  18. OculusGoGearVR,
  19. Quest,
  20. None,
  21. };
  22. const string urlPlatformUtil =
  23. "https://www.oculus.com/download_app/?id=1076686279105243";
  24. static private Process ovrPlatUtilProcess;
  25. Vector2 commandMenuScroll;
  26. Vector2 debugLogScroll;
  27. static public string log;
  28. private static bool activeProcess = false;
  29. private static bool ranSelfUpdate = false;
  30. private static int retryCount = 0;
  31. private static string appToken;
  32. private const float buttonPadding = 5.0f;
  33. private bool showOptionalCommands = false;
  34. private bool show2DCommands = false;
  35. private bool showExpansionFileCommands = false;
  36. private bool showRedistCommands = false;
  37. private const float INDENT_SPACING = 15f;
  38. private const float SINGLE_LINE_SPACING = 18f;
  39. private const float ASSET_CONFIG_BACKGROUND_PADDING = 10f;
  40. private const float DEFAULT_LABEL_WIDTH = 180f;
  41. private const int MAX_DOWNLOAD_RETRY_COUNT = 2;
  42. private static GUIStyle boldFoldoutStyle;
  43. string[] platformOptions = new string[]
  44. {
  45. "Oculus Rift",
  46. "Oculus Go | Gear VR",
  47. "Oculus Quest"
  48. };
  49. string[] gamepadOptions = new string[]
  50. {
  51. "Off",
  52. "Twinstick",
  53. "Right D Pad",
  54. "Left D Pad"
  55. };
  56. [MenuItem("Oculus/Tools/Oculus Platform Tool")]
  57. static void Init()
  58. {
  59. OVRPlatformTool.log = string.Empty;
  60. // Get existing open window or if none, make a new one:
  61. EditorWindow.GetWindow(typeof(OVRPlatformTool));
  62. // Populate initial target platform value based on OVRDeviceSelector
  63. #if UNITY_ANDROID
  64. if (OVRDeviceSelector.isTargetDeviceQuest)
  65. {
  66. OVRPlatformToolSettings.TargetPlatform = TargetPlatform.Quest;
  67. }
  68. else
  69. {
  70. OVRPlatformToolSettings.TargetPlatform = TargetPlatform.OculusGoGearVR;
  71. }
  72. #else
  73. OVRPlatformToolSettings.TargetPlatform = TargetPlatform.Rift;
  74. #endif
  75. EditorUtility.SetDirty(OVRPlatformToolSettings.Instance);
  76. // Load redist packages by calling list-redists in the CLI
  77. string dataPath = Application.dataPath;
  78. var thread = new Thread(delegate () {
  79. retryCount = 0;
  80. LoadRedistPackages(dataPath);
  81. });
  82. thread.Start();
  83. OVRPlugin.SendEvent("oculus_platform_tool", "show_window");
  84. }
  85. void OnGUI()
  86. {
  87. if (boldFoldoutStyle == null)
  88. {
  89. boldFoldoutStyle = new GUIStyle(EditorStyles.foldout);
  90. boldFoldoutStyle.fontStyle = FontStyle.Bold;
  91. }
  92. EditorGUIUtility.labelWidth = DEFAULT_LABEL_WIDTH;
  93. GUILayout.Label("OVR Platform Tool", EditorStyles.boldLabel);
  94. this.titleContent.text = "OVR Platform Tool";
  95. GUIContent TargetPlatformLabel = new GUIContent("Target Oculus Platform");
  96. OVRPlatformToolSettings.TargetPlatform = (TargetPlatform)MakePopup(TargetPlatformLabel, (int)OVRPlatformToolSettings.TargetPlatform, platformOptions);
  97. SetOVRProjectConfig(OVRPlatformToolSettings.TargetPlatform);
  98. SetDirtyOnGUIChange();
  99. commandMenuScroll = EditorGUILayout.BeginScrollView(commandMenuScroll, GUILayout.Height(Screen.height / 2));
  100. {
  101. // Add the UI Form
  102. EditorGUI.BeginChangeCheck();
  103. GUILayout.Space(15.0f);
  104. // App ID
  105. GUIContent AppIDLabel = new GUIContent("Oculus Application ID [?]: ",
  106. "This AppID will be used when uploading the build.");
  107. OVRPlatformToolSettings.AppID = MakeTextBox(AppIDLabel, OVRPlatformToolSettings.AppID);
  108. // App Token
  109. GUIContent AppTokenLabel = new GUIContent("Oculus App Token [?]: ",
  110. "You can get your app token from your app's Oculus API Dashboard.");
  111. appToken = MakePasswordBox(AppTokenLabel, appToken);
  112. // Release Channel
  113. GUIContent ReleaseChannelLabel = new GUIContent("Release Channel [?]: ",
  114. "Specify the releaes channel of the new build, you can reassign to other channels after upload.");
  115. OVRPlatformToolSettings.ReleaseChannel = MakeTextBox(ReleaseChannelLabel, OVRPlatformToolSettings.ReleaseChannel);
  116. // Releaes Note
  117. GUIContent ReleaseNoteLabel = new GUIContent("Release Note: ");
  118. OVRPlatformToolSettings.ReleaseNote = MakeTextBox(ReleaseNoteLabel, OVRPlatformToolSettings.ReleaseNote);
  119. // Platform specific fields
  120. if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.Rift)
  121. {
  122. GUIContent BuildDirLabel = new GUIContent("Rift Build Directory [?]: ",
  123. "The full path to the directory containing your Rift build files.");
  124. OVRPlatformToolSettings.RiftBuildDirectory = MakeFileDirectoryField(BuildDirLabel, OVRPlatformToolSettings.RiftBuildDirectory,
  125. "Choose Rifle Build Directory");
  126. GUIContent BuildVersionLabel = new GUIContent("Build Version [?]: ",
  127. "The version number shown to users.");
  128. OVRPlatformToolSettings.RiftBuildVersion = MakeTextBox(BuildVersionLabel, OVRPlatformToolSettings.RiftBuildVersion);
  129. GUIContent LaunchFileLabel = new GUIContent("Launch File Path [?]: ",
  130. "The full path to the executable that launches your app.");
  131. OVRPlatformToolSettings.RiftLaunchFile = MakeFileDirectoryField(LaunchFileLabel, OVRPlatformToolSettings.RiftLaunchFile,
  132. "Choose Launch File", true, "exe");
  133. }
  134. else
  135. {
  136. GUIContent ApkPathLabel = new GUIContent("Build APK File Path [?]: ",
  137. "The full path to the APK file.");
  138. OVRPlatformToolSettings.ApkBuildPath = MakeFileDirectoryField(ApkPathLabel, OVRPlatformToolSettings.ApkBuildPath,
  139. "Choose APK File", true, "apk");
  140. if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.OculusGoGearVR)
  141. {
  142. // Go and Gear VR specific fields
  143. }
  144. else if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.Quest)
  145. {
  146. // Quest specific fields
  147. }
  148. }
  149. showOptionalCommands = EditorGUILayout.Foldout(showOptionalCommands, "Optional Commands", boldFoldoutStyle);
  150. if (showOptionalCommands)
  151. {
  152. IncrementIndent();
  153. if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.Rift)
  154. {
  155. // Launch Parameters
  156. GUIContent LaunchParamLabel = new GUIContent("Launch Parameters [?]: ",
  157. "Specifies any arguments passed to the launcher.");
  158. OVRPlatformToolSettings.RiftLaunchParams = MakeTextBox(LaunchParamLabel, OVRPlatformToolSettings.RiftLaunchParams);
  159. GUIContent FirewallExceptionLabel = new GUIContent("Firewall Exception [?]: ",
  160. "Specifies if a Windows Firewall exception is required.");
  161. OVRPlatformToolSettings.RiftFirewallException = MakeToggleBox(FirewallExceptionLabel, OVRPlatformToolSettings.RiftFirewallException);
  162. GUIContent GamepadEmulationLabel = new GUIContent("Gamepad Emulation [?]: ",
  163. "Specifies the type of gamepad emulation used by the Oculus Touch controllers.");
  164. OVRPlatformToolSettings.RiftGamepadEmulation = (OVRPlatformToolSettings.GamepadType)MakePopup(GamepadEmulationLabel, (int)OVRPlatformToolSettings.RiftGamepadEmulation, gamepadOptions);
  165. show2DCommands = EditorGUILayout.Foldout(show2DCommands, "2D", boldFoldoutStyle);
  166. if (show2DCommands)
  167. {
  168. IncrementIndent();
  169. // 2D Launch File
  170. GUIContent LaunchFile2DLabel = new GUIContent("2D Launch File [?]: ",
  171. "The full path to the executable that launches your app in 2D mode.");
  172. OVRPlatformToolSettings.Rift2DLaunchFile = MakeFileDirectoryField(LaunchFile2DLabel, OVRPlatformToolSettings.Rift2DLaunchFile,
  173. "Choose 2D Launch File", true, "exe");
  174. // 2D Launch Parameters
  175. GUIContent LaunchParam2DLabel = new GUIContent("2D Launch Parameters [?]: ",
  176. "Specifies any arguments passed to the launcher in 2D mode.");
  177. OVRPlatformToolSettings.Rift2DLaunchParams = MakeTextBox(LaunchParam2DLabel, OVRPlatformToolSettings.Rift2DLaunchParams);
  178. DecrementIndent();
  179. }
  180. showRedistCommands = EditorGUILayout.Foldout(showRedistCommands, "Redistributable Packages", boldFoldoutStyle);
  181. if (showRedistCommands)
  182. {
  183. IncrementIndent();
  184. for (int i = 0; i < OVRPlatformToolSettings.RiftRedistPackages.Count; i++)
  185. {
  186. GUIContent RedistPackageLabel = new GUIContent(OVRPlatformToolSettings.RiftRedistPackages[i].name);
  187. OVRPlatformToolSettings.RiftRedistPackages[i].include = MakeToggleBox(RedistPackageLabel, OVRPlatformToolSettings.RiftRedistPackages[i].include);
  188. }
  189. DecrementIndent();
  190. }
  191. showExpansionFileCommands = EditorGUILayout.Foldout(showExpansionFileCommands, "Expansion Files", boldFoldoutStyle);
  192. if (showExpansionFileCommands)
  193. {
  194. IncrementIndent();
  195. // Language Pack Directory
  196. GUIContent LanguagePackLabel = new GUIContent("Language Pack Directory [?]: ",
  197. "The full path to the directory containing the language packs");
  198. OVRPlatformToolSettings.LanguagePackDirectory = MakeFileDirectoryField(LanguagePackLabel, OVRPlatformToolSettings.LanguagePackDirectory,
  199. "Choose Language Pack Directory");
  200. }
  201. }
  202. else
  203. {
  204. if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.OculusGoGearVR)
  205. {
  206. // Go and Gear VR specific optional fields
  207. }
  208. else if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.Quest)
  209. {
  210. // Quest specific optional fields
  211. }
  212. showExpansionFileCommands = EditorGUILayout.Foldout(showExpansionFileCommands, "Expansion Files", boldFoldoutStyle);
  213. if (showExpansionFileCommands)
  214. {
  215. IncrementIndent();
  216. // OBB File Path
  217. GUIContent ObbPathLabel = new GUIContent("OBB File Path [?]: ",
  218. "The full path to the OBB file.");
  219. OVRPlatformToolSettings.ObbFilePath = MakeFileDirectoryField(ObbPathLabel, OVRPlatformToolSettings.ObbFilePath,
  220. "Choose OBB File", true, "obb");
  221. }
  222. }
  223. if (showExpansionFileCommands)
  224. {
  225. // Assets Directory
  226. GUIContent AssetsDirLabel = new GUIContent("Assets Directory [?]: ",
  227. "The full path to the directory with DLCs for this build.");
  228. string assetsDirectory = MakeFileDirectoryField(AssetsDirLabel, OVRPlatformToolSettings.AssetsDirectory,
  229. "Choose Assets Directory");
  230. if (assetsDirectory != OVRPlatformToolSettings.AssetsDirectory)
  231. {
  232. OVRPlatformToolSettings.AssetsDirectory = assetsDirectory;
  233. OVRPlatformToolSettings.AssetConfigs.Clear();
  234. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.AssetsDirectory))
  235. {
  236. DirectoryInfo dirInfo = new DirectoryInfo(OVRPlatformToolSettings.AssetsDirectory);
  237. FileInfo[] assetFiles = dirInfo.GetFiles();
  238. foreach (FileInfo f in assetFiles)
  239. {
  240. OVRPlatformToolSettings.AssetConfigs.Add(new AssetConfig(f.Name));
  241. }
  242. }
  243. EditorUtility.SetDirty(OVRPlatformToolSettings.Instance);
  244. }
  245. // Display bordered asset configuration list
  246. GUILayout.Space(3f);
  247. Rect rect = GUILayoutUtility.GetRect(0, GetAssetConfigElementHeight() + (ASSET_CONFIG_BACKGROUND_PADDING * 2),
  248. GUILayout.ExpandWidth(true));
  249. rect.x += (EditorGUI.indentLevel * INDENT_SPACING + 5);
  250. rect.width -= (EditorGUI.indentLevel * INDENT_SPACING + 10);
  251. DrawAssetConfigList(rect);
  252. DecrementIndent();
  253. }
  254. EditorGUI.indentLevel--;
  255. }
  256. if (EditorGUI.EndChangeCheck())
  257. {
  258. EditorUtility.SetDirty(OVRPlatformToolSettings.Instance);
  259. }
  260. }
  261. EditorGUILayout.EndScrollView();
  262. GUILayout.Space(SINGLE_LINE_SPACING);
  263. GUILayout.FlexibleSpace();
  264. // Run OVR Lint Option
  265. EditorGUIUtility.labelWidth = DEFAULT_LABEL_WIDTH;
  266. GUIContent RunOvrLintLabel = new GUIContent("Run OVR Lint (Recommended) [?]: ",
  267. "Run OVR Lint tool to ensure project is optimized for performance and meets Oculus packaging requirement for publishing.");
  268. OVRPlatformToolSettings.RunOvrLint = MakeToggleBox(RunOvrLintLabel, OVRPlatformToolSettings.RunOvrLint);
  269. // Add an Upload button
  270. GUI.enabled = !activeProcess;
  271. GUIContent btnTxt = new GUIContent("Upload");
  272. var rt = GUILayoutUtility.GetRect(btnTxt, GUI.skin.button, GUILayout.ExpandWidth(false));
  273. var btnYPos = rt.center.y;
  274. rt.center = new Vector2(EditorGUIUtility.currentViewWidth / 2 - rt.width / 2 - buttonPadding, btnYPos);
  275. if (GUI.Button(rt, btnTxt, GUI.skin.button))
  276. {
  277. OVRPlugin.SendEvent("oculus_platform_tool", "upload");
  278. OVRPlatformTool.log = string.Empty;
  279. OnUpload(OVRPlatformToolSettings.TargetPlatform);
  280. }
  281. // Add a cancel button
  282. GUI.enabled = activeProcess;
  283. btnTxt = new GUIContent("Cancel");
  284. rt = GUILayoutUtility.GetRect(btnTxt, GUI.skin.button, GUILayout.ExpandWidth(false));
  285. rt.center = new Vector2(EditorGUIUtility.currentViewWidth / 2 + rt.width / 2 + buttonPadding, btnYPos);
  286. if (GUI.Button(rt, btnTxt, GUI.skin.button))
  287. {
  288. if (EditorUtility.DisplayDialog("Cancel Upload Process", "Are you sure you want to cancel the upload process?", "Yes", "No"))
  289. {
  290. if (ovrPlatUtilProcess != null)
  291. {
  292. ovrPlatUtilProcess.Kill();
  293. OVRPlatformTool.log += "Upload process was canceled\n";
  294. }
  295. }
  296. }
  297. GUI.enabled = true;
  298. GUILayout.FlexibleSpace();
  299. GUILayout.Space(SINGLE_LINE_SPACING);
  300. debugLogScroll = EditorGUILayout.BeginScrollView(debugLogScroll);
  301. GUIStyle logBoxStyle = new GUIStyle();
  302. logBoxStyle.margin.left = 5;
  303. logBoxStyle.wordWrap = true;
  304. logBoxStyle.normal.textColor = logBoxStyle.focused.textColor = EditorStyles.label.normal.textColor;
  305. EditorGUILayout.SelectableLabel(OVRPlatformTool.log, logBoxStyle, GUILayout.Height(position.height - 30));
  306. EditorGUILayout.EndScrollView();
  307. }
  308. private void SetOVRProjectConfig(TargetPlatform targetPlatform)
  309. {
  310. #if UNITY_ANDROID
  311. var targetDeviceTypes = new List<OVRProjectConfig.DeviceType>();
  312. if (targetPlatform == TargetPlatform.Quest && !OVRDeviceSelector.isTargetDeviceQuest)
  313. {
  314. targetDeviceTypes.Add(OVRProjectConfig.DeviceType.Quest);
  315. }
  316. else if (targetPlatform == TargetPlatform.OculusGoGearVR && !OVRDeviceSelector.isTargetDeviceGearVrOrGo)
  317. {
  318. targetDeviceTypes.Add(OVRProjectConfig.DeviceType.GearVrOrGo);
  319. }
  320. if (targetDeviceTypes.Count != 0)
  321. {
  322. OVRProjectConfig projectConfig = OVRProjectConfig.GetProjectConfig();
  323. projectConfig.targetDeviceTypes = targetDeviceTypes;
  324. OVRProjectConfig.CommitProjectConfig(projectConfig);
  325. }
  326. #endif
  327. }
  328. private void IncrementIndent()
  329. {
  330. EditorGUI.indentLevel++;
  331. EditorGUIUtility.labelWidth = DEFAULT_LABEL_WIDTH - (EditorGUI.indentLevel * INDENT_SPACING);
  332. }
  333. private void DecrementIndent()
  334. {
  335. EditorGUI.indentLevel--;
  336. EditorGUIUtility.labelWidth = DEFAULT_LABEL_WIDTH - (EditorGUI.indentLevel * INDENT_SPACING);
  337. }
  338. private void OnUpload(TargetPlatform targetPlatform)
  339. {
  340. OVRPlatformTool.log = string.Empty;
  341. SetDirtyOnGUIChange();
  342. var lintCount = 0;
  343. if (OVRPlatformToolSettings.RunOvrLint)
  344. {
  345. lintCount = OVRLint.RunCheck();
  346. }
  347. if (lintCount != 0)
  348. {
  349. OVRPlatformTool.log += lintCount.ToString() + " lint suggestions are found. \n" +
  350. "Please run Oculus\\Tools\\OVR Performance Lint Tool to review and fix lint errors. \n" +
  351. "You can uncheck Run OVR Lint to bypass lint errors. \n";
  352. OVRPlugin.SendEvent("oculus_platform_tool_lint", lintCount.ToString());
  353. }
  354. else
  355. {
  356. // Continue uploading process
  357. ExecuteCommand(targetPlatform);
  358. }
  359. }
  360. static void ExecuteCommand(TargetPlatform targetPlatform)
  361. {
  362. string dataPath = Application.dataPath;
  363. // If we already have a copy of the platform util, check if it needs to be updated
  364. if (!ranSelfUpdate && File.Exists(dataPath + "/Oculus/VR/Editor/Tools/ovr-platform-util.exe"))
  365. {
  366. ranSelfUpdate = true;
  367. activeProcess = true;
  368. var updateThread = new Thread(delegate () {
  369. retryCount = 0;
  370. CheckForUpdate(dataPath);
  371. });
  372. updateThread.Start();
  373. }
  374. var thread = new Thread(delegate () {
  375. // Wait for update process to finish before starting upload process
  376. while (activeProcess)
  377. {
  378. Thread.Sleep(100);
  379. }
  380. retryCount = 0;
  381. Command(targetPlatform, dataPath);
  382. });
  383. thread.Start();
  384. }
  385. private static string CheckForPlatformUtil(string dataPath)
  386. {
  387. string toolDataPath = dataPath + "/Oculus/VR/Editor/Tools";
  388. if (!Directory.Exists(toolDataPath))
  389. {
  390. Directory.CreateDirectory(toolDataPath);
  391. }
  392. string platformUtil = toolDataPath + "/ovr-platform-util.exe";
  393. if (!System.IO.File.Exists(platformUtil))
  394. {
  395. OVRPlugin.SendEvent("oculus_platform_tool", "provision_util");
  396. EditorCoroutine downloadCoroutine = EditorCoroutine.Start(ProvisionPlatformUtil(platformUtil));
  397. while (!downloadCoroutine.GetCompleted()) { }
  398. }
  399. return platformUtil;
  400. }
  401. private static void InitializePlatformUtilProcess(string path, string args)
  402. {
  403. ovrPlatUtilProcess = new Process();
  404. var processInfo = new ProcessStartInfo(path, args);
  405. processInfo.CreateNoWindow = true;
  406. processInfo.UseShellExecute = false;
  407. processInfo.RedirectStandardError = true;
  408. processInfo.RedirectStandardOutput = true;
  409. ovrPlatUtilProcess.StartInfo = processInfo;
  410. ovrPlatUtilProcess.EnableRaisingEvents = true;
  411. }
  412. static void CheckForUpdate(string dataPath)
  413. {
  414. string platformUtilPath = CheckForPlatformUtil(dataPath);
  415. InitializePlatformUtilProcess(platformUtilPath, "self-update");
  416. OVRPlatformTool.log += "Checking for update...\n";
  417. ovrPlatUtilProcess.Exited += new EventHandler(
  418. (s, e) =>
  419. {
  420. if (File.Exists(dataPath + ".ovr-platform-util.exe"))
  421. {
  422. OVRPlatformTool.log += "Cleaning up...\n";
  423. while (File.Exists(dataPath + ".ovr-platform-util.exe")) { }
  424. OVRPlatformTool.log += "Finished updating platform utility.\n";
  425. }
  426. activeProcess = false;
  427. }
  428. );
  429. ovrPlatUtilProcess.OutputDataReceived += new DataReceivedEventHandler(
  430. (s, e) =>
  431. {
  432. if (e.Data != null && e.Data.Length != 0 && !e.Data.Contains("\u001b"))
  433. {
  434. OVRPlatformTool.log += e.Data + "\n";
  435. }
  436. }
  437. );
  438. try
  439. {
  440. ovrPlatUtilProcess.Start();
  441. ovrPlatUtilProcess.BeginOutputReadLine();
  442. }
  443. catch
  444. {
  445. if (ThrowPlatformUtilStartupError(platformUtilPath))
  446. {
  447. CheckForUpdate(dataPath);
  448. }
  449. }
  450. }
  451. static void LoadRedistPackages(string dataPath)
  452. {
  453. // Check / Download the platform util and call list-redists on it
  454. activeProcess = true;
  455. string platformUtilPath = CheckForPlatformUtil(dataPath);
  456. InitializePlatformUtilProcess(platformUtilPath, "list-redists");
  457. OVRPlatformTool.log += "Loading redistributable packages...\n";
  458. List<RedistPackage> redistPacks = new List<RedistPackage>();
  459. ovrPlatUtilProcess.Exited += new EventHandler(
  460. (s, e) =>
  461. {
  462. activeProcess = false;
  463. }
  464. );
  465. ovrPlatUtilProcess.OutputDataReceived += new DataReceivedEventHandler(
  466. (s, e) =>
  467. {
  468. if (e.Data != null && e.Data.Length != 0 && !e.Data.Contains("\u001b") && !e.Data.Contains("ID"))
  469. {
  470. // Get the name / ID pair from the CLI and create a redist package instance
  471. string[] terms = e.Data.Split('|');
  472. if (terms.Length == 2)
  473. {
  474. RedistPackage redistPack = new RedistPackage(terms[1], terms[0]);
  475. redistPacks.Add(redistPack);
  476. }
  477. }
  478. }
  479. );
  480. try
  481. {
  482. ovrPlatUtilProcess.Start();
  483. ovrPlatUtilProcess.BeginOutputReadLine();
  484. ovrPlatUtilProcess.WaitForExit();
  485. if (redistPacks.Count != OVRPlatformToolSettings.RiftRedistPackages.Count)
  486. {
  487. OVRPlatformTool.log += "Successfully updated redistributable packages.\n";
  488. OVRPlatformToolSettings.RiftRedistPackages = redistPacks;
  489. }
  490. else
  491. {
  492. OVRPlatformTool.log += "Redistributable packages up to date.\n";
  493. }
  494. }
  495. catch
  496. {
  497. if (ThrowPlatformUtilStartupError(platformUtilPath))
  498. {
  499. LoadRedistPackages(dataPath);
  500. }
  501. }
  502. }
  503. static void Command(TargetPlatform targetPlatform, string dataPath)
  504. {
  505. string platformUtilPath = CheckForPlatformUtil(dataPath);
  506. string args;
  507. if (genUploadCommand(targetPlatform, out args))
  508. {
  509. activeProcess = true;
  510. InitializePlatformUtilProcess(platformUtilPath, args);
  511. ovrPlatUtilProcess.Exited += new EventHandler(
  512. (s, e) =>
  513. {
  514. activeProcess = false;
  515. }
  516. );
  517. ovrPlatUtilProcess.OutputDataReceived += new DataReceivedEventHandler(
  518. (s, e) =>
  519. {
  520. if (e.Data != null && e.Data.Length != 0 && !e.Data.Contains("\u001b"))
  521. {
  522. OVRPlatformTool.log += e.Data + "\n";
  523. }
  524. }
  525. );
  526. ovrPlatUtilProcess.ErrorDataReceived += new DataReceivedEventHandler(
  527. (s, e) =>
  528. {
  529. OVRPlatformTool.log += e.Data + "\n";
  530. }
  531. );
  532. try
  533. {
  534. ovrPlatUtilProcess.Start();
  535. ovrPlatUtilProcess.BeginOutputReadLine();
  536. ovrPlatUtilProcess.BeginErrorReadLine();
  537. }
  538. catch
  539. {
  540. if (ThrowPlatformUtilStartupError(platformUtilPath))
  541. {
  542. Command(targetPlatform, dataPath);
  543. }
  544. }
  545. }
  546. }
  547. private static bool genUploadCommand(TargetPlatform targetPlatform, out string command)
  548. {
  549. bool success = true;
  550. command = "";
  551. switch (targetPlatform)
  552. {
  553. case TargetPlatform.Rift:
  554. command = "upload-rift-build";
  555. break;
  556. case TargetPlatform.OculusGoGearVR:
  557. command = "upload-mobile-build";
  558. break;
  559. case TargetPlatform.Quest:
  560. command = "upload-quest-build";
  561. break;
  562. default:
  563. OVRPlatformTool.log += "ERROR: Invalid target platform selected";
  564. success = false;
  565. break;
  566. }
  567. // Add App ID
  568. ValidateTextField(AppIDFieldValidator, OVRPlatformToolSettings.AppID, "App ID", ref success);
  569. command += " --app-id \"" + OVRPlatformToolSettings.AppID + "\"";
  570. // Add App Token
  571. ValidateTextField(GenericFieldValidator, appToken, "App Token", ref success);
  572. command += " --app-secret \"" + appToken + "\"";
  573. // Add Platform specific fields
  574. if (targetPlatform == TargetPlatform.Rift)
  575. {
  576. // Add Rift Build Directory
  577. ValidateTextField(DirectoryValidator, OVRPlatformToolSettings.RiftBuildDirectory, "Rift Build Directory", ref success);
  578. command += " --build-dir \"" + OVRPlatformToolSettings.RiftBuildDirectory + "\"";
  579. // Add Rift Launch File
  580. ValidateTextField(FileValidator, OVRPlatformToolSettings.RiftLaunchFile, "Rift Launch File Path", ref success);
  581. command += " --launch-file \"" + OVRPlatformToolSettings.RiftLaunchFile + "\"";
  582. // Add Rift Build Version
  583. ValidateTextField(GenericFieldValidator, OVRPlatformToolSettings.RiftBuildVersion, "Build Version", ref success);
  584. command += " --version \"" + OVRPlatformToolSettings.RiftBuildVersion + "\"";
  585. // Add Rift Launch Parameters
  586. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.RiftLaunchParams))
  587. {
  588. ValidateTextField(LaunchParameterValidator, OVRPlatformToolSettings.RiftLaunchParams, "Launch Parameters", ref success);
  589. command += " --launch_params \"" + OVRPlatformToolSettings.RiftLaunchParams + "\"";
  590. }
  591. // Add 2D Launch File
  592. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.Rift2DLaunchFile))
  593. {
  594. ValidateTextField(FileValidator, OVRPlatformToolSettings.Rift2DLaunchFile, "2D Launch File", ref success);
  595. command += " --launch_file_2d \"" + OVRPlatformToolSettings.Rift2DLaunchFile + "\"";
  596. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.Rift2DLaunchParams))
  597. {
  598. ValidateTextField(LaunchParameterValidator, OVRPlatformToolSettings.Rift2DLaunchParams, "2D Launch Parameters", ref success);
  599. command += " --launch_params_2d \"" + OVRPlatformToolSettings.Rift2DLaunchParams + "\"";
  600. }
  601. }
  602. // Add Firewall Exception
  603. if (OVRPlatformToolSettings.RiftFirewallException)
  604. {
  605. command += " --firewall_exceptions true";
  606. }
  607. // Add Redistributable Packages
  608. List<string> redistCommandIds = new List<string>();
  609. for (int i = 0; i < OVRPlatformToolSettings.RiftRedistPackages.Count; i++)
  610. {
  611. if (OVRPlatformToolSettings.RiftRedistPackages[i].include)
  612. {
  613. redistCommandIds.Add(OVRPlatformToolSettings.RiftRedistPackages[i].id);
  614. }
  615. }
  616. if (redistCommandIds.Count > 0)
  617. {
  618. command += " --redistributables \"" + string.Join(",", redistCommandIds.ToArray()) + "\"";
  619. }
  620. // Add Gamepad Emulation
  621. if (OVRPlatformToolSettings.RiftGamepadEmulation > OVRPlatformToolSettings.GamepadType.OFF &&
  622. OVRPlatformToolSettings.RiftGamepadEmulation <= OVRPlatformToolSettings.GamepadType.LEFT_D_PAD)
  623. {
  624. command += " --gamepad-emulation ";
  625. switch (OVRPlatformToolSettings.RiftGamepadEmulation)
  626. {
  627. case OVRPlatformToolSettings.GamepadType.TWINSTICK: command += "TWINSTICK"; break;
  628. case OVRPlatformToolSettings.GamepadType.RIGHT_D_PAD: command += "RIGHT_D_PAD"; break;
  629. case OVRPlatformToolSettings.GamepadType.LEFT_D_PAD: command += "LEFT_D_PAD"; break;
  630. default: command += "OFF"; break;
  631. }
  632. }
  633. // Add Rift Language Pack Directory
  634. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.LanguagePackDirectory))
  635. {
  636. ValidateTextField(DirectoryValidator, OVRPlatformToolSettings.LanguagePackDirectory, "Language Pack Directory", ref success);
  637. command += " --language_packs_dir \"" + OVRPlatformToolSettings.LanguagePackDirectory + "\"";
  638. }
  639. }
  640. else
  641. {
  642. // Add APK Build Path
  643. ValidateTextField(FileValidator, OVRPlatformToolSettings.ApkBuildPath, "APK Build Path", ref success);
  644. command += " --apk \"" + OVRPlatformToolSettings.ApkBuildPath + "\"";
  645. // Add OBB File Path
  646. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.ObbFilePath))
  647. {
  648. ValidateTextField(FileValidator, OVRPlatformToolSettings.ObbFilePath, "OBB File Path", ref success);
  649. command += " --obb \"" + OVRPlatformToolSettings.ObbFilePath + "\"";
  650. }
  651. if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.OculusGoGearVR)
  652. {
  653. // Go and Gear VR specific commands
  654. }
  655. else if (OVRPlatformToolSettings.TargetPlatform == TargetPlatform.Quest)
  656. {
  657. // Quest specific commands
  658. }
  659. }
  660. // Add Assets Directory
  661. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.AssetsDirectory))
  662. {
  663. ValidateTextField(DirectoryValidator, OVRPlatformToolSettings.AssetsDirectory, "Assets Directory", ref success);
  664. command += " --assets-dir \"" + OVRPlatformToolSettings.AssetsDirectory + "\"";
  665. // Add Asset Configurations
  666. if (OVRPlatformToolSettings.AssetConfigs.Count > 0)
  667. {
  668. List<string> assetConfigs = new List<string>();
  669. for (int i = 0; i < OVRPlatformToolSettings.AssetConfigs.Count; i++)
  670. {
  671. List<string> configParameters = new List<string>();
  672. AssetConfig config = OVRPlatformToolSettings.AssetConfigs[i];
  673. if (config.required)
  674. {
  675. configParameters.Add("\\\"required\\\":true");
  676. }
  677. if (config.type > AssetConfig.AssetType.DEFAULT)
  678. {
  679. string typeCommand = "\\\"type\\\":";
  680. switch (config.type)
  681. {
  682. case AssetConfig.AssetType.LANGUAGE_PACK:
  683. configParameters.Add(typeCommand + "\\\"LANGUAGE_PACK\\\"");
  684. break;
  685. case AssetConfig.AssetType.STORE:
  686. configParameters.Add(typeCommand + "\\\"STORE\\\"");
  687. break;
  688. default:
  689. configParameters.Add(typeCommand + "\\\"DEFAULT\\\"");
  690. break;
  691. }
  692. }
  693. if (!string.IsNullOrEmpty(config.sku))
  694. {
  695. configParameters.Add("\\\"sku\\\":\\\"" + config.sku + "\\\"");
  696. }
  697. if (configParameters.Count > 0)
  698. {
  699. string configString = "\\\"" + config.name + "\\\":{" + string.Join(",", configParameters.ToArray()) + "}";
  700. assetConfigs.Add(configString);
  701. }
  702. }
  703. if (assetConfigs.Count > 0)
  704. {
  705. command += " --asset_files_config {" + string.Join(",", assetConfigs.ToArray()) + "}";
  706. }
  707. }
  708. }
  709. // Add Release Channel
  710. ValidateTextField(GenericFieldValidator, OVRPlatformToolSettings.ReleaseChannel, "Release Channel", ref success);
  711. command += " --channel \"" + OVRPlatformToolSettings.ReleaseChannel + "\"";
  712. // Add Notes
  713. if (!string.IsNullOrEmpty(OVRPlatformToolSettings.ReleaseNote))
  714. {
  715. string sanatizedReleaseNote = OVRPlatformToolSettings.ReleaseNote;
  716. sanatizedReleaseNote = sanatizedReleaseNote.Replace("\"", "\"\"");
  717. command += " --notes \"" + sanatizedReleaseNote + "\"";
  718. }
  719. return success;
  720. }
  721. // Private delegate for text field validation functions
  722. private delegate TSuccess FieldValidatorDelegate<in TText, TError, out TSuccess>(TText text, ref TError error);
  723. // Validate the text using a given field validator function. An error message will be printed if validation fails. Success will ONLY be modified to false if validation fails.
  724. static void ValidateTextField(FieldValidatorDelegate<string, string, bool> fieldValidator, string fieldText, string fieldName, ref bool success)
  725. {
  726. string error = "";
  727. if (!fieldValidator(fieldText, ref error))
  728. {
  729. OVRPlatformTool.log += "ERROR: Please verify that the " + fieldName + " is correct. ";
  730. OVRPlatformTool.log += string.IsNullOrEmpty(error) ? "\n" : error + "\n";
  731. success = false;
  732. }
  733. }
  734. // Checks if the text is null or empty
  735. static bool GenericFieldValidator(string fieldText, ref string error)
  736. {
  737. if (string.IsNullOrEmpty(fieldText))
  738. {
  739. error = "The field is empty.";
  740. return false;
  741. }
  742. return true;
  743. }
  744. // Checks if the App ID contains only numbers
  745. static bool AppIDFieldValidator(string fieldText, ref string error)
  746. {
  747. if (string.IsNullOrEmpty(fieldText))
  748. {
  749. error = "The field is empty.";
  750. return false;
  751. }
  752. else if (!Regex.IsMatch(OVRPlatformToolSettings.AppID, "^[0-9]+$"))
  753. {
  754. error = "The field contains invalid characters.";
  755. return false;
  756. }
  757. return true;
  758. }
  759. // Check that the directory exists
  760. static bool DirectoryValidator(string path, ref string error)
  761. {
  762. if (!Directory.Exists(path))
  763. {
  764. error = "The directory does not exist.";
  765. return false;
  766. }
  767. return true;
  768. }
  769. // Check that the file exists
  770. static bool FileValidator(string path, ref string error)
  771. {
  772. if (!File.Exists(path))
  773. {
  774. error = "The file does not exist.";
  775. return false;
  776. }
  777. return true;
  778. }
  779. // Check if the launch parameter string contains illegal characters
  780. static bool LaunchParameterValidator(string fieldText, ref string error)
  781. {
  782. if (fieldText.Contains("\""))
  783. {
  784. error = "The field contains illegal characters.";
  785. return false;
  786. }
  787. return true;
  788. }
  789. void OnInspectorUpdate()
  790. {
  791. Repaint();
  792. }
  793. private static bool ThrowPlatformUtilStartupError(string utilPath)
  794. {
  795. if (retryCount < MAX_DOWNLOAD_RETRY_COUNT)
  796. {
  797. retryCount++;
  798. OVRPlatformTool.log += "There was a problem starting Oculus Platform Util. Restarting provision process...\n";
  799. File.Delete(utilPath);
  800. return true;
  801. }
  802. else
  803. {
  804. OVRPlatformTool.log += "OVR Platform Tool had a problem with downloading a valid executable after several trys. Please reopen the tool to try again.\n";
  805. return false;
  806. }
  807. }
  808. private string MakeTextBox(GUIContent label, string variable)
  809. {
  810. string result = string.Empty;
  811. EditorGUILayout.BeginHorizontal();
  812. EditorGUILayout.LabelField(label, GUILayout.ExpandWidth(false));
  813. result = EditorGUILayout.TextField(variable);
  814. EditorGUILayout.EndHorizontal();
  815. return result;
  816. }
  817. private string MakePasswordBox(GUIContent label, string variable)
  818. {
  819. string result = string.Empty;
  820. EditorGUILayout.BeginHorizontal();
  821. EditorGUILayout.LabelField(label, GUILayout.ExpandWidth(false));
  822. result = EditorGUILayout.PasswordField(variable);
  823. EditorGUILayout.EndHorizontal();
  824. return result;
  825. }
  826. private bool MakeToggleBox(GUIContent label, bool variable)
  827. {
  828. bool result = false;
  829. EditorGUILayout.BeginHorizontal();
  830. EditorGUILayout.LabelField(label, GUILayout.ExpandWidth(false));
  831. result = EditorGUILayout.Toggle(variable);
  832. EditorGUILayout.EndHorizontal();
  833. return result;
  834. }
  835. private int MakePopup(GUIContent label, int variable, string[] options)
  836. {
  837. int result = 0;
  838. EditorGUILayout.BeginHorizontal();
  839. EditorGUILayout.LabelField(label, GUILayout.ExpandWidth(false));
  840. result = EditorGUILayout.Popup(variable, options);
  841. EditorGUILayout.EndHorizontal();
  842. return result;
  843. }
  844. private string MakeFileDirectoryField(GUIContent label, string variable, string title, bool isFile = false, string extension = "")
  845. {
  846. EditorGUILayout.BeginHorizontal();
  847. EditorGUILayout.LabelField(label, GUILayout.ExpandWidth(false));
  848. Rect rect = GUILayoutUtility.GetRect(0, SINGLE_LINE_SPACING, GUILayout.ExpandWidth(true));
  849. EditorGUI.SelectableLabel(rect, variable);
  850. // Create X button if there is a valid path in the field
  851. string result = variable;
  852. if (!string.IsNullOrEmpty(variable))
  853. {
  854. Color defaultColor = GUI.backgroundColor;
  855. GUI.backgroundColor = new Color(.9f, 0.5f, 0.5f);
  856. rect = GUILayoutUtility.GetRect(SINGLE_LINE_SPACING, SINGLE_LINE_SPACING, GUILayout.ExpandWidth(false));
  857. if (GUI.Button(rect, "X"))
  858. {
  859. result = string.Empty;
  860. }
  861. GUI.backgroundColor = defaultColor;
  862. }
  863. // Create the Choose button to initiate the file explorer
  864. rect = GUILayoutUtility.GetRect(75f, SINGLE_LINE_SPACING, GUILayout.ExpandWidth(false));
  865. if (GUI.Button(rect, "Choose ..."))
  866. {
  867. string newPath = string.Empty;
  868. string path = string.IsNullOrEmpty(variable) ? Application.dataPath : variable;
  869. if (isFile)
  870. {
  871. newPath = EditorUtility.OpenFilePanel(title, path, extension);
  872. }
  873. else
  874. {
  875. newPath = EditorUtility.OpenFolderPanel(title, path, string.Empty);
  876. }
  877. if (newPath.Length > 0)
  878. {
  879. result = newPath;
  880. }
  881. }
  882. GUILayout.Space(5f);
  883. EditorGUILayout.EndHorizontal();
  884. // If the path has changed, deselect the selectable field so that it can update.
  885. if (result != variable)
  886. {
  887. GUIUtility.hotControl = 0;
  888. GUIUtility.keyboardControl = 0;
  889. }
  890. return result;
  891. }
  892. private static void SetDirtyOnGUIChange()
  893. {
  894. if (GUI.changed)
  895. {
  896. EditorUtility.SetDirty(OVRPlatformToolSettings.Instance);
  897. GUI.changed = false;
  898. }
  899. }
  900. private static IEnumerator ProvisionPlatformUtil(string dataPath)
  901. {
  902. UnityEngine.Debug.Log("Started Provisioning Oculus Platform Util");
  903. #if UNITY_2018_3_OR_NEWER
  904. var webRequest = new UnityWebRequest(urlPlatformUtil, UnityWebRequest.kHttpVerbGET);
  905. string path = dataPath;
  906. webRequest.downloadHandler = new DownloadHandlerFile(path);
  907. // WWW request timeout in seconds
  908. webRequest.timeout = 60;
  909. UnityWebRequestAsyncOperation webOp = webRequest.SendWebRequest();
  910. while (!webOp.isDone) { }
  911. if (webRequest.isNetworkError || webRequest.isHttpError)
  912. {
  913. var networkErrorMsg = "Failed to provision Oculus Platform Util\n";
  914. UnityEngine.Debug.LogError(networkErrorMsg);
  915. OVRPlatformTool.log += networkErrorMsg;
  916. }
  917. else
  918. {
  919. OVRPlatformTool.log += "Completed Provisioning Oculus Platform Util\n";
  920. }
  921. SetDirtyOnGUIChange();
  922. yield return webOp;
  923. #else
  924. using (WWW www = new WWW(urlPlatformUtil))
  925. {
  926. float timer = 0;
  927. float timeOut = 60;
  928. yield return www;
  929. while (!www.isDone && timer < timeOut)
  930. {
  931. timer += Time.deltaTime;
  932. if (www.error != null)
  933. {
  934. UnityEngine.Debug.Log("Download error: " + www.error);
  935. break;
  936. }
  937. OVRPlatformTool.log = string.Format("Downloading.. {0:P1}", www.progress);
  938. SetDirtyOnGUIChange();
  939. yield return new WaitForSeconds(1f);
  940. }
  941. if (www.isDone)
  942. {
  943. System.IO.File.WriteAllBytes(dataPath, www.bytes);
  944. OVRPlatformTool.log = "Completed Provisioning Oculus Platform Util\n";
  945. SetDirtyOnGUIChange();
  946. }
  947. }
  948. #endif
  949. }
  950. private static void DrawAssetConfigList(Rect rect)
  951. {
  952. DrawAssetConfigHeader(rect);
  953. DrawAssetConfigBackground(rect);
  954. DrawAssetConfigElement(rect);
  955. }
  956. private static void DrawAssetConfigElement(Rect rect)
  957. {
  958. Rect elementRect = new Rect(rect.x, rect.y + SINGLE_LINE_SPACING + ASSET_CONFIG_BACKGROUND_PADDING / 2,
  959. rect.width, SINGLE_LINE_SPACING);
  960. if (OVRPlatformToolSettings.AssetConfigs.Count > 0)
  961. {
  962. for (int i = 0; i < OVRPlatformToolSettings.AssetConfigs.Count; i++)
  963. {
  964. AssetConfig config = OVRPlatformToolSettings.AssetConfigs[i];
  965. GUIContent fieldLabel;
  966. config.SetFoldoutState(EditorGUI.Foldout(elementRect, config.GetFoldoutState(), config.name, boldFoldoutStyle));
  967. if (config.GetFoldoutState())
  968. {
  969. Rect attributeRect = new Rect(elementRect.x + INDENT_SPACING, elementRect.y + SINGLE_LINE_SPACING,
  970. elementRect.width - INDENT_SPACING - 3f, SINGLE_LINE_SPACING);
  971. // Extra asset config params are disabled for now until CLI supports them
  972. #if !DISABLE_EXTRA_ASSET_CONFIG
  973. fieldLabel = new GUIContent("Required Asset [?]", "Whether or not this asset file is required for the app to run.");
  974. config.required = EditorGUI.Toggle(attributeRect, fieldLabel, config.required);
  975. attributeRect.y += SINGLE_LINE_SPACING;
  976. fieldLabel = new GUIContent("Asset Type [?]", "The asset file type.");
  977. config.type = (AssetConfig.AssetType)EditorGUI.EnumPopup(attributeRect, fieldLabel, config.type);
  978. attributeRect.y += SINGLE_LINE_SPACING;
  979. #endif
  980. fieldLabel = new GUIContent("Asset SKU [?]", "The Oculus store SKU for this asset file.");
  981. config.sku = EditorGUI.TextField(attributeRect, fieldLabel, config.sku);
  982. elementRect.y = attributeRect.y;
  983. }
  984. elementRect.y += SINGLE_LINE_SPACING;
  985. }
  986. }
  987. else
  988. {
  989. EditorGUI.LabelField(elementRect, "No asset files found. Choose a valid assets directory.");
  990. }
  991. }
  992. private static float GetAssetConfigElementHeight()
  993. {
  994. float totalHeight = 0f;
  995. if (OVRPlatformToolSettings.AssetConfigs.Count > 0)
  996. {
  997. for (int i = 0; i < OVRPlatformToolSettings.AssetConfigs.Count; i++)
  998. {
  999. AssetConfig config = OVRPlatformToolSettings.AssetConfigs[i];
  1000. #if !DISABLE_EXTRA_ASSET_CONFIG
  1001. totalHeight += config.GetFoldoutState() ? SINGLE_LINE_SPACING * 4 : SINGLE_LINE_SPACING;
  1002. #else
  1003. totalHeight += config.GetFoldoutState() ? SINGLE_LINE_SPACING * 2 : SINGLE_LINE_SPACING;
  1004. #endif
  1005. }
  1006. }
  1007. else
  1008. {
  1009. totalHeight += SINGLE_LINE_SPACING;
  1010. }
  1011. return totalHeight + ASSET_CONFIG_BACKGROUND_PADDING;
  1012. }
  1013. private static void DrawAssetConfigHeader(Rect rect)
  1014. {
  1015. Rect headerRect = new Rect(rect.x, rect.y, rect.width, SINGLE_LINE_SPACING);
  1016. EditorGUI.DrawRect(headerRect, EditorGUIUtility.isProSkin ? new Color(0.37f, 0.37f, 0.37f) : new Color(0.55f, 0.55f, 0.55f));
  1017. EditorGUI.LabelField(rect, "Asset File Configuration");
  1018. }
  1019. private static void DrawAssetConfigBackground(Rect rect)
  1020. {
  1021. Rect backgroundRect = new Rect(rect.x, rect.y + SINGLE_LINE_SPACING, rect.width, GetAssetConfigElementHeight());
  1022. EditorGUI.DrawRect(backgroundRect, EditorGUIUtility.isProSkin ? new Color(0.3f, 0.3f, 0.3f) : new Color(0.63f, 0.63f, 0.63f));
  1023. }
  1024. class GUIHelper
  1025. {
  1026. public delegate void Worker();
  1027. static void InOut(Worker begin, Worker body, Worker end)
  1028. {
  1029. try
  1030. {
  1031. begin();
  1032. body();
  1033. }
  1034. finally
  1035. {
  1036. end();
  1037. }
  1038. }
  1039. public static void HInset(int pixels, Worker worker)
  1040. {
  1041. InOut(
  1042. () => {
  1043. GUILayout.BeginHorizontal();
  1044. GUILayout.Space(pixels);
  1045. GUILayout.BeginVertical();
  1046. },
  1047. worker,
  1048. () => {
  1049. GUILayout.EndVertical();
  1050. GUILayout.EndHorizontal();
  1051. }
  1052. );
  1053. }
  1054. public delegate T ControlWorker<T>();
  1055. public static T MakeControlWithLabel<T>(GUIContent label, ControlWorker<T> worker)
  1056. {
  1057. EditorGUILayout.BeginHorizontal();
  1058. EditorGUILayout.LabelField(label);
  1059. var result = worker();
  1060. EditorGUILayout.EndHorizontal();
  1061. return result;
  1062. }
  1063. }
  1064. public class EditorCoroutine
  1065. {
  1066. public static EditorCoroutine Start(IEnumerator routine)
  1067. {
  1068. EditorCoroutine coroutine = new EditorCoroutine(routine);
  1069. coroutine.Start();
  1070. return coroutine;
  1071. }
  1072. readonly IEnumerator routine;
  1073. bool completed;
  1074. EditorCoroutine(IEnumerator _routine)
  1075. {
  1076. routine = _routine;
  1077. completed = false;
  1078. }
  1079. void Start()
  1080. {
  1081. EditorApplication.update += Update;
  1082. }
  1083. public void Stop()
  1084. {
  1085. EditorApplication.update -= Update;
  1086. completed = true;
  1087. }
  1088. public bool GetCompleted()
  1089. {
  1090. return completed;
  1091. }
  1092. void Update()
  1093. {
  1094. if (!routine.MoveNext())
  1095. {
  1096. Stop();
  1097. }
  1098. }
  1099. }
  1100. }
  1101. }