Нема описа
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.

LongTextArea.cs 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using UnityEngine;
  5. namespace Unity.Burst.Editor
  6. {
  7. internal class LongTextArea
  8. {
  9. private const int kMaxFragment = 2048;
  10. private struct Fragment
  11. {
  12. public int lineCount;
  13. public string text;
  14. }
  15. private string m_Text = "";
  16. private List<Fragment> m_Fragments = null;
  17. private Vector2[] m_AreaSizes = null;
  18. private bool invalidated = true;
  19. private Vector2 finalAreaSize;
  20. public string Text
  21. {
  22. get {
  23. return m_Text;
  24. }
  25. set {
  26. if (value != m_Text)
  27. {
  28. m_Text = value;
  29. m_Fragments = RecomputeFragments(m_Text);
  30. invalidated = true;
  31. m_AreaSizes = new Vector2[m_Fragments.Count];
  32. }
  33. }
  34. }
  35. // Changing the font size doesn't update the text field, so added this to force a recalculation
  36. public void Invalidate()
  37. {
  38. invalidated = true;
  39. }
  40. public void Render(GUIStyle style, Vector2 scrollPos, Rect workingArea)
  41. {
  42. // working area will be valid only during repaint, for the layout event we don't draw the labels
  43. style.richText = true;
  44. if (invalidated)
  45. {
  46. invalidated = false;
  47. int sizeIdx = 0;
  48. finalAreaSize = new Vector2(0.0f, 0.0f);
  49. foreach (var frag in m_Fragments)
  50. {
  51. var size = style.CalcSize(new GUIContent(frag.text));
  52. finalAreaSize.x = Math.Max(finalAreaSize.x, size.x);
  53. finalAreaSize.y += size.y + style.padding.vertical;
  54. m_AreaSizes[sizeIdx++] = size;
  55. }
  56. }
  57. GUILayoutUtility.GetRect(finalAreaSize.x,finalAreaSize.y);
  58. // NB we don't use workingArea or scrollPos, but if we find rendering is still too slow at a later date, we can use
  59. // these values to decide which chunks to render
  60. if (Event.current.type == EventType.Repaint)
  61. {
  62. float positionY = 0.0f;
  63. int sizeIdx = 0;
  64. foreach (var fragment in m_Fragments)
  65. {
  66. var size = m_AreaSizes[sizeIdx++];
  67. GUI.Label(new Rect(0.0f, positionY, finalAreaSize.x, size.y), fragment.text, style);
  68. positionY += size.y + style.padding.vertical;
  69. }
  70. }
  71. }
  72. private static List<Fragment> RecomputeFragments(string text)
  73. {
  74. List<Fragment> result = new List<Fragment>();
  75. string[] pieces = text.Split('\n');
  76. StringBuilder b = new StringBuilder();
  77. int lineCount = 0;
  78. foreach (var piece in pieces)
  79. {
  80. if (b.Length >= kMaxFragment)
  81. {
  82. AddFragment(b, lineCount, result);
  83. lineCount = 0;
  84. }
  85. if (b.Length > 0)
  86. b.Append('\n');
  87. b.Append(piece);
  88. lineCount++;
  89. }
  90. AddFragment(b, lineCount, result);
  91. return result;
  92. }
  93. private static void AddFragment(StringBuilder b, int lineCount, List<Fragment> result)
  94. {
  95. result.Add(new Fragment() { text = b.ToString(), lineCount = lineCount });
  96. b.Length = 0;
  97. }
  98. }
  99. }