SettingsWindow.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. namespace SRDebugger.Editor
  2. {
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Globalization;
  7. using System.Linq;
  8. #if !DISABLE_SRDEBUGGER
  9. using SRDebugger.Internal;
  10. #endif
  11. using SRF;
  12. using UnityEditor;
  13. using UnityEditorInternal;
  14. using UnityEngine;
  15. class SRDebuggerSettingsWindow : EditorWindow
  16. {
  17. [MenuItem(SRDebugEditorPaths.SettingsMenuItemPath)]
  18. public static void Open()
  19. {
  20. GetWindowWithRect<SRDebuggerSettingsWindow>(new Rect(0, 0, 449, 520), true, "SRDebugger - Settings",
  21. true);
  22. }
  23. #if DISABLE_SRDEBUGGER
  24. private bool _isWorking;
  25. private void OnGUI()
  26. {
  27. SRDebugEditor.DrawDisabledWindowGui(ref _isWorking);
  28. }
  29. #else
  30. private enum ProfilerAlignment
  31. {
  32. TopLeft = 0,
  33. TopRight = 1,
  34. BottomLeft = 2,
  35. BottomRight = 3
  36. }
  37. private enum OptionsAlignment
  38. {
  39. TopLeft = 0,
  40. TopRight = 1,
  41. BottomLeft = 2,
  42. BottomRight = 3,
  43. TopCenter = 6,
  44. BottomCenter = 7
  45. }
  46. private string _currentEntryCode;
  47. private bool _enableTabChange = true;
  48. private Tabs _selectedTab;
  49. private bool _showBugReportSignupForm;
  50. private string[] _tabs = Enum.GetNames(typeof (Tabs)).Select(s => s.Replace('_', ' ')).ToArray();
  51. [NonSerialized] private bool _hasError;
  52. [NonSerialized] private string _error;
  53. private bool _isAppearing = true;
  54. private void Reset()
  55. {
  56. if (_isAppearing)
  57. {
  58. return;
  59. }
  60. SRInternalEditorUtil.EditorSettings.ClearCache();
  61. _hasError = false;
  62. }
  63. private bool SettingsReady(out Settings settings)
  64. {
  65. if (!_hasError)
  66. {
  67. string message;
  68. SRInternalEditorUtil.SettingsResult result =
  69. SRInternalEditorUtil.EditorSettings.TryGetOrCreate(out settings, out message);
  70. switch (result)
  71. {
  72. case SRInternalEditorUtil.SettingsResult.Loaded:
  73. {
  74. // Perform on-load logic
  75. _currentEntryCode = GetEntryCodeString(settings);
  76. if (string.IsNullOrEmpty(settings.ApiKey))
  77. {
  78. _showBugReportSignupForm = true;
  79. }
  80. return true;
  81. }
  82. case SRInternalEditorUtil.SettingsResult.Cache:
  83. {
  84. return true;
  85. }
  86. case SRInternalEditorUtil.SettingsResult.Waiting:
  87. {
  88. EditorGUILayout.Space();
  89. GUILayout.Label(message, SRInternalEditorUtil.Styles.ParagraphLabel);
  90. return false;
  91. }
  92. case SRInternalEditorUtil.SettingsResult.Error:
  93. {
  94. _error = message;
  95. _hasError = true;
  96. break;
  97. }
  98. }
  99. }
  100. // Display Error UI
  101. settings = null;
  102. EditorGUILayout.Space();
  103. GUILayout.Label("An error has occurred while loading settings.");
  104. EditorGUILayout.Space();
  105. GUILayout.Label("Message: ", EditorStyles.boldLabel);
  106. GUILayout.Label(_error, SRInternalEditorUtil.Styles.ParagraphLabel);
  107. EditorGUILayout.Space();
  108. if (GUILayout.Button("Open Integrity Checker"))
  109. {
  110. SRIntegrityCheckWindow.Open();
  111. }
  112. if (GUILayout.Button("Retry"))
  113. {
  114. Reset();
  115. Repaint();
  116. }
  117. return false;
  118. }
  119. private void OnGUI()
  120. {
  121. _isAppearing = false;
  122. // Draw header area
  123. SRInternalEditorUtil.BeginDrawBackground();
  124. SRInternalEditorUtil.DrawLogo(SRInternalEditorUtil.GetLogo());
  125. SRInternalEditorUtil.EndDrawBackground();
  126. // Draw header/content divider
  127. EditorGUILayout.BeginVertical(SRInternalEditorUtil.Styles.SettingsHeaderBoxStyle);
  128. EditorGUILayout.EndVertical();
  129. Settings settings;
  130. if (!SettingsReady(out settings))
  131. {
  132. return;
  133. }
  134. // Draw tab buttons
  135. var rect = EditorGUILayout.BeginVertical(GUI.skin.box);
  136. --rect.width;
  137. var height = 18;
  138. EditorGUI.BeginChangeCheck();
  139. EditorGUI.BeginDisabledGroup(!_enableTabChange);
  140. for (var i = 0; i < _tabs.Length; ++i)
  141. {
  142. var xStart = Mathf.RoundToInt(i*rect.width/_tabs.Length);
  143. var xEnd = Mathf.RoundToInt((i + 1)*rect.width/_tabs.Length);
  144. var pos = new Rect(rect.x + xStart, rect.y, xEnd - xStart, height);
  145. if (GUI.Toggle(pos, (int) _selectedTab == i, new GUIContent(_tabs[i]), EditorStyles.toolbarButton))
  146. {
  147. _selectedTab = (Tabs) i;
  148. }
  149. }
  150. GUILayoutUtility.GetRect(10f, height);
  151. EditorGUI.EndDisabledGroup();
  152. if (EditorGUI.EndChangeCheck())
  153. {
  154. _scrollPosition = Vector2.zero;
  155. GUIUtility.keyboardControl = 0;
  156. }
  157. // Draw selected tab
  158. switch (_selectedTab)
  159. {
  160. case Tabs.General:
  161. DrawTabGeneral(settings);
  162. break;
  163. case Tabs.Layout:
  164. DrawTabLayout(settings);
  165. break;
  166. case Tabs.Bug_Reporter:
  167. DrawTabBugReporter(settings);
  168. break;
  169. case Tabs.Shortcuts:
  170. DrawTabShortcuts(settings);
  171. break;
  172. case Tabs.Advanced:
  173. DrawTabAdvanced(settings);
  174. break;
  175. }
  176. EditorGUILayout.EndVertical();
  177. // Display rating prompt and link buttons
  178. EditorGUILayout.LabelField(SRDebugEditorStrings.Current.SettingsRateBoxContents, EditorStyles.miniLabel);
  179. SRInternalEditorUtil.DrawFooterLayout(position.width);
  180. if (GUI.changed)
  181. {
  182. EditorUtility.SetDirty(settings);
  183. }
  184. }
  185. private enum Tabs
  186. {
  187. General,
  188. Layout,
  189. Bug_Reporter,
  190. Shortcuts,
  191. Advanced
  192. }
  193. #region Tabs
  194. private void DrawTabGeneral(Settings settings)
  195. {
  196. GUILayout.Label("Loading", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  197. EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
  198. if (GUILayout.Toggle(!settings.IsEnabled, "Disabled", SRInternalEditorUtil.Styles.RadioButton))
  199. {
  200. settings.IsEnabled = false;
  201. }
  202. GUILayout.Label("Do not load SRDebugger until a manual call to <i>SRDebug.Init()</i>.",
  203. SRInternalEditorUtil.Styles.RadioButtonDescription);
  204. var msg = "Automatic (recommended)";
  205. if (GUILayout.Toggle(settings.IsEnabled, msg,
  206. SRInternalEditorUtil.Styles.RadioButton))
  207. {
  208. settings.IsEnabled = true;
  209. }
  210. GUILayout.Label("SRDebugger loads automatically when your game starts.",
  211. SRInternalEditorUtil.Styles.RadioButtonDescription);
  212. EditorGUILayout.EndVertical();
  213. GUILayout.Label("Panel Access", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  214. EditorGUILayout.HelpBox("Configure trigger location in the layout tab.", MessageType.None, true);
  215. settings.EnableTrigger =
  216. (Settings.TriggerEnableModes)
  217. EditorGUILayout.EnumPopup(new GUIContent("Trigger Mode"),
  218. settings.EnableTrigger);
  219. EditorGUI.BeginDisabledGroup(settings.EnableTrigger == Settings.TriggerEnableModes.Off);
  220. settings.TriggerBehaviour =
  221. (Settings.TriggerBehaviours)
  222. EditorGUILayout.EnumPopup(new GUIContent("Trigger Behaviour"),
  223. settings.TriggerBehaviour);
  224. settings.ErrorNotification =
  225. EditorGUILayout.Toggle(
  226. new GUIContent("Error Notification",
  227. "Display a notification on the panel trigger when an error is printed to the log."),
  228. settings.ErrorNotification);
  229. EditorGUI.EndDisabledGroup();
  230. EditorGUILayout.Space();
  231. settings.DefaultTab =
  232. (DefaultTabs)
  233. EditorGUILayout.EnumPopup(
  234. new GUIContent("Default Tab", SRDebugEditorStrings.Current.SettingsDefaultTabTooltip),
  235. settings.DefaultTab);
  236. EditorGUILayout.Space();
  237. EditorGUILayout.BeginHorizontal();
  238. settings.RequireCode = EditorGUILayout.Toggle(new GUIContent("Require Entry Code"),
  239. settings.RequireCode);
  240. EditorGUI.BeginDisabledGroup(!settings.RequireCode);
  241. settings.RequireEntryCodeEveryTime = EditorGUILayout.Toggle(new GUIContent("...Every Time", "Require the user to enter the PIN every time they access the debug panel."),
  242. settings.RequireEntryCodeEveryTime);
  243. EditorGUILayout.EndHorizontal();
  244. var newCode = EditorGUILayout.TextField("Entry Code", _currentEntryCode);
  245. if (newCode != _currentEntryCode)
  246. {
  247. // Strip out alpha numeric chars
  248. newCode = new string(newCode.Where(char.IsDigit).ToArray());
  249. // Max length = 4
  250. newCode = newCode.Substring(0, Mathf.Min(4, newCode.Length));
  251. if (newCode.Length == 4)
  252. {
  253. UpdateEntryCode(settings, newCode);
  254. }
  255. }
  256. EditorGUI.EndDisabledGroup();
  257. EditorGUILayout.Space();
  258. settings.AutomaticallyShowCursor =
  259. EditorGUILayout.Toggle(
  260. new GUIContent("Show Cursor",
  261. "Automatically set the cursor to visible when the debug panel is opened, and revert when closed."),
  262. settings.AutomaticallyShowCursor);
  263. // Expand content area to fit all available space
  264. GUILayout.FlexibleSpace();
  265. }
  266. private void DrawTabLayout(Settings settings)
  267. {
  268. GUILayout.Label("Pinned Tool Positions", SRInternalEditorUtil.Styles.HeaderLabel);
  269. EditorGUILayout.BeginHorizontal();
  270. GUILayout.FlexibleSpace();
  271. var rect = GUILayoutUtility.GetRect(360, 210);
  272. GUILayout.FlexibleSpace();
  273. EditorGUILayout.EndHorizontal();
  274. SRInternalEditorUtil.DrawLayoutPreview(rect, settings);
  275. EditorGUILayout.BeginHorizontal();
  276. {
  277. EditorGUILayout.BeginVertical();
  278. GUILayout.Label("Console", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  279. settings.ConsoleAlignment =
  280. (ConsoleAlignment) EditorGUILayout.EnumPopup(settings.ConsoleAlignment);
  281. EditorGUILayout.EndVertical();
  282. }
  283. {
  284. EditorGUI.BeginDisabledGroup(settings.EnableTrigger == Settings.TriggerEnableModes.Off);
  285. EditorGUILayout.BeginVertical();
  286. GUILayout.Label("Entry Trigger", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  287. settings.TriggerPosition =
  288. (PinAlignment) EditorGUILayout.EnumPopup(settings.TriggerPosition);
  289. EditorGUILayout.EndVertical();
  290. EditorGUI.EndDisabledGroup();
  291. }
  292. EditorGUILayout.EndHorizontal();
  293. EditorGUILayout.BeginHorizontal();
  294. {
  295. EditorGUILayout.BeginVertical();
  296. GUILayout.Label("Profiler", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  297. settings.ProfilerAlignment =
  298. (PinAlignment) EditorGUILayout.EnumPopup((ProfilerAlignment)settings.ProfilerAlignment);
  299. EditorGUILayout.EndVertical();
  300. }
  301. {
  302. EditorGUILayout.BeginVertical();
  303. GUILayout.Label("Options", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  304. settings.OptionsAlignment =
  305. (PinAlignment) EditorGUILayout.EnumPopup((OptionsAlignment)settings.OptionsAlignment);
  306. EditorGUILayout.EndVertical();
  307. }
  308. EditorGUILayout.EndHorizontal();
  309. // Expand content area to fit all available space
  310. GUILayout.FlexibleSpace();
  311. }
  312. private bool _enableButton;
  313. private void DrawTabBugReporter(Settings settings)
  314. {
  315. if (_showBugReportSignupForm)
  316. {
  317. DrawBugReportSignupForm(settings);
  318. return;
  319. }
  320. GUILayout.Label("Bug Reporter", SRInternalEditorUtil.Styles.HeaderLabel);
  321. EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(settings.ApiKey));
  322. settings.EnableBugReporter = EditorGUILayout.Toggle("Enable Bug Reporter",
  323. settings.EnableBugReporter);
  324. settings.EnableBugReportScreenshot = EditorGUILayout.Toggle("Take Screenshot",
  325. settings.EnableBugReportScreenshot);
  326. EditorGUI.EndDisabledGroup();
  327. EditorGUILayout.BeginHorizontal();
  328. settings.ApiKey = EditorGUILayout.TextField("API Key", settings.ApiKey);
  329. if (GUILayout.Button("Verify", GUILayout.ExpandWidth(false)))
  330. {
  331. EditorUtility.DisplayDialog("Verify API Key", ApiSignup.Verify(settings.ApiKey), "OK");
  332. }
  333. EditorGUILayout.EndHorizontal();
  334. EditorGUILayout.Space();
  335. GUILayout.Label(
  336. "If you need to change your account email address, or have any other questions or concerns, please email us at contact@stompyrobot.uk.",
  337. SRInternalEditorUtil.Styles.ParagraphLabel);
  338. GUILayout.FlexibleSpace();
  339. if (!string.IsNullOrEmpty(settings.ApiKey))
  340. {
  341. GUILayout.Label("Reset", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  342. GUILayout.Label("Click the button below to clear the API key and show the signup form.",
  343. SRInternalEditorUtil.Styles.ParagraphLabel);
  344. EditorGUILayout.BeginHorizontal();
  345. _enableButton = EditorGUILayout.Toggle("Enable Button", _enableButton, GUILayout.ExpandWidth(false));
  346. EditorGUI.BeginDisabledGroup(!_enableButton);
  347. if (GUILayout.Button("Reset"))
  348. {
  349. settings.ApiKey = null;
  350. settings.EnableBugReporter = false;
  351. _enableButton = false;
  352. _showBugReportSignupForm = true;
  353. }
  354. EditorGUI.EndDisabledGroup();
  355. EditorGUILayout.EndHorizontal();
  356. EditorGUILayout.Space();
  357. }
  358. else
  359. {
  360. if (GUILayout.Button("Show Signup Form"))
  361. {
  362. _showBugReportSignupForm = true;
  363. }
  364. }
  365. }
  366. private string _invoiceNumber;
  367. private string _emailAddress;
  368. private bool _agreeLegal;
  369. private string _errorMessage;
  370. private void DrawBugReportSignupForm(Settings settings)
  371. {
  372. var isWeb = false;
  373. #if UNITY_WEBPLAYER
  374. EditorGUILayout.HelpBox("Signup form is not available when build target is Web Player.", MessageType.Error);
  375. isWeb = true;
  376. #endif
  377. EditorGUI.BeginDisabledGroup(isWeb || !_enableTabChange);
  378. GUILayout.Label("Signup Form", SRInternalEditorUtil.Styles.HeaderLabel);
  379. GUILayout.Label(
  380. "SRDebugger requires a free API key to enable the bug reporter system. This form will acquire one for you.",
  381. SRInternalEditorUtil.Styles.ParagraphLabel);
  382. if (
  383. SRInternalEditorUtil.ClickableLabel(
  384. "Already got an API key? <color={0}>Click here</color>.".Fmt(SRInternalEditorUtil.Styles.LinkColour),
  385. SRInternalEditorUtil.Styles.RichTextLabel))
  386. {
  387. _showBugReportSignupForm = false;
  388. Repaint();
  389. }
  390. EditorGUILayout.Space();
  391. GUILayout.Label("Invoice/Order Number", EditorStyles.boldLabel);
  392. GUILayout.Label(
  393. "Enter the order number from your Asset Store purchase email.",
  394. EditorStyles.miniLabel);
  395. _invoiceNumber = EditorGUILayout.TextField(_invoiceNumber);
  396. EditorGUILayout.Space();
  397. GUILayout.Label("Email Address", EditorStyles.boldLabel);
  398. GUILayout.Label(
  399. "Provide an email address where the bug reports should be sent.",
  400. EditorStyles.miniLabel);
  401. _emailAddress = EditorGUILayout.TextField(_emailAddress);
  402. EditorGUILayout.Space();
  403. EditorGUILayout.BeginHorizontal();
  404. if (SRInternalEditorUtil.ClickableLabel(
  405. "I agree to the <color={0}>terms and conditions</color>.".Fmt(SRInternalEditorUtil.Styles.LinkColour),
  406. SRInternalEditorUtil.Styles.RichTextLabel))
  407. {
  408. ApiSignupTermsWindow.Open();
  409. }
  410. _agreeLegal = EditorGUILayout.Toggle(_agreeLegal);
  411. EditorGUILayout.EndHorizontal();
  412. EditorGUILayout.Space();
  413. var isEnabled = !string.IsNullOrEmpty(_invoiceNumber) && !string.IsNullOrEmpty(_emailAddress) && _agreeLegal;
  414. EditorGUI.BeginDisabledGroup(!isEnabled);
  415. if (GUILayout.Button("Submit"))
  416. {
  417. _errorMessage = null;
  418. _enableTabChange = false;
  419. EditorApplication.delayCall += () =>
  420. {
  421. ApiSignup.SignUp(_emailAddress, _invoiceNumber,
  422. (success, key, email, error) => OnSignupResult(success, key, email, error, settings));
  423. Repaint();
  424. };
  425. }
  426. EditorGUI.EndDisabledGroup();
  427. if (!string.IsNullOrEmpty(_errorMessage))
  428. {
  429. EditorGUILayout.HelpBox(_errorMessage, MessageType.Error, true);
  430. }
  431. GUILayout.FlexibleSpace();
  432. GUILayout.Label("Having trouble? Please email contact@stompyrobot.uk for assistance.",
  433. EditorStyles.miniLabel);
  434. EditorGUI.EndDisabledGroup();
  435. }
  436. private void OnSignupResult(bool didSucceed, string apiKey, string email, string error, Settings settings)
  437. {
  438. _enableTabChange = true;
  439. _selectedTab = Tabs.Bug_Reporter;
  440. if (!didSucceed)
  441. {
  442. _errorMessage = error;
  443. return;
  444. }
  445. settings.ApiKey = apiKey;
  446. settings.EnableBugReporter = true;
  447. EditorUtility.DisplayDialog("SRDebugger API",
  448. "API key has been created successfully. An email has been sent to your email address ({0}) with a verification link. You must verify your email before you can receive any bug reports."
  449. .Fmt(email), "OK");
  450. _showBugReportSignupForm = false;
  451. }
  452. private ReorderableList _keyboardShortcutList;
  453. private Vector2 _scrollPosition;
  454. private void DrawTabShortcuts(Settings settings)
  455. {
  456. if (_keyboardShortcutList == null)
  457. {
  458. _keyboardShortcutList = new ReorderableList((IList) settings.KeyboardShortcuts,
  459. typeof (Settings.KeyboardShortcut), false, true, true, true);
  460. _keyboardShortcutList.drawHeaderCallback = DrawKeyboardListHeaderCallback;
  461. _keyboardShortcutList.drawElementCallback = DrawKeyboardListItemCallback;
  462. _keyboardShortcutList.onAddCallback += OnAddKeyboardListCallback;
  463. _keyboardShortcutList.onRemoveCallback += OnRemoveKeyboardListCallback;
  464. }
  465. EditorGUILayout.Space();
  466. EditorGUILayout.BeginHorizontal();
  467. settings.EnableKeyboardShortcuts = EditorGUILayout.Toggle(
  468. new GUIContent("Enable", SRDebugEditorStrings.Current.SettingsKeyboardShortcutsTooltip),
  469. settings.EnableKeyboardShortcuts);
  470. EditorGUI.BeginDisabledGroup(!settings.EnableKeyboardShortcuts);
  471. settings.KeyboardEscapeClose =
  472. EditorGUILayout.Toggle(
  473. new GUIContent("Close on Esc", SRDebugEditorStrings.Current.SettingsCloseOnEscapeTooltip),
  474. settings.KeyboardEscapeClose);
  475. EditorGUILayout.EndHorizontal();
  476. EditorGUILayout.Separator();
  477. var dupe = DetectDuplicateKeyboardShortcuts(settings);
  478. if (dupe != null)
  479. {
  480. var shortcut = "";
  481. if (dupe.Control)
  482. {
  483. shortcut += "Ctrl";
  484. }
  485. if (dupe.Shift)
  486. {
  487. if (shortcut.Length > 0)
  488. {
  489. shortcut += "-";
  490. }
  491. shortcut += "Shift";
  492. }
  493. if (dupe.Alt)
  494. {
  495. if (shortcut.Length > 0)
  496. {
  497. shortcut += "-";
  498. }
  499. shortcut += "Alt";
  500. }
  501. if (shortcut.Length > 0)
  502. {
  503. shortcut += "-";
  504. }
  505. shortcut += dupe.Key;
  506. EditorGUILayout.HelpBox(
  507. "Duplicate shortcut ({0}). Only one shortcut per key is supported.".Fmt(shortcut),
  508. MessageType.Warning);
  509. }
  510. _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, false, false,
  511. GUILayout.Width(position.width - 11));
  512. EditorGUILayout.BeginVertical(GUILayout.Width(position.width - 30));
  513. _keyboardShortcutList.DoLayoutList();
  514. GUILayout.FlexibleSpace();
  515. EditorGUILayout.EndVertical();
  516. EditorGUILayout.EndScrollView();
  517. EditorGUI.EndDisabledGroup();
  518. }
  519. private void DrawTabAdvanced(Settings settings)
  520. {
  521. _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, false, true);
  522. GUILayout.Label("Console", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  523. settings.CollapseDuplicateLogEntries =
  524. EditorGUILayout.Toggle(
  525. new GUIContent("Collapse Log Entries", "Collapse duplicate log entries into single log."),
  526. settings.CollapseDuplicateLogEntries);
  527. settings.RichTextInConsole =
  528. EditorGUILayout.Toggle(
  529. new GUIContent("Rich Text in Console", "Parse rich text tags in console log entries."),
  530. settings.RichTextInConsole);
  531. settings.MaximumConsoleEntries =
  532. EditorGUILayout.IntSlider(
  533. new GUIContent("Max Console Entries",
  534. "The maximum size of the console buffer. Higher values may cause performance issues on slower devices."),
  535. settings.MaximumConsoleEntries, 100, 6000);
  536. EditorGUILayout.Separator();
  537. GUILayout.Label("Display", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  538. settings.EnableBackgroundTransparency =
  539. EditorGUILayout.Toggle(new GUIContent("Transparent Background"),
  540. settings.EnableBackgroundTransparency);
  541. EditorGUI.BeginDisabledGroup(!settings.EnableBackgroundTransparency);
  542. settings.BackgroundTransparency = EditorGUILayout.Slider(new GUIContent("Background Opacity"),
  543. settings.BackgroundTransparency, 0.0f, 1.0f);
  544. EditorGUI.EndDisabledGroup();
  545. EditorGUILayout.BeginHorizontal();
  546. EditorGUILayout.PrefixLabel(new GUIContent("Layer", "The layer the debug panel UI will be drawn to"));
  547. settings.DebugLayer = EditorGUILayout.LayerField(settings.DebugLayer);
  548. EditorGUILayout.EndHorizontal();
  549. settings.UseDebugCamera =
  550. EditorGUILayout.Toggle(
  551. new GUIContent("Use Debug Camera", SRDebugEditorStrings.Current.SettingsDebugCameraTooltip),
  552. settings.UseDebugCamera);
  553. EditorGUI.BeginDisabledGroup(!settings.UseDebugCamera);
  554. settings.DebugCameraDepth = EditorGUILayout.Slider(new GUIContent("Debug Camera Depth"),
  555. settings.DebugCameraDepth, -100, 100);
  556. EditorGUI.EndDisabledGroup();
  557. settings.UIScale =
  558. EditorGUILayout.Slider(new GUIContent("UI Scale"), settings.UIScale, 1f, 3f);
  559. EditorGUILayout.Separator();
  560. GUILayout.Label("Enabled Tabs", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  561. GUILayout.Label(SRDebugEditorStrings.Current.SettingsEnabledTabsDescription, EditorStyles.wordWrappedLabel);
  562. EditorGUILayout.Space();
  563. var disabledTabs = settings.DisabledTabs.ToList();
  564. var tabNames = Enum.GetNames(typeof (DefaultTabs));
  565. var tabValues = Enum.GetValues(typeof (DefaultTabs));
  566. EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
  567. var changed = false;
  568. for (var i = 0; i < tabNames.Length; i++)
  569. {
  570. var tabName = tabNames[i];
  571. var tabValue = (DefaultTabs) (tabValues.GetValue(i));
  572. if (tabName == "BugReporter")
  573. {
  574. continue;
  575. }
  576. if (tabName == "SystemInformation")
  577. {
  578. tabName = "System Information";
  579. }
  580. EditorGUILayout.BeginHorizontal();
  581. var isEnabled = !disabledTabs.Contains(tabValue);
  582. var isNowEnabled = EditorGUILayout.ToggleLeft(tabName, isEnabled,
  583. SRInternalEditorUtil.Styles.LeftToggleButton);
  584. if (isEnabled && !isNowEnabled)
  585. {
  586. disabledTabs.Add(tabValue);
  587. changed = true;
  588. }
  589. else if (!isEnabled && isNowEnabled)
  590. {
  591. disabledTabs.Remove(tabValue);
  592. changed = true;
  593. }
  594. EditorGUILayout.EndHorizontal();
  595. }
  596. EditorGUILayout.EndVertical();
  597. if (changed)
  598. {
  599. settings.DisabledTabs = disabledTabs;
  600. }
  601. GUILayout.Label("Other", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  602. settings.EnableEventSystemGeneration =
  603. EditorGUILayout.Toggle(
  604. new GUIContent("Automatic Event System", "Automatically create a UGUI EventSystem if none is found in the scene."),
  605. settings.EnableEventSystemGeneration);
  606. #if ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
  607. using (new EditorGUI.DisabledScope(!Settings.Instance.EnableEventSystemGeneration))
  608. {
  609. Settings.Instance.UIInputMode =
  610. (Settings.UIModes) EditorGUILayout.EnumPopup(new GUIContent("Input Mode"), Settings.Instance.UIInputMode);
  611. }
  612. #endif
  613. settings.UnloadOnClose =
  614. EditorGUILayout.Toggle(
  615. new GUIContent("Unload When Closed", "Unload the debug panel from the scene when it is closed."),
  616. settings.UnloadOnClose);
  617. EditorGUILayout.HelpBox(
  618. "The panel loads again automatically when opened. You can always unload the panel by holding down the close button.",
  619. MessageType.Info);
  620. settings.DisableWelcomePopup =
  621. EditorGUILayout.Toggle(
  622. new GUIContent("Disable Welcome Popup", "Disable the welcome popup that appears when a project with SRDebugger is opened for the first time."),
  623. settings.DisableWelcomePopup);
  624. EditorGUILayout.Separator();
  625. if (GUILayout.Button("Run Migrations"))
  626. {
  627. Migrations.RunMigrations(true);
  628. }
  629. EditorGUILayout.Separator();
  630. GUILayout.Label("Disable SRDebugger (beta)", SRInternalEditorUtil.Styles.InspectorHeaderStyle);
  631. GUILayout.Label("Disabling will exclude any SRDebugger assets and scripts from your game.", SRInternalEditorUtil.Styles.ParagraphLabel);
  632. EditorGUILayout.HelpBox("This is an experimental feature. Please make sure your project is backed up via source control.", MessageType.Warning);
  633. GUILayout.Label("• " + SRDebugEditor.DisableSRDebuggerCompileDefine + " compiler define will be added to all build configurations.", SRInternalEditorUtil.Styles.ListBulletPoint);
  634. GUILayout.Label("• Some SRDebugger folders will be renamed to prevent Unity from importing them.", SRInternalEditorUtil.Styles.ListBulletPoint);
  635. GUILayout.Label("• Any code that interacts with SRDebugger (e.g. SROptions or SRDebug API) should use the `#if !"+ SRDebugEditor.DisableSRDebuggerCompileDefine + "` preprocessor directive.", SRInternalEditorUtil.Styles.ListBulletPoint);
  636. GUILayout.Label("• You can enable SRDebugger again at any time.", SRInternalEditorUtil.Styles.ListBulletPoint);
  637. if (GUILayout.Button("Disable SRDebugger"))
  638. {
  639. EditorApplication.delayCall += () =>
  640. {
  641. SRDebugEditor.SetEnabled(false);
  642. Reset();
  643. };
  644. }
  645. EditorGUILayout.EndScrollView();
  646. }
  647. #endregion
  648. #region Entry Code Utility
  649. private string GetEntryCodeString(Settings settings)
  650. {
  651. var entryCode = settings.EntryCode;
  652. if (entryCode.Count == 0)
  653. {
  654. settings.EntryCode = new[] {0, 0, 0, 0};
  655. }
  656. var code = "";
  657. for (var i = 0; i < entryCode.Count; i++)
  658. {
  659. code += entryCode[i];
  660. }
  661. return code;
  662. }
  663. private void UpdateEntryCode(Settings settings, string str)
  664. {
  665. var newCode = new List<int>();
  666. for (var i = 0; i < str.Length; i++)
  667. {
  668. newCode.Add(int.Parse(str[i].ToString(), NumberStyles.Integer));
  669. }
  670. settings.EntryCode = newCode;
  671. _currentEntryCode = GetEntryCodeString(settings);
  672. }
  673. #endregion
  674. #region Keyboard Shortcut Utility
  675. private Settings.KeyboardShortcut DetectDuplicateKeyboardShortcuts(Settings settings)
  676. {
  677. var s = settings.KeyboardShortcuts;
  678. return
  679. s.FirstOrDefault(
  680. shortcut =>
  681. s.Any(
  682. p =>
  683. p != shortcut && p.Shift == shortcut.Shift && p.Control == shortcut.Control &&
  684. p.Alt == shortcut.Alt &&
  685. p.Key == shortcut.Key));
  686. }
  687. private void DrawKeyboardListHeaderCallback(Rect rect)
  688. {
  689. EditorGUI.LabelField(rect, "Keyboard Shortcuts");
  690. }
  691. private void DrawKeyboardListItemCallback(Rect rect, int index, bool isActive, bool isFocused)
  692. {
  693. Settings settings;
  694. if (!SettingsReady(out settings))
  695. {
  696. return;
  697. }
  698. var item = settings.KeyboardShortcuts[index];
  699. rect.y += 2;
  700. var buttonWidth = 40;
  701. var padding = 5;
  702. item.Control = GUI.Toggle(new Rect(rect.x, rect.y, buttonWidth, EditorGUIUtility.singleLineHeight),
  703. item.Control,
  704. "Ctrl", "Button");
  705. rect.x += buttonWidth + padding;
  706. rect.width -= buttonWidth + padding;
  707. item.Alt = GUI.Toggle(new Rect(rect.x, rect.y, buttonWidth, EditorGUIUtility.singleLineHeight), item.Alt,
  708. "Alt",
  709. "Button");
  710. rect.x += buttonWidth + padding;
  711. rect.width -= buttonWidth + padding;
  712. item.Shift = GUI.Toggle(new Rect(rect.x, rect.y, buttonWidth, EditorGUIUtility.singleLineHeight), item.Shift,
  713. "Shift",
  714. "Button");
  715. rect.x += buttonWidth + padding;
  716. rect.width -= buttonWidth + padding;
  717. item.Key =
  718. (KeyCode) EditorGUI.EnumPopup(new Rect(rect.x, rect.y, 80, EditorGUIUtility.singleLineHeight), item.Key);
  719. rect.x += 80 + padding;
  720. rect.width -= 80 + padding;
  721. item.Action =
  722. (Settings.ShortcutActions)
  723. EditorGUI.EnumPopup(new Rect(rect.x, rect.y, rect.width - 4, EditorGUIUtility.singleLineHeight),
  724. item.Action);
  725. }
  726. private void OnAddKeyboardListCallback(ReorderableList list)
  727. {
  728. Settings settings;
  729. if (!SettingsReady(out settings))
  730. {
  731. return;
  732. }
  733. var shortcuts = settings.KeyboardShortcuts.ToList();
  734. shortcuts.Add(new Settings.KeyboardShortcut());
  735. settings.KeyboardShortcuts = shortcuts;
  736. list.list = (IList) settings.KeyboardShortcuts;
  737. }
  738. private void OnRemoveKeyboardListCallback(ReorderableList list)
  739. {
  740. Settings settings;
  741. if (!SettingsReady(out settings))
  742. {
  743. return;
  744. }
  745. var shortcuts = settings.KeyboardShortcuts.ToList();
  746. shortcuts.RemoveAt(list.index);
  747. settings.KeyboardShortcuts = shortcuts;
  748. list.list = (IList) settings.KeyboardShortcuts;
  749. }
  750. #endregion
  751. #endif
  752. }
  753. }