SRInternalEditorUtil.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. using SRF;
  2. namespace SRDebugger.Editor
  3. {
  4. using System;
  5. using System.IO;
  6. using UnityEditor;
  7. using UnityEngine;
  8. static class SRInternalEditorUtil
  9. {
  10. // Path to this file from the root path
  11. private const string TestPath = "SRDebugger/README.txt";
  12. private static GUIStyle _bgStyle;
  13. private static Texture2D _logoTexture;
  14. private static Texture2D _welcomeLogoTexture;
  15. private static Texture2D _bgTexture;
  16. private static GUIStyle _middleAlign;
  17. /// <summary>
  18. /// Finds the path to the SRDebugger installation folder (e.g. Assets/StompyRobot/SRDebugger)
  19. /// </summary>
  20. /// <returns></returns>
  21. public static string GetRootPath()
  22. {
  23. // Find assets that match this file name
  24. var potentialAssets = AssetDatabase.FindAssets("README");
  25. foreach (var potentialAsset in potentialAssets)
  26. {
  27. var path = AssetDatabase.GUIDToAssetPath(potentialAsset);
  28. if (path.Contains(TestPath))
  29. {
  30. var rootPath = Path.GetDirectoryName(path);
  31. return rootPath;
  32. }
  33. }
  34. throw new Exception("Unable to find SRDebugger root path. Please ensure the README file in StompyRobot/SRDebugger still exists.");
  35. }
  36. /// <summary>
  37. /// Finds the path to an SRDebugger asset relative to the installation root.
  38. /// </summary>
  39. /// <param name="relativeToRoot"></param>
  40. /// <returns></returns>
  41. public static string GetAssetPath(string relativeToRoot)
  42. {
  43. if (!relativeToRoot.StartsWith("/"))
  44. {
  45. relativeToRoot = "/" + relativeToRoot;
  46. }
  47. var p = GetRootPath() + relativeToRoot;
  48. return p;
  49. }
  50. public static T LoadResource<T>(string path) where T : UnityEngine.Object
  51. {
  52. var p = GetAssetPath(path);
  53. //Debug.Log("[SRDebugger] Loading " + p);
  54. var asset = AssetDatabase.LoadAssetAtPath(p, typeof(T));
  55. return asset as T;
  56. }
  57. #if !DISABLE_SRDEBUGGER
  58. public enum SettingsResult
  59. {
  60. Cache,
  61. Loaded,
  62. Waiting,
  63. Error
  64. }
  65. public static class EditorSettings
  66. {
  67. internal const string SettingsFilePath = "/usr/Resources/SRDebugger/Settings.asset";
  68. internal const string DisabledSettingsFilePath = "/usr" + SRDebugEditor.DisabledDirectoryPostfix + "/Resources/SRDebugger/Settings.asset";
  69. private static Settings _instance;
  70. public static SettingsResult TryGetOrCreate(out Settings instance, out string message)
  71. {
  72. if (_instance != null)
  73. {
  74. instance = _instance;
  75. message = string.Empty;
  76. return SettingsResult.Cache;
  77. }
  78. try
  79. {
  80. SettingsResult result = InternalTryGetOrCreateSettings(out _instance, out message);
  81. instance = _instance;
  82. return result;
  83. }
  84. catch (Exception e)
  85. {
  86. instance = null;
  87. message = e.ToString();
  88. return SettingsResult.Error;
  89. }
  90. }
  91. public static void ClearCache()
  92. {
  93. Settings.ClearCache(); // Just in case runtime settings are loaded.
  94. if (_instance == null)
  95. {
  96. return;
  97. }
  98. var instance = _instance;
  99. _instance = null;
  100. Resources.UnloadAsset(instance);
  101. instance = null;
  102. GC.Collect();
  103. EditorUtility.UnloadUnusedAssetsImmediate();
  104. Resources.UnloadUnusedAssets();
  105. }
  106. private static SettingsResult InternalTryGetOrCreateSettings(out Settings instance, out string message)
  107. {
  108. instance = null;
  109. message = null;
  110. if (EditorApplication.isPlaying || EditorApplication.isPlayingOrWillChangePlaymode)
  111. {
  112. message = "Settings can only be modified while in edit-mode. Exit play mode to make changes to SRDebugger settings.";
  113. return SettingsResult.Waiting;
  114. }
  115. // If compiling, wait for that to finish. We might be disabling/enabling SRDebugger and don't want to recreate the settings while that is in progress.
  116. if (EditorApplication.isCompiling || EditorApplication.isUpdating)
  117. {
  118. message = "Waiting for Unity to finish compiling/updating...";
  119. return SettingsResult.Waiting;
  120. }
  121. // Check if there is a 'disabled' settings file, we don't want to create a new settings file if a disabled one exists.
  122. string disabledSettingsFile = SRInternalEditorUtil.GetAssetPath(DisabledSettingsFilePath);
  123. if (File.Exists(disabledSettingsFile))
  124. {
  125. message = "A settings file already exists but is disabled. Please ensure SRDebugger is correctly enabled or disabled.";
  126. return SettingsResult.Error;
  127. }
  128. // Get resources folder path
  129. var settingsAssetPath = SRInternalEditorUtil.GetAssetPath(SettingsFilePath);
  130. // Load existing asset.
  131. if (File.Exists(settingsAssetPath))
  132. {
  133. instance = AssetDatabase.LoadAssetAtPath<Settings>(settingsAssetPath);
  134. if (instance == null)
  135. {
  136. message = "Error loading settings asset.";
  137. return SettingsResult.Error;
  138. }
  139. return SettingsResult.Loaded;
  140. }
  141. Debug.Log("[SRDebugger] Creating settings asset at {0}".Fmt(settingsAssetPath));
  142. instance = ScriptableObject.CreateInstance<Settings>();
  143. string containingDirectory = Path.GetDirectoryName(settingsAssetPath);
  144. if (containingDirectory == null)
  145. {
  146. message = "Error finding target settings directory.";
  147. return SettingsResult.Error;
  148. }
  149. // Create directory if it doesn't exist
  150. Directory.CreateDirectory(containingDirectory);
  151. // Save instance if in editor
  152. AssetDatabase.CreateAsset(instance, settingsAssetPath);
  153. return SettingsResult.Loaded;
  154. }
  155. }
  156. #endif
  157. public static Texture2D GetLogo()
  158. {
  159. if (_logoTexture != null)
  160. {
  161. return _logoTexture;
  162. }
  163. return
  164. _logoTexture =
  165. LoadResource<Texture2D>("Editor/Logo_" + (EditorGUIUtility.isProSkin ? "DarkBG" : "LightBG") +
  166. ".png");
  167. }
  168. public static Texture2D GetWelcomeLogo()
  169. {
  170. if (_welcomeLogoTexture != null)
  171. {
  172. return _welcomeLogoTexture;
  173. }
  174. return
  175. _welcomeLogoTexture =
  176. LoadResource<Texture2D>("Editor/WelcomeLogo_" +
  177. (EditorGUIUtility.isProSkin ? "DarkBG" : "LightBG") + ".png");
  178. }
  179. public static Texture2D GetBackground()
  180. {
  181. if (_bgTexture != null)
  182. {
  183. return _bgTexture;
  184. }
  185. return
  186. _bgTexture =
  187. LoadResource<Texture2D>("Editor/BG_" + (EditorGUIUtility.isProSkin ? "Dark" : "Light") + ".png");
  188. }
  189. public static void DrawLogo(Texture2D logo)
  190. {
  191. if (logo == null)
  192. {
  193. Debug.LogError("Error loading SRDebugger logo");
  194. return;
  195. }
  196. #if !DISABLE_SRDEBUGGER
  197. var rect =
  198. #endif
  199. EditorGUILayout.BeginVertical();
  200. GUILayout.Space(15);
  201. EditorGUILayout.BeginHorizontal();
  202. GUILayout.FlexibleSpace();
  203. GUI.DrawTexture(
  204. GUILayoutUtility.GetRect(logo.width, logo.width, logo.height, logo.height, GUILayout.ExpandHeight(false),
  205. GUILayout.ExpandWidth(false)),
  206. logo);
  207. GUILayout.FlexibleSpace();
  208. EditorGUILayout.EndHorizontal();
  209. GUILayout.Space(15);
  210. EditorGUILayout.EndVertical();
  211. #if !DISABLE_SRDEBUGGER
  212. var size = EditorStyles.miniLabel.CalcSize(new GUIContent(SRDebug.Version));
  213. GUI.Label(new Rect(rect.xMax - size.x, rect.yMax - size.y, size.x, size.y), SRDebug.Version,
  214. EditorStyles.miniLabel);
  215. #endif
  216. }
  217. public static bool DrawInspectorFoldout(bool isVisible, string content)
  218. {
  219. isVisible = EditorGUILayout.Foldout(isVisible, content, Styles.InspectorHeaderFoldoutStyle);
  220. EditorGUILayout.Separator();
  221. return isVisible;
  222. }
  223. public static void BeginDrawBackground()
  224. {
  225. if (_bgStyle == null)
  226. {
  227. _bgStyle = new GUIStyle();
  228. _bgStyle.margin = _bgStyle.padding = new RectOffset(0, 0, 0, 0);
  229. }
  230. var rect = EditorGUILayout.BeginVertical(_bgStyle);
  231. DrawTextureTiled(rect, GetBackground());
  232. }
  233. public static void EndDrawBackground()
  234. {
  235. EditorGUILayout.EndVertical();
  236. }
  237. public static void DrawTextureTiled(Rect rect, Texture2D tex)
  238. {
  239. GUI.BeginGroup(rect);
  240. var tilesX = Mathf.Max(1, Mathf.CeilToInt(rect.width / tex.width));
  241. var tilesY = Mathf.Max(1, Mathf.CeilToInt(rect.height / tex.height));
  242. for (var x = 0; x < tilesX; x++)
  243. {
  244. for (var y = 0; y < tilesY; y++)
  245. {
  246. var pos = new Rect(x * tex.width, y * tex.height, tex.width, tex.height);
  247. pos.x += rect.x;
  248. pos.y += rect.y;
  249. GUI.DrawTexture(pos, tex, ScaleMode.ScaleAndCrop);
  250. }
  251. }
  252. GUI.EndGroup();
  253. }
  254. public static bool ClickableLabel(string text, GUIStyle style)
  255. {
  256. var rect = EditorGUILayout.BeginVertical(Styles.NoPaddingNoMargin);
  257. GUILayout.Label(text, style);
  258. EditorGUILayout.EndVertical();
  259. if (Event.current.type == EventType.MouseUp && rect.Contains(Event.current.mousePosition))
  260. {
  261. return true;
  262. }
  263. return false;
  264. }
  265. #if !DISABLE_SRDEBUGGER
  266. public static void DrawLayoutPreview(Rect rect, Settings settings)
  267. {
  268. const int profilerWidth = 120;
  269. const int profilerHeight = 70;
  270. const int optionsWidth = 150;
  271. const int optionsHeight = 36;
  272. if (_middleAlign == null)
  273. {
  274. _middleAlign = new GUIStyle(EditorStyles.helpBox);
  275. _middleAlign.alignment = TextAnchor.MiddleCenter;
  276. }
  277. var iconPath = "Editor/Icons/" + (EditorGUIUtility.isProSkin ? "Light" : "Dark");
  278. const float consoleHeight = 90;
  279. GUI.Box(rect, "", EditorStyles.helpBox);
  280. var consoleAlignment = settings.ConsoleAlignment;
  281. var consoleRect = new Rect(rect.x,
  282. consoleAlignment == ConsoleAlignment.Top ? rect.y : rect.yMax - consoleHeight, rect.width,
  283. consoleHeight);
  284. GUI.Box(consoleRect, new GUIContent(LoadResource<Texture2D>(iconPath + "/console-25.png"), "Console"),
  285. _middleAlign);
  286. var workRect = rect;
  287. if (consoleAlignment == ConsoleAlignment.Top)
  288. {
  289. workRect.yMin += consoleHeight;
  290. }
  291. else
  292. {
  293. workRect.yMax -= consoleHeight;
  294. }
  295. var opAlignment = settings.OptionsAlignment;
  296. var proAlignment = settings.ProfilerAlignment;
  297. GUI.Box(GetAlignedRect(profilerWidth, profilerHeight, proAlignment, workRect),
  298. new GUIContent(LoadResource<Texture2D>(iconPath + "/profiler-25.png"), "Profiler"), _middleAlign);
  299. var optionsRect = workRect;
  300. if ((opAlignment == PinAlignment.TopCenter && proAlignment == PinAlignment.TopLeft) || (opAlignment == PinAlignment.BottomCenter && proAlignment == PinAlignment.BottomLeft))
  301. {
  302. optionsRect.x += profilerWidth;
  303. optionsRect.width -= profilerWidth;
  304. }
  305. else if ((opAlignment == PinAlignment.TopCenter && proAlignment == PinAlignment.TopRight) ||
  306. opAlignment == PinAlignment.BottomCenter && proAlignment == PinAlignment.BottomRight)
  307. {
  308. optionsRect.width -= profilerWidth;
  309. }
  310. GUI.Box(GetAlignedRect(optionsWidth, optionsHeight, opAlignment, optionsRect),
  311. new GUIContent(LoadResource<Texture2D>(iconPath + "/options-25.png"), "Pinned Options"), _middleAlign);
  312. if (settings.EnableTrigger != Settings.TriggerEnableModes.Off)
  313. {
  314. GUI.Box(GetAlignedRect(25, 25, settings.TriggerPosition, rect),
  315. new GUIContent("", "Entry Trigger"),
  316. _middleAlign);
  317. }
  318. }
  319. private static Rect GetAlignedRect(int width, int height, PinAlignment alignment, Rect workRect)
  320. {
  321. var rect = new Rect(0, 0, width, height);
  322. if (alignment == PinAlignment.BottomLeft || alignment == PinAlignment.BottomRight || alignment == PinAlignment.BottomCenter)
  323. {
  324. rect.position = new Vector2(0, workRect.height - rect.height);
  325. }
  326. else if (alignment == PinAlignment.CenterLeft || alignment == PinAlignment.CenterRight)
  327. {
  328. rect.position = new Vector2(0, workRect.height / 2 - rect.height / 2);
  329. }
  330. if (alignment == PinAlignment.TopRight || alignment == PinAlignment.BottomRight || alignment == PinAlignment.CenterRight)
  331. {
  332. rect.position += new Vector2(workRect.width - rect.width, 0);
  333. }
  334. else if (alignment == PinAlignment.TopCenter || alignment == PinAlignment.BottomCenter)
  335. {
  336. rect.position += new Vector2(workRect.width / 2 - rect.width / 2, 0);
  337. }
  338. rect.position += workRect.position;
  339. return rect;
  340. }
  341. #endif
  342. public static void RenderGif(Rect pos, Texture2D map, int frameNo, int frameWidth, int frameHeight, int perLine,
  343. int paddingX = 0, int paddingY = 0)
  344. {
  345. var x = frameNo % perLine;
  346. var y = Mathf.FloorToInt((float)frameNo / perLine);
  347. var xCoord = x * (frameWidth + paddingX);
  348. var yCoord = (y + 1) * (frameHeight + paddingY);
  349. var texCoords = new Rect(
  350. xCoord / (float)map.width,
  351. (map.height - yCoord) / (float)map.height,
  352. (frameWidth) / (float)map.width,
  353. (frameHeight) / (float)map.height);
  354. GUI.DrawTextureWithTexCoords(pos, map, texCoords);
  355. //Debug.Log(texCoords);
  356. //Debug.Log("x: " + x + ", y: " + y);
  357. }
  358. public static void DrawFooterLayout(float width)
  359. {
  360. EditorGUILayout.BeginHorizontal();
  361. var margin = (EditorStyles.miniButton.padding.left) / 2f;
  362. width = width - margin * 2;
  363. if (GUILayout.Button("Web Site", GUILayout.Width(width / 2f - margin)))
  364. {
  365. Application.OpenURL(SRDebugEditorStrings.Current.SettingsWebSiteUrl);
  366. }
  367. if (GUILayout.Button("Asset Store Page", GUILayout.Width(width / 2f - margin)))
  368. {
  369. Application.OpenURL(SRDebugEditorStrings.Current.SettingsAssetStoreUrl);
  370. }
  371. EditorGUILayout.EndHorizontal();
  372. EditorGUILayout.BeginHorizontal();
  373. if (GUILayout.Button("Documentation", GUILayout.Width(width / 2f - margin)))
  374. {
  375. Application.OpenURL(SRDebugEditorStrings.Current.SettingsDocumentationUrl);
  376. }
  377. if (GUILayout.Button("Support", GUILayout.Width(width / 2f - margin)))
  378. {
  379. Application.OpenURL(
  380. SRDebugEditorStrings.Current.SettingsSupportUrl);
  381. }
  382. EditorGUILayout.EndHorizontal();
  383. }
  384. public static class Styles
  385. {
  386. private static GUIStyle _inspectorHeaderStyle;
  387. private static GUIStyle _inspectorHeaderFoldoutStyle;
  388. private static GUIStyle _settingsHeaderBoxStyle;
  389. private static GUIStyle _headerLabel;
  390. private static GUIStyle _paragraphLabel;
  391. private static GUIStyle _paragraphLabelItalic;
  392. private static GUIStyle _radioButtonDescription;
  393. private static GUIStyle _radioButton;
  394. private static GUIStyle _leftToggleButton;
  395. private static GUIStyle _noPaddingNoMargin;
  396. private static GUIStyle _richTextLabel;
  397. private static GUIStyle _listBulletPoint;
  398. public static string LinkColour
  399. {
  400. get
  401. {
  402. if (EditorGUIUtility.isProSkin)
  403. {
  404. return "#7C8CB9";
  405. }
  406. return "#0032E6";
  407. }
  408. }
  409. public static GUIStyle InspectorHeaderStyle
  410. {
  411. get
  412. {
  413. if (_inspectorHeaderStyle == null)
  414. {
  415. _inspectorHeaderStyle = new GUIStyle(EditorStyles.boldLabel);
  416. _inspectorHeaderStyle.fontSize = 12;
  417. }
  418. return _inspectorHeaderStyle;
  419. }
  420. }
  421. public static GUIStyle InspectorHeaderFoldoutStyle
  422. {
  423. get
  424. {
  425. if (_inspectorHeaderFoldoutStyle == null)
  426. {
  427. _inspectorHeaderFoldoutStyle = new GUIStyle(EditorStyles.foldout);
  428. _inspectorHeaderFoldoutStyle.fontSize = 12;
  429. _inspectorHeaderFoldoutStyle.fontStyle = FontStyle.Bold;
  430. }
  431. return _inspectorHeaderFoldoutStyle;
  432. }
  433. }
  434. public static GUIStyle SettingsHeaderBoxStyle
  435. {
  436. get
  437. {
  438. if (_settingsHeaderBoxStyle == null)
  439. {
  440. _settingsHeaderBoxStyle = new GUIStyle("OL Title");
  441. _settingsHeaderBoxStyle.padding = new RectOffset(0, 0, 0, 0);
  442. _settingsHeaderBoxStyle.margin = new RectOffset(0, 0, 0, 0);
  443. _settingsHeaderBoxStyle.clipping = TextClipping.Clip;
  444. _settingsHeaderBoxStyle.overflow = new RectOffset(0, 0, 0, 0);
  445. //_settingsHeaderBoxStyle.border = new RectOffset(1, 1, 1, 1);
  446. _settingsHeaderBoxStyle.fixedHeight = 0.5f;
  447. }
  448. return _settingsHeaderBoxStyle;
  449. }
  450. }
  451. public static GUIStyle HeaderLabel
  452. {
  453. get
  454. {
  455. if (_headerLabel == null)
  456. {
  457. _headerLabel = new GUIStyle(EditorStyles.largeLabel);
  458. _headerLabel.fontSize = 18;
  459. _headerLabel.fontStyle = FontStyle.Normal;
  460. _headerLabel.margin = new RectOffset(5, 5, 5, 5);
  461. }
  462. return _headerLabel;
  463. }
  464. }
  465. public static GUIStyle ParagraphLabel
  466. {
  467. get
  468. {
  469. if (_paragraphLabel == null)
  470. {
  471. _paragraphLabel = new GUIStyle(EditorStyles.label);
  472. _paragraphLabel.margin = new RectOffset(5, 5, 5, 5);
  473. _paragraphLabel.wordWrap = true;
  474. _paragraphLabel.richText = true;
  475. }
  476. return _paragraphLabel;
  477. }
  478. }
  479. public static GUIStyle ParagraphLabelItalic
  480. {
  481. get
  482. {
  483. if (_paragraphLabelItalic == null)
  484. {
  485. _paragraphLabelItalic = new GUIStyle(EditorStyles.label);
  486. _paragraphLabelItalic.margin = new RectOffset(5, 5, 5, 5);
  487. _paragraphLabelItalic.wordWrap = true;
  488. _paragraphLabelItalic.richText = true;
  489. _paragraphLabelItalic.fontStyle = FontStyle.Italic;
  490. }
  491. return _paragraphLabelItalic;
  492. }
  493. }
  494. public static GUIStyle LeftToggleButton
  495. {
  496. get
  497. {
  498. if (_leftToggleButton == null)
  499. {
  500. _leftToggleButton = new GUIStyle(EditorStyles.label);
  501. _leftToggleButton.contentOffset = new Vector2(_leftToggleButton.contentOffset.x + 5,
  502. _leftToggleButton.contentOffset.y);
  503. }
  504. return _leftToggleButton;
  505. }
  506. }
  507. public static GUIStyle RadioButton
  508. {
  509. get
  510. {
  511. if (_radioButton == null)
  512. {
  513. _radioButton = new GUIStyle(EditorStyles.radioButton);
  514. _radioButton.contentOffset = new Vector2(_radioButton.contentOffset.x + 5,
  515. _radioButton.contentOffset.y);
  516. }
  517. return _radioButton;
  518. }
  519. }
  520. public static GUIStyle RadioButtonDescription
  521. {
  522. get
  523. {
  524. if (_radioButtonDescription == null)
  525. {
  526. _radioButtonDescription = new GUIStyle(ParagraphLabel);
  527. _radioButtonDescription.padding.left = (int)RadioButton.contentOffset.x +
  528. RadioButton.padding.left;
  529. }
  530. return _radioButtonDescription;
  531. }
  532. }
  533. public static GUIStyle NoPaddingNoMargin
  534. {
  535. get
  536. {
  537. if (_noPaddingNoMargin == null)
  538. {
  539. _noPaddingNoMargin = new GUIStyle();
  540. _noPaddingNoMargin.margin = new RectOffset(0, 0, 0, 0);
  541. _noPaddingNoMargin.padding = new RectOffset(0, 0, 0, 0);
  542. }
  543. return _noPaddingNoMargin;
  544. }
  545. }
  546. public static GUIStyle RichTextLabel
  547. {
  548. get
  549. {
  550. if (_richTextLabel == null)
  551. {
  552. _richTextLabel = new GUIStyle(EditorStyles.label);
  553. _richTextLabel.richText = true;
  554. _richTextLabel.margin = new RectOffset(2, 2, 0, 0);
  555. }
  556. return _richTextLabel;
  557. }
  558. }
  559. public static GUIStyle ListBulletPoint
  560. {
  561. get
  562. {
  563. if (_listBulletPoint == null)
  564. {
  565. _listBulletPoint = new GUIStyle(EditorStyles.miniBoldLabel);
  566. _listBulletPoint.wordWrap = true;
  567. _listBulletPoint.margin = new RectOffset(6, 2, 0, 0);
  568. }
  569. return _listBulletPoint;
  570. }
  571. }
  572. }
  573. }
  574. }