using System; using System.Collections.Generic; using System.Linq; using UnityEngine; [RequireComponent(typeof(MeshRenderer))] [RequireComponent(typeof(MeshFilter))] public class TextRenderer : MonoBehaviour { public float Width { get; private set; } public float Height { get; private set; } public Vector3 CursorPos { get { return new Vector3(this.cursorLocation.x / 100f * this.scale, this.cursorLocation.y / 100f * this.scale, -0.001f); } } public TextAsset FontData; public float scale = 1f; public float TabWidth = 0.5f; public bool Centered; public bool RightAligned; public TextLink textLinkPrefab; [HideInInspector] private Mesh mesh; [HideInInspector] private MeshRenderer render; [Multiline] public string Text; private string lastText; public Color Color = Color.white; private Color lastColor = Color.white; public Color OutlineColor = Color.black; private Color lastOutlineColor = Color.white; public float maxWidth = -1f; public bool scaleToFit; public bool paragraphSpacing; private Vector2 cursorLocation; public void Start() { this.render = base.GetComponent(); MeshFilter component = base.GetComponent(); if (!component.mesh) { this.mesh = new Mesh(); this.mesh.name = "Text" + base.name; component.mesh = this.mesh; this.render.material.SetColor("_OutlineColor", this.OutlineColor); return; } this.mesh = component.mesh; } [ContextMenu("Generate Mesh")] public void GenerateMesh() { this.render = base.GetComponent(); MeshFilter component = base.GetComponent(); if (!component.sharedMesh) { this.mesh = new Mesh(); this.mesh.name = "Text" + base.name; component.mesh = this.mesh; } else { this.mesh = component.sharedMesh; } this.lastText = null; this.lastOutlineColor = this.OutlineColor; this.Update(); } private void Update() { if (this.lastOutlineColor != this.OutlineColor) { this.lastOutlineColor = this.OutlineColor; this.render.material.SetColor("_OutlineColor", this.OutlineColor); } if (this.lastText != this.Text || this.lastColor != this.Color) { this.RefreshMesh(); } } public void RefreshMesh() { if (this.render == null) { this.Start(); } if (this.Text != null) { if (this.Text.Any((char c) => c > '✐')) { FontCache.Instance.SetFont(this, "Korean"); } } FontData fontData = FontCache.Instance.LoadFont(this.FontData); this.lastText = this.Text; this.lastColor = this.Color; float num = this.scale; if (this.scaleToFit) { num = Mathf.Min(this.scale, this.maxWidth / this.GetMaxWidth(fontData, this.lastText)); } else if (this.maxWidth > 0f) { this.lastText = (this.Text = TextRenderer.WrapText(fontData, this.lastText, this.maxWidth)); } List list = new List(this.lastText.Length * 4); List list2 = new List(this.lastText.Length * 4); List list3 = new List(this.lastText.Length * 4); List list4 = new List(this.lastText.Length * 4); int[] array = new int[this.lastText.Length * 6]; this.Width = 0f; this.cursorLocation.x = (this.cursorLocation.y = 0f); int num2 = -1; Vector2 from = default(Vector2); string text = null; int lineStart = 0; int num3 = 0; Color item = this.Color; int? num4 = null; int i = 0; while (i < this.lastText.Length) { int num5 = (int)this.lastText[i]; if (num5 == 91) { if (num2 != 91) { if (this.lastText[i + 1] == '[') { goto IL_422; } num4 = new int?(0); num2 = num5; } } else { if (num4 == null) { goto IL_422; } if (num5 == 93) { if (num2 != 91) { int? num6 = num4; byte r = (byte)((num6 != null) ? new int?(num6.GetValueOrDefault() >> 24 & 255) : null).Value; int? num7 = num4; byte g = (byte)((num7 != null) ? new int?(num7.GetValueOrDefault() >> 16 & 255) : null).Value; int? num8 = num4; item = new Color32(r, g, (byte)((num8 != null) ? new int?(num8.GetValueOrDefault() >> 8 & 255) : null).Value, (byte)(num4 & 255).Value); item.a *= this.Color.a; } else { item = this.Color; } num4 = null; if (text != null) { TextLink textLink = UnityEngine.Object.Instantiate(this.textLinkPrefab, base.transform); textLink.transform.localScale = Vector3.one; Vector3 v = list.Last(); textLink.Set(from, v, text); text = null; } } else if (num5 == 104) { int num9 = this.lastText.IndexOf(']', i); text = this.lastText.Substring(i, num9 - i); from = list[list.Count - 2]; item = new Color(0.5f, 0.5f, 1f); num4 = null; i = num9; } else { num4 = (num4 << 4 | this.CharToInt(num5)); } num2 = num5; } IL_81F: i++; continue; IL_422: if (num5 == 13) { goto IL_81F; } if (num5 == 10) { if (this.Centered) { this.CenterVerts(list, this.cursorLocation.x, lineStart, num); } else if (this.RightAligned) { this.RightAlignVerts(list, this.cursorLocation.x, lineStart, num); } bool flag = this.cursorLocation.x == 0f; this.cursorLocation.x = 0f; if (flag) { this.cursorLocation.y = this.cursorLocation.y - fontData.LineHeight / 2f; } else { this.cursorLocation.y = this.cursorLocation.y - fontData.LineHeight; } lineStart = list.Count; goto IL_81F; } if (num5 == 9) { float num10 = this.cursorLocation.x / 100f; num10 = Mathf.Ceil(num10 / this.TabWidth) * this.TabWidth; this.cursorLocation.x = num10 * 100f; goto IL_81F; } int index; if (!fontData.charMap.TryGetValue(num5, out index)) { Debug.Log("Missing char :" + num5); num5 = -1; index = fontData.charMap[-1]; } Vector4 vector = fontData.bounds[index]; Vector2 textureSize = fontData.TextureSize; Vector3 vector2 = fontData.offsets[index]; float kerning = fontData.GetKerning(num2, num5); float num11 = this.cursorLocation.x + vector2.x + kerning; float num12 = this.cursorLocation.y - vector2.y; list.Add(new Vector3(num11, num12 - vector.w) / 100f * num); list.Add(new Vector3(num11, num12) / 100f * num); list.Add(new Vector3(num11 + vector.z, num12) / 100f * num); list.Add(new Vector3(num11 + vector.z, num12 - vector.w) / 100f * num); list4.Add(item); list4.Add(item); list4.Add(item); list4.Add(item); list2.Add(new Vector2(vector.x / textureSize.x, 1f - (vector.y + vector.w) / textureSize.y)); list2.Add(new Vector2(vector.x / textureSize.x, 1f - vector.y / textureSize.y)); list2.Add(new Vector2((vector.x + vector.z) / textureSize.x, 1f - vector.y / textureSize.y)); list2.Add(new Vector2((vector.x + vector.z) / textureSize.x, 1f - (vector.y + vector.w) / textureSize.y)); Vector4 item2 = fontData.Channels[index]; list3.Add(item2); list3.Add(item2); list3.Add(item2); list3.Add(item2); array[num3 * 6] = num3 * 4; array[num3 * 6 + 1] = num3 * 4 + 1; array[num3 * 6 + 2] = num3 * 4 + 2; array[num3 * 6 + 3] = num3 * 4; array[num3 * 6 + 4] = num3 * 4 + 2; array[num3 * 6 + 5] = num3 * 4 + 3; this.cursorLocation.x = this.cursorLocation.x + (vector2.z + kerning); float num13 = this.cursorLocation.x / 100f * num; if (this.Width < num13) { this.Width = num13; } num2 = num5; num3++; goto IL_81F; } if (this.Centered) { this.CenterVerts(list, this.cursorLocation.x, lineStart, num); this.cursorLocation.x = this.cursorLocation.x / 2f; this.Width /= 2f; } else if (this.RightAligned) { this.RightAlignVerts(list, this.cursorLocation.x, lineStart, num); } this.Height = -(this.cursorLocation.y - fontData.LineHeight) / 100f * num; this.mesh.Clear(); if (list.Count > 0) { this.mesh.SetVertices(list); this.mesh.SetColors(list4); this.mesh.SetUVs(0, list2); this.mesh.SetUVs(1, list3); this.mesh.SetIndices(array, MeshTopology.Triangles, 0); } } private float GetMaxWidth(FontData data, string lastText) { float num = 0f; float num2 = 0f; int last = -1; bool flag = false; int num3 = 0; int num4 = 0; while (num4 < lastText.Length && num3++ <= 1000) { int num5 = (int)lastText[num4]; if (num5 == 91) { flag = true; goto IL_4D; } if (num5 != 93) { goto IL_4D; } flag = false; IL_100: num4++; continue; IL_4D: if (flag || num5 == 13) { goto IL_100; } if (num5 == 10) { last = -1; num2 = 0f; goto IL_100; } if (num5 == 9) { num2 = Mathf.Ceil(num2 / 100f / 0.5f) * 0.5f * 100f; goto IL_100; } int index; if (!data.charMap.TryGetValue(num5, out index)) { Debug.Log("Missing char :" + num5); num5 = -1; index = data.charMap[-1]; } Vector3 vector = data.offsets[index]; num2 += vector.z + data.GetKerning(last, num5); if (num2 > num) { num = num2; } last = num5; goto IL_100; } return num / 100f; } private void RightAlignVerts(List verts, float baseX, int lineStart, float scale) { for (int i = lineStart; i < verts.Count; i++) { Vector3 value = verts[i]; value.x -= baseX / 100f * scale; verts[i] = value; } } private void CenterVerts(List verts, float baseX, int lineStart, float scale) { for (int i = lineStart; i < verts.Count; i++) { Vector3 value = verts[i]; value.x -= baseX / 200f * scale; verts[i] = value; } } private int CharToInt(int c) { if (c < 65) { return c - 48; } if (c < 97) { return 10 + (c - 65); } return 10 + (c - 97); } public static string WrapText(FontData data, string displayTxt, float maxWidth) { float num = 0f; int num2 = -1; int last = -1; bool flag = false; int num3 = 0; int num4 = 0; while (num4 < displayTxt.Length && num3++ <= 1000) { int num5 = (int)displayTxt[num4]; if (num5 == 91) { flag = true; goto IL_49; } if (num5 != 93) { goto IL_49; } flag = false; IL_155: num4++; continue; IL_49: if (flag || num5 == 13) { goto IL_155; } if (num5 == 10) { num2 = -1; last = -1; num = 0f; goto IL_155; } if (num5 == 9) { num = Mathf.Ceil(num / 100f / 0.5f) * 0.5f * 100f; goto IL_155; } int index; if (!data.charMap.TryGetValue(num5, out index)) { Debug.Log("Missing char :" + num5); num5 = -1; index = data.charMap[-1]; } if (num5 == 32) { num2 = num4; } Vector3 vector = data.offsets[index]; num += vector.z + data.GetKerning(last, num5); if (num > maxWidth * 100f) { if (num2 != -1) { displayTxt = displayTxt.Substring(0, num2) + "\n" + displayTxt.Substring(num2 + 1); num4 = num2; } else { displayTxt = displayTxt.Substring(0, num4) + "\n" + displayTxt.Substring(num4); } num2 = -1; num = 0f; } last = num5; goto IL_155; } return displayTxt; } }