Seven is the number.
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.

1061 lines
30 KiB

4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Text.RegularExpressions;
  5. using System.Threading;
  6. using Bolt.Utils;
  7. using UnityEditor;
  8. using UnityEngine;
  9. using Debug = UnityEngine.Debug;
  10. [InitializeOnLoad]
  11. public partial class BoltWizardWindow : EditorWindow
  12. {
  13. BoltSetupStage currentStage = BoltSetupStage.Intro;
  14. static Stopwatch watch = new Stopwatch();
  15. static Boolean? Ready;
  16. static Single? FirstCall;
  17. private static volatile bool requestingAppId = false;
  18. static bool RunCompiler;
  19. static String FirstStartupKey
  20. {
  21. get { return "$Bolt$First$Startup$Wizard/" + BoltNetwork.Version; }
  22. }
  23. static Vector2 WindowSize;
  24. static Vector2 WindowPosition;
  25. static string AppIdOrEmail = "";
  26. [NonSerialized] Func<bool> beforeNextCallback;
  27. [NonSerialized] Dictionary<BoltInstalls, BoltPackage> packageInfo;
  28. [NonSerialized] int ButtonWidth;
  29. [NonSerialized] int NavMenuWidth;
  30. [NonSerialized] string ReleaseHistoryHeader;
  31. [NonSerialized] List<string> ReleaseHistoryTextAdded;
  32. [NonSerialized] List<string> ReleaseHistoryTextChanged;
  33. [NonSerialized] List<string> ReleaseHistoryTextFixed;
  34. [NonSerialized] List<string> ReleaseHistoryTextRemoved;
  35. // GUI
  36. [NonSerialized] Texture2D introIcon;
  37. [NonSerialized] Texture2D releaseIcon;
  38. [NonSerialized] Texture2D photonCloudIcon;
  39. [NonSerialized] Texture2D boltIcon;
  40. [NonSerialized] Texture2D activeIcon;
  41. [NonSerialized] Texture2D inactiveIcon;
  42. [NonSerialized] Texture2D bugtrackerIcon;
  43. [NonSerialized] GUIContent bugtrackerHeader;
  44. [NonSerialized] GUIContent bugtrackerText;
  45. [NonSerialized] Texture2D discordIcon;
  46. [NonSerialized] GUIContent discordHeader;
  47. [NonSerialized] GUIContent discordText;
  48. [NonSerialized] Texture2D documentationIcon;
  49. [NonSerialized] GUIContent documentationHeader;
  50. [NonSerialized] GUIContent documentationText;
  51. [NonSerialized] Texture2D reviewIcon;
  52. [NonSerialized] GUIContent reviewHeader;
  53. [NonSerialized] GUIContent reviewText;
  54. [NonSerialized] Texture2D samplesIcon;
  55. [NonSerialized] GUIStyle iconSection;
  56. [NonSerialized] GUIStyle stepStyle;
  57. [NonSerialized] GUIStyle headerStyle;
  58. [NonSerialized] GUIStyle headerLabel;
  59. [NonSerialized] GUIStyle headerLargeLabel;
  60. [NonSerialized] GUIStyle textLabel;
  61. [NonSerialized] GUIStyle centerInputText;
  62. [NonSerialized] GUIStyle minimalButton;
  63. [NonSerialized] GUIStyle simpleButton;
  64. [NonSerialized] GUIStyle introStyle;
  65. [NonSerialized] Vector2 scrollPosition;
  66. static BoltWizardWindow()
  67. {
  68. EditorApplication.update -= ShowWizardWindow;
  69. EditorApplication.update += ShowWizardWindow;
  70. WindowPosition = new Vector2(100, 100);
  71. }
  72. static void ShowWizardWindow()
  73. {
  74. if (FirstCall.HasValue == false)
  75. {
  76. FirstCall = Time.realtimeSinceStartup;
  77. return;
  78. }
  79. if ((Time.realtimeSinceStartup - FirstCall.Value) > 1)
  80. {
  81. if (!EditorPrefs.GetBool(FirstStartupKey, false))
  82. {
  83. Open();
  84. }
  85. EditorApplication.update -= ShowWizardWindow;
  86. }
  87. }
  88. [MenuItem("Bolt/Wizard", priority = 100)]
  89. public static void Open()
  90. {
  91. if (Application.isPlaying)
  92. {
  93. return;
  94. }
  95. BoltWizardWindow window = GetWindow<BoltWizardWindow>(true, BoltWizardText.WINDOW_TITLE, true);
  96. window.position = new Rect(WindowPosition, WindowSize);
  97. window.Show();
  98. watch.Start();
  99. }
  100. static void ReOpen()
  101. {
  102. if (Ready.HasValue && Ready.Value == false)
  103. {
  104. Open();
  105. }
  106. EditorApplication.update -= ReOpen;
  107. }
  108. void OnEnable()
  109. {
  110. WindowSize = new Vector2(600, 600);
  111. minSize = WindowSize;
  112. NavMenuWidth = 210;
  113. ButtonWidth = 120;
  114. Ready = false;
  115. beforeNextCallback = null;
  116. // Pre-load Release History
  117. PrepareReleaseHistoryText();
  118. }
  119. void OnDestroy()
  120. {
  121. if (!EditorPrefs.GetBool(FirstStartupKey, false))
  122. {
  123. if (!EditorUtility.DisplayDialog(BoltWizardText.CLOSE_MSG_TITLE,
  124. BoltWizardText.CLOSE_MSG_QUESTION, "Yes", "Back"))
  125. {
  126. EditorApplication.update += ReOpen;
  127. }
  128. }
  129. Ready = false;
  130. }
  131. void InitContent()
  132. {
  133. if (Ready.HasValue && Ready.Value)
  134. {
  135. return;
  136. }
  137. introIcon = Resources.Load<Texture2D>("icons_welcome/information");
  138. releaseIcon = Resources.Load<Texture2D>("icons_welcome/documentation");
  139. photonCloudIcon = Resources.Load<Texture2D>("PhotonCloudIcon");
  140. boltIcon = Resources.Load<Texture2D>("BoltIcon");
  141. activeIcon = Resources.Load<Texture2D>("icons_welcome/bullet_green");
  142. inactiveIcon = Resources.Load<Texture2D>("icons_welcome/bullet_black");
  143. Texture2D texture = new Texture2D(1, 1);
  144. texture.SetPixel(0, 0, Color.gray);
  145. texture.Apply();
  146. Color headerTextColor = EditorGUIUtility.isProSkin
  147. ? new Color(0xf2 / 255f, 0xad / 255f, 0f)
  148. : new Color(30 / 255f, 99 / 255f, 183 / 255f);
  149. Color commonTextColor = EditorGUIUtility.isProSkin ? Color.white : Color.black;
  150. introStyle = new GUIStyle(EditorStyles.helpBox)
  151. {
  152. fontSize = 15,
  153. padding = new RectOffset(10, 10, 10, 10),
  154. normal =
  155. {
  156. textColor = commonTextColor
  157. }
  158. };
  159. stepStyle = new GUIStyle(EditorStyles.helpBox)
  160. {
  161. padding = new RectOffset(10, 10, 10, 10),
  162. margin = new RectOffset(0, 0, 5, 0),
  163. normal =
  164. {
  165. textColor = commonTextColor
  166. }
  167. };
  168. headerLabel = new GUIStyle(EditorStyles.boldLabel)
  169. {
  170. padding = new RectOffset(10, 0, 0, 0),
  171. margin = new RectOffset(),
  172. normal =
  173. {
  174. textColor = commonTextColor
  175. }
  176. };
  177. headerStyle = new GUIStyle(EditorStyles.boldLabel)
  178. {
  179. fontSize = 14,
  180. margin = new RectOffset(),
  181. padding = new RectOffset(10, 0, 0, 0),
  182. normal =
  183. {
  184. textColor = commonTextColor
  185. }
  186. };
  187. headerLargeLabel = new GUIStyle(EditorStyles.boldLabel)
  188. {
  189. padding = new RectOffset(10, 0, 0, 0),
  190. margin = new RectOffset(),
  191. fontSize = 18,
  192. normal =
  193. {
  194. textColor = headerTextColor
  195. }
  196. };
  197. textLabel = new GUIStyle()
  198. {
  199. wordWrap = true,
  200. margin = new RectOffset(),
  201. padding = new RectOffset(10, 0, 0, 0),
  202. normal =
  203. {
  204. textColor = commonTextColor
  205. }
  206. };
  207. centerInputText = new GUIStyle(GUI.skin.textField)
  208. {
  209. alignment = TextAnchor.MiddleCenter,
  210. fontSize = 12,
  211. fixedHeight = 26
  212. };
  213. minimalButton = new GUIStyle(EditorStyles.miniButton)
  214. {
  215. fixedWidth = 130
  216. };
  217. simpleButton = new GUIStyle(GUI.skin.button)
  218. {
  219. fontSize = 12,
  220. padding = new RectOffset(10, 10, 10, 10)
  221. };
  222. iconSection = new GUIStyle
  223. {
  224. margin = new RectOffset(0, 0, 0, 0)
  225. };
  226. discordIcon = Resources.Load<Texture2D>("icons_welcome/community");
  227. discordText = new GUIContent(BoltWizardText.DISCORD_TEXT);
  228. discordHeader = new GUIContent(BoltWizardText.DISCORD_HEADER);
  229. bugtrackerIcon = Resources.Load<Texture2D>("icons_welcome/bugtracker");
  230. bugtrackerText = new GUIContent(BoltWizardText.BUGTRACKER_TEXT);
  231. bugtrackerHeader = new GUIContent(BoltWizardText.BUGTRACKER_HEADER);
  232. documentationIcon = Resources.Load<Texture2D>("icons_welcome/documentation");
  233. documentationText = new GUIContent(BoltWizardText.DOCUMENTATION_TEXT);
  234. documentationHeader = new GUIContent(BoltWizardText.DOCUMENTATION_HEADER);
  235. reviewIcon = Resources.Load<Texture2D>("icons_welcome/comments");
  236. reviewText = new GUIContent(BoltWizardText.REVIEW_TEXT);
  237. reviewHeader = new GUIContent(BoltWizardText.REVIEW_HEADER);
  238. samplesIcon = Resources.Load<Texture2D>("icons_welcome/samples");
  239. // Package List
  240. packageInfo = new Dictionary<BoltInstalls, BoltPackage>
  241. {
  242. {
  243. BoltInstalls.Core,
  244. new BoltPackage()
  245. {
  246. name = "bolt_install",
  247. title = "Core Package",
  248. description = "Install core bolt package",
  249. installTest = MainPackageInstalled,
  250. packageFlags = PackageFlags.RunInitialSetup
  251. }
  252. },
  253. // {
  254. // BoltInstalls.Mobile,
  255. // new BoltPackage()
  256. // {
  257. // name = "bolt_mobile_plugins",
  258. // title = "Mobile Plugins",
  259. // installTest = MobilePackageInstalled,
  260. // description = "Install iOS / Android socket plugins"
  261. // }
  262. // },
  263. {
  264. BoltInstalls.XB1,
  265. new BoltPackage()
  266. {
  267. name = "bolt_xb1",
  268. title = "XBox One",
  269. installTest = XB1PackageInstalled,
  270. description = "Install XB1 support"
  271. }
  272. },
  273. {
  274. BoltInstalls.PS4,
  275. new BoltPackage()
  276. {
  277. name = "bolt_ps4",
  278. title = "Playstation 4",
  279. installTest = PS4PackageInstalled,
  280. description = "Install PS4 support"
  281. }
  282. },
  283. {
  284. BoltInstalls.Samples,
  285. new BoltPackage()
  286. {
  287. name = "bolt_samples",
  288. title = "Samples",
  289. description = "Install bolt samples",
  290. installTest = SamplesPackageInstalled,
  291. packageFlags = PackageFlags.WarnForProjectOverwrite
  292. }
  293. }
  294. };
  295. // App ID
  296. if (string.IsNullOrEmpty(BoltRuntimeSettings.instance.photonAppId))
  297. {
  298. AppIdOrEmail = "";
  299. }
  300. else if (IsAppId(BoltRuntimeSettings.instance.photonAppId))
  301. {
  302. AppIdOrEmail = BoltRuntimeSettings.instance.photonAppId;
  303. }
  304. Ready = true;
  305. RunCompiler = false;
  306. }
  307. void OnGUI()
  308. {
  309. try
  310. {
  311. InitContent();
  312. WindowPosition = position.position;
  313. EditorGUILayout.BeginVertical();
  314. DrawHeader();
  315. // Content
  316. EditorGUILayout.BeginHorizontal();
  317. // Nav menu
  318. EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.MaxWidth(NavMenuWidth),
  319. GUILayout.MinWidth(NavMenuWidth));
  320. DrawNavMenu();
  321. EditorGUILayout.EndVertical();
  322. // Main Content
  323. EditorGUILayout.BeginVertical(EditorStyles.helpBox);
  324. DrawContent();
  325. EditorGUILayout.EndVertical();
  326. EditorGUILayout.EndHorizontal();
  327. EditorGUILayout.EndVertical();
  328. if (GUI.changed)
  329. {
  330. Save();
  331. }
  332. }
  333. catch (Exception)
  334. {
  335. // ignored
  336. }
  337. }
  338. private void DrawContent()
  339. {
  340. switch (currentStage)
  341. {
  342. case BoltSetupStage.Intro:
  343. DrawIntro();
  344. break;
  345. case BoltSetupStage.ReleaseHistory:
  346. DrawReleaseHistory();
  347. break;
  348. case BoltSetupStage.Photon:
  349. DrawSetupPhoton();
  350. break;
  351. case BoltSetupStage.Bolt:
  352. DrawSetupBolt();
  353. break;
  354. case BoltSetupStage.Support:
  355. DrawSupport();
  356. break;
  357. }
  358. GUILayout.FlexibleSpace();
  359. DrawFooter();
  360. }
  361. private void DrawIntro()
  362. {
  363. GUILayout.BeginVertical();
  364. GUILayout.Label(BoltWizardText.WIZARD_INTRO, introStyle);
  365. if (GUILayout.Button("Visit Getting Started Documentation", simpleButton))
  366. {
  367. OpenURL("https://doc.photonengine.com/en-us/bolt/")();
  368. }
  369. if (GUILayout.Button("Leave a review", simpleButton))
  370. {
  371. OpenURL("https://assetstore.unity.com/packages/tools/network/photon-bolt-free-127156")();
  372. }
  373. GUILayout.EndVertical();
  374. }
  375. private void DrawSetupBolt()
  376. {
  377. DrawInputWithLabel("Bolt Setup", () =>
  378. {
  379. GUILayout.BeginVertical();
  380. GUILayout.Space(5);
  381. GUILayout.Label(BoltWizardText.PACKAGES, textLabel);
  382. GUILayout.EndVertical();
  383. }, false);
  384. GUILayout.Space(15);
  385. DrawInstallOption(BoltInstalls.Core);
  386. EditorGUI.BeginDisabledGroup(!IsInstalled(BoltInstalls.Core));
  387. // SAMPLES
  388. DrawInstallOption(BoltInstalls.Samples);
  389. scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
  390. // // MOBILE
  391. // DrawInstallOption(BoltInstalls.Mobile);
  392. // XB1
  393. DrawInstallOption(BoltInstalls.XB1);
  394. // PS4
  395. DrawInstallOption(BoltInstalls.PS4);
  396. EditorGUILayout.EndScrollView();
  397. EditorGUI.EndDisabledGroup();
  398. // Action
  399. if (beforeNextCallback == null)
  400. {
  401. beforeNextCallback = () =>
  402. {
  403. if (!IsInstalled(BoltInstalls.Core))
  404. {
  405. ShowNotification(new GUIContent("You must install at least the Bolt Core package."));
  406. return false;
  407. }
  408. return true;
  409. };
  410. }
  411. }
  412. private void DrawReleaseHistory()
  413. {
  414. DrawInputWithLabel(string.Format("Version Changelog: {0}", ReleaseHistoryHeader), () =>
  415. {
  416. GUILayout.BeginVertical();
  417. GUILayout.Space(5);
  418. scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUIStyle.none, GUILayout.ExpandHeight(true),
  419. GUILayout.ExpandWidth(true));
  420. DrawReleaseHistoryItem("Added:", ReleaseHistoryTextAdded);
  421. DrawReleaseHistoryItem("Changed:", ReleaseHistoryTextChanged);
  422. DrawReleaseHistoryItem("Fixed:", ReleaseHistoryTextFixed);
  423. DrawReleaseHistoryItem("Removed:", ReleaseHistoryTextRemoved);
  424. GUILayout.EndScrollView();
  425. GUILayout.EndVertical();
  426. }, false, labelSize: 300);
  427. }
  428. private void DrawReleaseHistoryItem(string label, List<string> items)
  429. {
  430. if (items != null && items.Count > 0)
  431. {
  432. DrawInputWithLabel(label, () =>
  433. {
  434. GUILayout.BeginVertical();
  435. GUILayout.Space(5);
  436. foreach (var text in items)
  437. {
  438. GUILayout.Label(string.Format("- {0}.", text), textLabel);
  439. }
  440. GUILayout.EndVertical();
  441. }, false, true, 200);
  442. }
  443. }
  444. private void DrawSetupPhoton()
  445. {
  446. DrawInputWithLabel("Photon Cloud Setup", () =>
  447. {
  448. GUILayout.BeginVertical();
  449. GUILayout.Space(5);
  450. GUILayout.Label(BoltWizardText.PHOTON, textLabel);
  451. GUILayout.EndVertical();
  452. GUILayout.BeginHorizontal();
  453. GUILayout.Label(BoltWizardText.PHOTON_DASH, textLabel);
  454. if (GUILayout.Button("Visit Dashboard", minimalButton))
  455. {
  456. OpenURL("https://dashboard.photonengine.com/")();
  457. }
  458. GUILayout.EndHorizontal();
  459. }, false);
  460. GUILayout.Space(15);
  461. BoltRuntimeSettings settings = BoltRuntimeSettings.instance;
  462. DrawInputWithLabel("Photon Bolt App ID or Email", () =>
  463. {
  464. GUILayout.BeginVertical();
  465. AppIdOrEmail = EditorGUILayout.TextField(AppIdOrEmail, centerInputText);
  466. GUILayout.EndVertical();
  467. }, false, true, 300);
  468. DrawInputWithLabel("Region",
  469. () =>
  470. {
  471. settings.photonCloudRegionIndex = EditorGUILayout.Popup(settings.photonCloudRegionIndex,
  472. BoltRuntimeSettings.photonCloudRegions);
  473. }, true, true);
  474. DrawInputWithLabel("NAT Punchthrough Enabled",
  475. () => { settings.photonUsePunch = BoltEditorGUI.Toggle(settings.photonUsePunch); }, true, true);
  476. // Action
  477. if (beforeNextCallback == null)
  478. {
  479. beforeNextCallback = () =>
  480. {
  481. if (requestingAppId)
  482. {
  483. BoltLog.Info("Please, wait until your request for a new AppID finishes.");
  484. return false;
  485. }
  486. if (AccountService.IsValidEmail(AppIdOrEmail))
  487. {
  488. try
  489. {
  490. EditorUtility.DisplayProgressBar(BoltWizardText.CONNECTION_TITLE,
  491. BoltWizardText.CONNECTION_INFO, 0.5f);
  492. BoltLog.Info("Starting request");
  493. requestingAppId = new AccountService().RegisterByEmail(
  494. AppIdOrEmail,
  495. new List<ServiceTypes>() {ServiceTypes.Bolt},
  496. (response) =>
  497. {
  498. if (response.ReturnCode == AccountServiceReturnCodes.Success)
  499. {
  500. var appKey = response.ApplicationIds[((int) ServiceTypes.Bolt).ToString()];
  501. settings.photonAppId = appKey;
  502. AppIdOrEmail = appKey;
  503. BoltLog.Info("You new App ID: {0}", AppIdOrEmail);
  504. }
  505. else
  506. {
  507. BoltLog.Warn(
  508. "It was not possible to process your request, please go to the Photon Cloud Dashboard.");
  509. BoltLog.Warn("Return Code: {0}",
  510. AccountServiceReturnCodes.ReturnCodes[response.ReturnCode]);
  511. }
  512. requestingAppId = false;
  513. EditorUtility.ClearProgressBar();
  514. }, (err) =>
  515. {
  516. BoltLog.Error(err);
  517. requestingAppId = false;
  518. EditorUtility.ClearProgressBar();
  519. });
  520. if (requestingAppId)
  521. {
  522. BoltLog.Info("Requesting your new App ID");
  523. }
  524. else
  525. {
  526. BoltLog.Warn(
  527. "It was not possible to process your request, please go to the Photon Cloud Dashboard.");
  528. EditorUtility.ClearProgressBar();
  529. }
  530. }
  531. catch (Exception ex)
  532. {
  533. EditorUtility.DisplayDialog("Error", ex.Message, "ok");
  534. }
  535. }
  536. else if (IsAppId(AppIdOrEmail))
  537. {
  538. settings.photonAppId = AppIdOrEmail;
  539. return true;
  540. }
  541. else
  542. {
  543. ShowNotification(new GUIContent("Please specify a valid Photon Bolt App ID or Email."));
  544. }
  545. return false;
  546. };
  547. }
  548. }
  549. private void DrawSupport()
  550. {
  551. DrawInputWithLabel("Bolt Support", () =>
  552. {
  553. GUILayout.BeginVertical();
  554. GUILayout.Space(5);
  555. GUILayout.Label(BoltWizardText.SUPPORT, textLabel);
  556. GUILayout.EndVertical();
  557. }, false);
  558. GUILayout.Space(15);
  559. DrawStepOption(discordIcon, discordHeader, discordText,
  560. callback: OpenURL("https://discord.gg/0ya6ZpOvnShSCtbb"));
  561. DrawStepOption(bugtrackerIcon, bugtrackerHeader, bugtrackerText,
  562. callback: OpenURL("https://github.com/BoltEngine/Bolt-Tracker"));
  563. DrawStepOption(documentationIcon, documentationHeader, documentationText,
  564. callback: OpenURL("https://doc.photonengine.com/en-us/bolt/current/setup/overview"));
  565. DrawStepOption(reviewIcon, reviewHeader, reviewText,
  566. callback: OpenURL("https://assetstore.unity.com/packages/tools/network/photon-bolt-free-127156"));
  567. // Action
  568. if (beforeNextCallback == null)
  569. {
  570. beforeNextCallback = () =>
  571. {
  572. RunCompiler = EditorUtility.DisplayDialog(BoltWizardText.FINISH_TITLE, BoltWizardText.FINISH_QUESTION,
  573. "Yes", "No");
  574. return true;
  575. };
  576. }
  577. }
  578. private void DrawNavMenu()
  579. {
  580. GUILayout.Space(5);
  581. DrawMenuHeader("Installation Steps");
  582. GUILayout.Space(10);
  583. DrawStepOption(introIcon, new GUIContent("Bolt Wizard Intro"),
  584. active: currentStage ==
  585. BoltSetupStage.Intro);
  586. DrawStepOption(releaseIcon, new GUIContent("Release History"),
  587. active: currentStage ==
  588. BoltSetupStage.ReleaseHistory);
  589. DrawStepOption(photonCloudIcon, new GUIContent("Photon Cloud"),
  590. active: currentStage ==
  591. BoltSetupStage.Photon);
  592. DrawStepOption(boltIcon, new GUIContent("Bolt"),
  593. active: currentStage ==
  594. BoltSetupStage.Bolt);
  595. DrawStepOption(discordIcon, new GUIContent("Support"),
  596. active: currentStage ==
  597. BoltSetupStage.Support);
  598. GUILayout.FlexibleSpace();
  599. GUILayout.Label(BoltNetwork.CurrentVersion, textLabel);
  600. GUILayout.Space(5);
  601. }
  602. void DrawHeader()
  603. {
  604. GUILayout.BeginHorizontal();
  605. GUILayout.FlexibleSpace();
  606. GUILayout.Label(Resources.Load<Texture2D>("BoltLogo"), GUILayout.Width(200), GUILayout.Height(109));
  607. GUILayout.FlexibleSpace();
  608. GUILayout.EndHorizontal();
  609. }
  610. void DrawFooter()
  611. {
  612. GUILayout.BeginHorizontal();
  613. GUILayout.FlexibleSpace();
  614. EditorGUI.BeginDisabledGroup((int) currentStage == 1);
  615. #if !BOLT_CLOUD
  616. if (currentStage == BoltSetupStage.Photon)
  617. {
  618. if (GUILayout.Button("Skip", GUILayout.Width(ButtonWidth)))
  619. {
  620. NextStep();
  621. beforeNextCallback = null;
  622. }
  623. }
  624. #endif
  625. if (GUILayout.Button("Back", GUILayout.Width(ButtonWidth)))
  626. {
  627. beforeNextCallback = null;
  628. BackStep();
  629. }
  630. EditorGUI.EndDisabledGroup();
  631. var nextLabel = "Next";
  632. switch (currentStage)
  633. {
  634. case BoltSetupStage.Photon:
  635. nextLabel = AccountService.IsValidEmail(AppIdOrEmail) ? "Register by Email" : nextLabel;
  636. break;
  637. case BoltSetupStage.Support:
  638. nextLabel = "Done";
  639. break;
  640. default:
  641. nextLabel = "Next";
  642. break;
  643. }
  644. if (GUILayout.Button(nextLabel, GUILayout.Width(ButtonWidth)))
  645. {
  646. if (beforeNextCallback == null || beforeNextCallback())
  647. {
  648. if (currentStage == BoltSetupStage.Support)
  649. {
  650. EditorPrefs.SetBool(FirstStartupKey, true);
  651. Close();
  652. if (RunCompiler)
  653. {
  654. BoltMenuItems.RunCompiler();
  655. }
  656. }
  657. NextStep();
  658. beforeNextCallback = null;
  659. }
  660. }
  661. GUILayout.Space(5);
  662. GUILayout.EndHorizontal();
  663. GUILayout.Space(5);
  664. }
  665. // Utils
  666. private void Save()
  667. {
  668. if (watch.ElapsedMilliseconds > 5000)
  669. {
  670. watch.Reset();
  671. watch.Start();
  672. EditorUtility.SetDirty(BoltRuntimeSettings.instance);
  673. AssetDatabase.SaveAssets();
  674. }
  675. }
  676. void DrawMenuHeader(String text)
  677. {
  678. GUILayout.BeginHorizontal();
  679. GUILayout.FlexibleSpace();
  680. GUILayout.Label(text, headerLargeLabel);
  681. GUILayout.FlexibleSpace();
  682. GUILayout.EndHorizontal();
  683. }
  684. void DrawInputWithLabel(String label, Action gui, bool horizontal = true, bool box = false, int labelSize = 220)
  685. {
  686. GUILayout.Space(10);
  687. if (horizontal)
  688. {
  689. if (box)
  690. {
  691. GUILayout.BeginHorizontal(stepStyle);
  692. }
  693. else
  694. {
  695. GUILayout.BeginHorizontal();
  696. }
  697. }
  698. else
  699. {
  700. if (box)
  701. {
  702. GUILayout.BeginVertical(stepStyle);
  703. }
  704. else
  705. {
  706. GUILayout.BeginVertical();
  707. }
  708. }
  709. GUILayout.Label(label, headerStyle, GUILayout.Width(labelSize));
  710. //GUILayout.Space(5);
  711. gui();
  712. GUILayout.Space(5);
  713. if (horizontal)
  714. {
  715. GUILayout.EndHorizontal();
  716. }
  717. else
  718. {
  719. GUILayout.EndVertical();
  720. }
  721. }
  722. void DrawInstallOption(BoltInstalls install)
  723. {
  724. BoltPackage package = packageInfo[install];
  725. Action action = () =>
  726. {
  727. if (package.installTest())
  728. {
  729. ShowNotification(new GUIContent("Package already installed"));
  730. return;
  731. }
  732. Install(package);
  733. };
  734. bool packageExists = PackageExists(package.name);
  735. Action ignoredAction;
  736. if (packageExists == true)
  737. {
  738. ignoredAction = () => { ShowNotification(new GUIContent("One of the dependencies is missing")); };
  739. }
  740. else
  741. {
  742. if (install == BoltInstalls.Core)
  743. {
  744. ignoredAction = () =>
  745. {
  746. ShowNotification(new GUIContent("Bolt Core is no longer required. You are ready to go."));
  747. };
  748. }
  749. else
  750. {
  751. ignoredAction = () =>
  752. {
  753. ShowNotification(new GUIContent("Please contact us at developer@photonengine.com"));
  754. };
  755. }
  756. EditorGUI.BeginDisabledGroup(true);
  757. }
  758. DrawStepOption(samplesIcon, new GUIContent(package.title), new GUIContent(package.description),
  759. package.installTest(), action, ignoredAction);
  760. if (packageExists == false)
  761. {
  762. EditorGUI.EndDisabledGroup();
  763. }
  764. }
  765. void DrawStepOption(Texture2D icon, GUIContent header, GUIContent description = null, bool? active = null,
  766. Action callback = null, Action ignoredCallback = null)
  767. {
  768. GUILayout.BeginHorizontal(stepStyle);
  769. if (icon != null)
  770. {
  771. GUILayout.Label(icon, iconSection, GUILayout.Width(32), GUILayout.Height(32));
  772. }
  773. var height = icon != null ? 32 : 16;
  774. GUILayout.BeginVertical(GUILayout.MinHeight(height));
  775. GUILayout.FlexibleSpace();
  776. GUILayout.Label(header, headerLabel, GUILayout.MinWidth(120));
  777. if (description != null)
  778. {
  779. GUILayout.Label(description, textLabel);
  780. }
  781. GUILayout.FlexibleSpace();
  782. GUILayout.EndVertical();
  783. if (active == true)
  784. {
  785. GUILayout.Label(activeIcon, iconSection, GUILayout.Width(height), GUILayout.Height(height));
  786. }
  787. else if (active == false)
  788. {
  789. GUILayout.Label(inactiveIcon, iconSection, GUILayout.Width(height), GUILayout.Height(height));
  790. }
  791. GUILayout.EndHorizontal();
  792. if (callback != null)
  793. {
  794. var rect = GUILayoutUtility.GetLastRect();
  795. EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link);
  796. if (rect.Contains(Event.current.mousePosition))
  797. {
  798. if (Event.current.type == EventType.MouseDown)
  799. {
  800. callback();
  801. GUIUtility.ExitGUI();
  802. }
  803. else if (Event.current.type == EventType.Ignore && Event.current.rawType == EventType.MouseDown)
  804. {
  805. if (ignoredCallback != null)
  806. {
  807. ignoredCallback();
  808. }
  809. }
  810. }
  811. }
  812. }
  813. void NextStep()
  814. {
  815. currentStage += (int) currentStage < Enum.GetValues(typeof(BoltSetupStage)).Length ? 1 : 0;
  816. }
  817. void BackStep()
  818. {
  819. currentStage -= (int) currentStage > 1 ? 1 : 0;
  820. }
  821. bool IsInstalled(params BoltInstalls[] installs)
  822. {
  823. foreach (var pack in installs)
  824. {
  825. if (!packageInfo[pack].installTest())
  826. {
  827. return false;
  828. }
  829. }
  830. return true;
  831. }
  832. void Install(BoltPackage package)
  833. {
  834. string packageName = package.name;
  835. PackageFlags flags = package.packageFlags;
  836. if ((flags & PackageFlags.WarnForProjectOverwrite) == PackageFlags.WarnForProjectOverwrite)
  837. {
  838. if (ProjectExists())
  839. {
  840. if (EditorUtility.DisplayDialog("Warning",
  841. "Importing this package will overwrite the existing bolt project file that contains all your states, events, etc. Are you sure?",
  842. "Yes", "No") == false)
  843. {
  844. return;
  845. }
  846. }
  847. }
  848. if ((flags & PackageFlags.RunInitialSetup) == PackageFlags.RunInitialSetup)
  849. {
  850. InitialSetup();
  851. }
  852. AssetDatabase.ImportPackage(PackagePath(packageName), false);
  853. currentStage = BoltSetupStage.Bolt;
  854. }
  855. }