InlieText.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. 
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using System.Collections.Generic;
  5. using System.Text.RegularExpressions;
  6. public class InlieText : Text
  7. {
  8. /// <summary>
  9. /// 用正则取标签属性 名称-大小-宽度比例
  10. /// </summary>
  11. private static readonly Regex m_spriteTagRegex =
  12. new Regex(@"<quad name=(.+?) size=(\d*\.?\d+%?) width=(\d*\.?\d+%?) />", RegexOptions.Singleline);
  13. /// <summary>
  14. /// 需要渲染的图片信息列表
  15. /// </summary>
  16. private List<InlineSpriteInfor> listSprite;
  17. /// <summary>
  18. /// 图片资源
  19. /// </summary>
  20. private UGUISpriteAsset m_spriteAsset;
  21. /// <summary>
  22. /// 标签的信息列表
  23. /// </summary>
  24. private List<SpriteTagInfor> listTagInfor;
  25. /// <summary>
  26. /// 图片渲染组件
  27. /// </summary>
  28. private SpriteGraphic m_spriteGraphic;
  29. /// <summary>
  30. /// CanvasRenderer
  31. /// </summary>
  32. private CanvasRenderer m_spriteCanvasRenderer;
  33. /// <summary>
  34. /// 初始化
  35. /// </summary>
  36. protected override void OnEnable()
  37. {
  38. base.OnEnable();
  39. if (m_spriteGraphic == null)
  40. m_spriteGraphic = GetComponentInChildren<SpriteGraphic>();
  41. if (m_spriteCanvasRenderer == null)
  42. m_spriteCanvasRenderer = m_spriteGraphic.GetComponentInChildren<CanvasRenderer>();
  43. m_spriteAsset = m_spriteGraphic.m_spriteAsset;
  44. }
  45. /// <summary>
  46. /// 在设置顶点时调用
  47. /// </summary>
  48. public override void SetVerticesDirty()
  49. {
  50. base.SetVerticesDirty();
  51. //解析标签属性
  52. listTagInfor = new List<SpriteTagInfor>();
  53. foreach (Match match in m_spriteTagRegex.Matches(text))
  54. {
  55. SpriteTagInfor tempSpriteTag = new SpriteTagInfor();
  56. tempSpriteTag.name = match.Groups[1].Value;
  57. tempSpriteTag.index = match.Index;
  58. tempSpriteTag.size = new Vector2(float.Parse(match.Groups[2].Value) * float.Parse(match.Groups[3].Value), float.Parse(match.Groups[2].Value));
  59. listTagInfor.Add(tempSpriteTag);
  60. }
  61. }
  62. /// <summary>
  63. /// 绘制模型
  64. /// </summary>
  65. /// <param name="toFill"></param>
  66. protected override void OnPopulateMesh(VertexHelper toFill)
  67. {
  68. base.OnPopulateMesh(toFill);
  69. //获取所有的UIVertex,绘制一个字符对应6个UIVertex,绘制顺序为012 203
  70. List<UIVertex> listUIVertex = new List<UIVertex>();
  71. toFill.GetUIVertexStream(listUIVertex);
  72. //通过标签信息来设置需要绘制的图片的信息
  73. listSprite = new List<InlineSpriteInfor>();
  74. for (int i = 0; i < listTagInfor.Count; i++)
  75. {
  76. //UGUIText不支持<quad/>标签,表现为乱码,我这里将他的uv全设置为0,清除乱码
  77. for (int m = listTagInfor[i].index * 6; m < listTagInfor[i].index * 6 + 6; m++)
  78. {
  79. UIVertex tempVertex = listUIVertex[m];
  80. tempVertex.uv0 = Vector2.zero;
  81. listUIVertex[m] = tempVertex;
  82. }
  83. InlineSpriteInfor tempSprite = new InlineSpriteInfor();
  84. //如果图片在第一个位置,则计算他的位置为文本的初始点位置
  85. //否,则返回上一个字符的第三个UIVertex的position,这是根据他的顶点的绘制顺序所获得的
  86. if (listTagInfor[i].index == 0)
  87. {
  88. Vector2 anchorPivot = GetTextAnchorPivot(alignment);
  89. Vector2 rectSize = rectTransform.sizeDelta;
  90. tempSprite.textpos = -rectSize / 2.0f + new Vector2(rectSize.x * anchorPivot.x, rectSize.y * anchorPivot.y - listTagInfor[i].size.y);
  91. }
  92. else
  93. tempSprite.textpos = listUIVertex[listTagInfor[i].index * 6 - 4].position;
  94. //设置图片的位置
  95. tempSprite.vertices = new Vector3[4];
  96. tempSprite.vertices[0] = new Vector3(0, 0, 0) + tempSprite.textpos;
  97. tempSprite.vertices[1] = new Vector3(listTagInfor[i].size.x, listTagInfor[i].size.y, 0) + tempSprite.textpos;
  98. tempSprite.vertices[2] = new Vector3(listTagInfor[i].size.x, 0, 0) + tempSprite.textpos;
  99. tempSprite.vertices[3] = new Vector3(0, listTagInfor[i].size.y, 0) + tempSprite.textpos;
  100. //计算其uv
  101. Rect spriteRect = m_spriteAsset.listSpriteInfor[0].rect;
  102. for (int j = 0; j < m_spriteAsset.listSpriteInfor.Count; j++)
  103. {
  104. //通过标签的名称去索引spriteAsset里所对应的sprite的名称
  105. if (listTagInfor[i].name == m_spriteAsset.listSpriteInfor[j].name)
  106. spriteRect = m_spriteAsset.listSpriteInfor[j].rect;
  107. }
  108. Vector2 texSize = new Vector2(m_spriteAsset.texSource.width, m_spriteAsset.texSource.height);
  109. tempSprite.uv = new Vector2[4];
  110. tempSprite.uv[0] = new Vector2(spriteRect.x / texSize.x, spriteRect.y / texSize.y);
  111. tempSprite.uv[1] = new Vector2((spriteRect.x + spriteRect.width) / texSize.x, (spriteRect.y + spriteRect.height) / texSize.y);
  112. tempSprite.uv[2] = new Vector2((spriteRect.x + spriteRect.width) / texSize.x, spriteRect.y / texSize.y);
  113. tempSprite.uv[3] = new Vector2(spriteRect.x / texSize.x, (spriteRect.y + spriteRect.height) / texSize.y);
  114. //声明三角顶点所需要的数组
  115. tempSprite.triangles = new int[6];
  116. listSprite.Add(tempSprite);
  117. }
  118. //清除<quad />标签的乱码 重新绘制
  119. toFill.Clear();
  120. toFill.AddUIVertexTriangleStream(listUIVertex);
  121. DrawSprite();
  122. }
  123. /// <summary>
  124. /// 绘制图片
  125. /// </summary>
  126. void DrawSprite()
  127. {
  128. Mesh m_spriteMesh = new Mesh();
  129. List<Vector3> tempVertices = new List<Vector3>();
  130. List<Vector2> tempUv = new List<Vector2>();
  131. List<int> tempTriangles = new List<int>();
  132. for (int i = 0; i < listSprite.Count; i++)
  133. {
  134. for (int j = 0; j < listSprite[i].vertices.Length; j++)
  135. {
  136. tempVertices.Add(listSprite[i].vertices[j]);
  137. }
  138. for (int j = 0; j < listSprite[i].uv.Length; j++)
  139. {
  140. tempUv.Add(listSprite[i].uv[j]);
  141. }
  142. for (int j = 0; j < listSprite[i].triangles.Length; j++)
  143. {
  144. tempTriangles.Add(listSprite[i].triangles[j]);
  145. }
  146. }
  147. //计算顶点绘制顺序
  148. for (int i = 0; i < tempTriangles.Count; i++)
  149. {
  150. if (i % 6 == 0)
  151. {
  152. int num = i / 6;
  153. tempTriangles[i] = 0 + 4 * num;
  154. tempTriangles[i + 1] = 1 + 4 * num;
  155. tempTriangles[i + 2] = 2 + 4 * num;
  156. tempTriangles[i + 3] = 1 + 4 * num;
  157. tempTriangles[i + 4] = 0 + 4 * num;
  158. tempTriangles[i + 5] = 3 + 4 * num;
  159. }
  160. }
  161. m_spriteMesh.vertices = tempVertices.ToArray();
  162. m_spriteMesh.uv = tempUv.ToArray();
  163. m_spriteMesh.triangles = tempTriangles.ToArray();
  164. if (m_spriteMesh == null)
  165. return;
  166. m_spriteCanvasRenderer.SetMesh(m_spriteMesh);
  167. m_spriteGraphic.UpdateMaterial();
  168. }
  169. }
  170. [System.Serializable]
  171. public class SpriteTagInfor
  172. {
  173. /// <summary>
  174. /// sprite名称
  175. /// </summary>
  176. public string name;
  177. /// <summary>
  178. /// 对应的字符索引
  179. /// </summary>
  180. public int index;
  181. /// <summary>
  182. /// 大小
  183. /// </summary>
  184. public Vector2 size;
  185. }
  186. [System.Serializable]
  187. public class InlineSpriteInfor
  188. {
  189. // 文字的最后的位置
  190. public Vector3 textpos;
  191. // 4 顶点
  192. public Vector3[] vertices;
  193. //4 uv
  194. public Vector2[] uv;
  195. //6 三角顶点顺序
  196. public int[] triangles;
  197. }