123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using UnityEngine;
-
- namespace Unity.Burst.Editor
- {
- internal class LongTextArea
- {
- private const int kMaxFragment = 2048;
-
- private struct Fragment
- {
- public int lineCount;
- public string text;
- }
-
- private string m_Text = "";
- private List<Fragment> m_Fragments = null;
- private Vector2[] m_AreaSizes = null;
- private bool invalidated = true;
- private Vector2 finalAreaSize;
-
- public string Text
- {
- get {
- return m_Text;
- }
- set {
- if (value != m_Text)
- {
- m_Text = value;
- m_Fragments = RecomputeFragments(m_Text);
- invalidated = true;
- m_AreaSizes = new Vector2[m_Fragments.Count];
- }
- }
- }
-
- // Changing the font size doesn't update the text field, so added this to force a recalculation
- public void Invalidate()
- {
- invalidated = true;
- }
-
- public void Render(GUIStyle style, Vector2 scrollPos, Rect workingArea)
- {
- // working area will be valid only during repaint, for the layout event we don't draw the labels
- style.richText = true;
-
- if (invalidated)
- {
- invalidated = false;
- int sizeIdx = 0;
- finalAreaSize = new Vector2(0.0f, 0.0f);
- foreach (var frag in m_Fragments)
- {
- var size = style.CalcSize(new GUIContent(frag.text));
- finalAreaSize.x = Math.Max(finalAreaSize.x, size.x);
- finalAreaSize.y += size.y + style.padding.vertical;
- m_AreaSizes[sizeIdx++] = size;
- }
- }
-
- GUILayoutUtility.GetRect(finalAreaSize.x,finalAreaSize.y);
-
- // NB we don't use workingArea or scrollPos, but if we find rendering is still too slow at a later date, we can use
- // these values to decide which chunks to render
- if (Event.current.type == EventType.Repaint)
- {
- float positionY = 0.0f;
- int sizeIdx = 0;
- foreach (var fragment in m_Fragments)
- {
- var size = m_AreaSizes[sizeIdx++];
- GUI.Label(new Rect(0.0f, positionY, finalAreaSize.x, size.y), fragment.text, style);
- positionY += size.y + style.padding.vertical;
- }
- }
- }
-
- private static List<Fragment> RecomputeFragments(string text)
- {
- List<Fragment> result = new List<Fragment>();
-
- string[] pieces = text.Split('\n');
-
- StringBuilder b = new StringBuilder();
- int lineCount = 0;
-
- foreach (var piece in pieces)
- {
- if (b.Length >= kMaxFragment)
- {
- AddFragment(b, lineCount, result);
- lineCount = 0;
- }
-
- if (b.Length > 0)
- b.Append('\n');
-
- b.Append(piece);
- lineCount++;
- }
-
- AddFragment(b, lineCount, result);
-
- return result;
- }
-
- private static void AddFragment(StringBuilder b, int lineCount, List<Fragment> result)
- {
- result.Add(new Fragment() { text = b.ToString(), lineCount = lineCount });
- b.Length = 0;
- }
- }
-
- }
|