TextMeshPro.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. using UnityEngine;
  2. using System;
  3. using UnityEngine.UI;
  4. namespace TMPro
  5. {
  6. [DisallowMultipleComponent]
  7. [RequireComponent(typeof(MeshRenderer))]
  8. [AddComponentMenu("Mesh/TextMeshPro - Text")]
  9. [ExecuteAlways]
  10. [HelpURL("https://docs.unity3d.com/Packages/com.unity.textmeshpro@2.1")]
  11. public partial class TextMeshPro : TMP_Text, ILayoutElement
  12. {
  13. // Public Properties and Serializable Properties
  14. /// <summary>
  15. /// Sets the Renderer's sorting Layer ID
  16. /// </summary>
  17. public int sortingLayerID
  18. {
  19. get
  20. {
  21. if (renderer == null)
  22. return 0;
  23. return m_renderer.sortingLayerID;
  24. }
  25. set
  26. {
  27. if (renderer == null)
  28. return;
  29. m_renderer.sortingLayerID = value;
  30. _SortingLayerID = value;
  31. }
  32. }
  33. [SerializeField]
  34. internal int _SortingLayerID;
  35. /// <summary>
  36. /// Sets the Renderer's sorting order within the assigned layer.
  37. /// </summary>
  38. public int sortingOrder
  39. {
  40. get
  41. {
  42. if (renderer == null)
  43. return 0;
  44. return m_renderer.sortingOrder;
  45. }
  46. set
  47. {
  48. if (renderer == null)
  49. return;
  50. m_renderer.sortingOrder = value;
  51. _SortingOrder = value;
  52. }
  53. }
  54. [SerializeField]
  55. internal int _SortingOrder;
  56. /// <summary>
  57. /// Determines if the size of the text container will be adjusted to fit the text object when it is first created.
  58. /// </summary>
  59. public override bool autoSizeTextContainer
  60. {
  61. get { return m_autoSizeTextContainer; }
  62. set { if (m_autoSizeTextContainer == value) return; m_autoSizeTextContainer = value; if (m_autoSizeTextContainer) { TMP_UpdateManager.RegisterTextElementForLayoutRebuild(this); SetLayoutDirty(); } }
  63. }
  64. /// <summary>
  65. /// Returns a reference to the Text Container
  66. /// </summary>
  67. [Obsolete("The TextContainer is now obsolete. Use the RectTransform instead.")]
  68. public TextContainer textContainer
  69. {
  70. get
  71. {
  72. return null;
  73. }
  74. }
  75. /// <summary>
  76. /// Returns a reference to the Transform
  77. /// </summary>
  78. public new Transform transform
  79. {
  80. get
  81. {
  82. if (m_transform == null)
  83. m_transform = GetComponent<Transform>();
  84. return m_transform;
  85. }
  86. }
  87. #pragma warning disable 0108
  88. /// <summary>
  89. /// Returns the rendered assigned to the text object.
  90. /// </summary>
  91. public Renderer renderer
  92. {
  93. get
  94. {
  95. if (m_renderer == null)
  96. m_renderer = GetComponent<Renderer>();
  97. return m_renderer;
  98. }
  99. }
  100. /// <summary>
  101. /// Returns the mesh assigned to the text object.
  102. /// </summary>
  103. public override Mesh mesh
  104. {
  105. get
  106. {
  107. if (m_mesh == null)
  108. {
  109. m_mesh = new Mesh();
  110. m_mesh.hideFlags = HideFlags.HideAndDontSave;
  111. }
  112. return m_mesh;
  113. }
  114. }
  115. /// <summary>
  116. /// Returns the Mesh Filter of the text object.
  117. /// </summary>
  118. public MeshFilter meshFilter
  119. {
  120. get
  121. {
  122. if (m_meshFilter == null)
  123. {
  124. m_meshFilter = GetComponent<MeshFilter>();
  125. if (m_meshFilter == null)
  126. {
  127. m_meshFilter = gameObject.AddComponent<MeshFilter>();
  128. m_meshFilter.hideFlags = HideFlags.HideInInspector | HideFlags.HideAndDontSave;
  129. }
  130. }
  131. return m_meshFilter;
  132. }
  133. }
  134. // MASKING RELATED PROPERTIES
  135. /// <summary>
  136. /// Sets the mask type
  137. /// </summary>
  138. public MaskingTypes maskType
  139. {
  140. get { return m_maskType; }
  141. set { m_maskType = value; SetMask(m_maskType); }
  142. }
  143. /// <summary>
  144. /// Function used to set the mask type and coordinates in World Space
  145. /// </summary>
  146. /// <param name="type"></param>
  147. /// <param name="maskCoords"></param>
  148. public void SetMask(MaskingTypes type, Vector4 maskCoords)
  149. {
  150. SetMask(type);
  151. SetMaskCoordinates(maskCoords);
  152. }
  153. /// <summary>
  154. /// Function used to set the mask type, coordinates and softness
  155. /// </summary>
  156. /// <param name="type"></param>
  157. /// <param name="maskCoords"></param>
  158. /// <param name="softnessX"></param>
  159. /// <param name="softnessY"></param>
  160. public void SetMask(MaskingTypes type, Vector4 maskCoords, float softnessX, float softnessY)
  161. {
  162. SetMask(type);
  163. SetMaskCoordinates(maskCoords, softnessX, softnessY);
  164. }
  165. /// <summary>
  166. /// Schedule rebuilding of the text geometry.
  167. /// </summary>
  168. public override void SetVerticesDirty()
  169. {
  170. //Debug.Log("***** SetVerticesDirty() called on object [" + this.name + "] at frame [" + Time.frameCount + "] *****");
  171. if (this == null || !this.IsActive())
  172. return;
  173. TMP_UpdateManager.RegisterTextElementForGraphicRebuild(this);
  174. }
  175. /// <summary>
  176. ///
  177. /// </summary>
  178. public override void SetLayoutDirty()
  179. {
  180. m_isPreferredWidthDirty = true;
  181. m_isPreferredHeightDirty = true;
  182. if (this == null || !this.IsActive())
  183. return;
  184. LayoutRebuilder.MarkLayoutForRebuild(this.rectTransform);
  185. m_isLayoutDirty = true;
  186. }
  187. /// <summary>
  188. /// Schedule updating of the material used by the text object.
  189. /// </summary>
  190. public override void SetMaterialDirty()
  191. {
  192. //Debug.Log("SetMaterialDirty()");
  193. //if (!this.IsActive())
  194. // return;
  195. //m_isMaterialDirty = true;
  196. UpdateMaterial();
  197. //TMP_UpdateManager.RegisterTextElementForGraphicRebuild(this);
  198. }
  199. /// <summary>
  200. ///
  201. /// </summary>
  202. public override void SetAllDirty()
  203. {
  204. m_isInputParsingRequired = true;
  205. SetLayoutDirty();
  206. SetVerticesDirty();
  207. SetMaterialDirty();
  208. }
  209. /// <summary>
  210. ///
  211. /// </summary>
  212. /// <param name="update"></param>
  213. public override void Rebuild(CanvasUpdate update)
  214. {
  215. if (this == null) return;
  216. if (update == CanvasUpdate.Prelayout)
  217. {
  218. if (m_autoSizeTextContainer)
  219. {
  220. m_rectTransform.sizeDelta = GetPreferredValues(Mathf.Infinity, Mathf.Infinity);
  221. }
  222. }
  223. else if (update == CanvasUpdate.PreRender)
  224. {
  225. this.OnPreRenderObject();
  226. if (!m_isMaterialDirty) return;
  227. UpdateMaterial();
  228. m_isMaterialDirty = false;
  229. }
  230. }
  231. /// <summary>
  232. ///
  233. /// </summary>
  234. protected override void UpdateMaterial()
  235. {
  236. //Debug.Log("***** UpdateMaterial() called on object ID " + GetInstanceID() + ". *****");
  237. //if (!this.IsActive())
  238. // return;
  239. if (renderer == null || m_sharedMaterial == null)
  240. return;
  241. // Only update the material if it has changed.
  242. if (m_renderer.sharedMaterial == null || m_renderer.sharedMaterial.GetInstanceID() != m_sharedMaterial.GetInstanceID())
  243. m_renderer.sharedMaterial = m_sharedMaterial;
  244. }
  245. /// <summary>
  246. /// Function to be used to force recomputing of character padding when Shader / Material properties have been changed via script.
  247. /// </summary>
  248. public override void UpdateMeshPadding()
  249. {
  250. m_padding = ShaderUtilities.GetPadding(m_sharedMaterial, m_enableExtraPadding, m_isUsingBold);
  251. m_isMaskingEnabled = ShaderUtilities.IsMaskingEnabled(m_sharedMaterial);
  252. m_havePropertiesChanged = true;
  253. checkPaddingRequired = false;
  254. // Return if text object is not awake yet.
  255. if (m_textInfo == null) return;
  256. // Update sub text objects
  257. for (int i = 1; i < m_textInfo.materialCount; i++)
  258. m_subTextObjects[i].UpdateMeshPadding(m_enableExtraPadding, m_isUsingBold);
  259. }
  260. /// <summary>
  261. /// Function to force regeneration of the text object before its normal process time. This is useful when changes to the text object properties need to be applied immediately.
  262. /// </summary>
  263. /// <param name="ignoreActiveState">Ignore Active State of text objects. Inactive objects are ignored by default.</param>
  264. /// <param name="forceTextReparsing">Force re-parsing of the text.</param>
  265. public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceTextReparsing = false)
  266. {
  267. m_havePropertiesChanged = true;
  268. m_ignoreActiveState = ignoreActiveState;
  269. m_isInputParsingRequired = m_isInputParsingRequired ? true : forceTextReparsing;
  270. OnPreRenderObject();
  271. }
  272. /// <summary>
  273. /// Function used to evaluate the length of a text string.
  274. /// </summary>
  275. /// <param name="text"></param>
  276. /// <returns></returns>
  277. public override TMP_TextInfo GetTextInfo(string text)
  278. {
  279. StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer);
  280. SetArraySizes(m_InternalParsingBuffer);
  281. m_renderMode = TextRenderFlags.DontRender;
  282. ComputeMarginSize();
  283. GenerateTextMesh();
  284. m_renderMode = TextRenderFlags.Render;
  285. return this.textInfo;
  286. }
  287. /// <summary>
  288. /// Function to clear the geometry of the Primary and Sub Text objects.
  289. /// </summary>
  290. public override void ClearMesh(bool updateMesh)
  291. {
  292. if (m_textInfo.meshInfo[0].mesh == null) m_textInfo.meshInfo[0].mesh = m_mesh;
  293. m_textInfo.ClearMeshInfo(updateMesh);
  294. }
  295. /// <summary>
  296. /// Event to allow users to modify the content of the text info before the text is rendered.
  297. /// </summary>
  298. public override event Action<TMP_TextInfo> OnPreRenderText;
  299. /// <summary>
  300. /// Function to update the geometry of the main and sub text objects.
  301. /// </summary>
  302. /// <param name="mesh"></param>
  303. /// <param name="index"></param>
  304. public override void UpdateGeometry(Mesh mesh, int index)
  305. {
  306. mesh.RecalculateBounds();
  307. }
  308. /// <summary>
  309. /// Function to upload the updated vertex data and renderer.
  310. /// </summary>
  311. public override void UpdateVertexData(TMP_VertexDataUpdateFlags flags)
  312. {
  313. int materialCount = m_textInfo.materialCount;
  314. for (int i = 0; i < materialCount; i++)
  315. {
  316. Mesh mesh;
  317. if (i == 0)
  318. mesh = m_mesh;
  319. else
  320. {
  321. // Clear unused vertices
  322. // TODO: Causes issues when sorting geometry as last vertex data attribute get wiped out.
  323. //m_textInfo.meshInfo[i].ClearUnusedVertices();
  324. mesh = m_subTextObjects[i].mesh;
  325. }
  326. //mesh.MarkDynamic();
  327. if ((flags & TMP_VertexDataUpdateFlags.Vertices) == TMP_VertexDataUpdateFlags.Vertices)
  328. mesh.vertices = m_textInfo.meshInfo[i].vertices;
  329. if ((flags & TMP_VertexDataUpdateFlags.Uv0) == TMP_VertexDataUpdateFlags.Uv0)
  330. mesh.uv = m_textInfo.meshInfo[i].uvs0;
  331. if ((flags & TMP_VertexDataUpdateFlags.Uv2) == TMP_VertexDataUpdateFlags.Uv2)
  332. mesh.uv2 = m_textInfo.meshInfo[i].uvs2;
  333. //if ((flags & TMP_VertexDataUpdateFlags.Uv4) == TMP_VertexDataUpdateFlags.Uv4)
  334. // mesh.uv4 = m_textInfo.meshInfo[i].uvs4;
  335. if ((flags & TMP_VertexDataUpdateFlags.Colors32) == TMP_VertexDataUpdateFlags.Colors32)
  336. mesh.colors32 = m_textInfo.meshInfo[i].colors32;
  337. mesh.RecalculateBounds();
  338. }
  339. }
  340. /// <summary>
  341. /// Function to upload the updated vertex data and renderer.
  342. /// </summary>
  343. public override void UpdateVertexData()
  344. {
  345. int materialCount = m_textInfo.materialCount;
  346. for (int i = 0; i < materialCount; i++)
  347. {
  348. Mesh mesh;
  349. if (i == 0)
  350. mesh = m_mesh;
  351. else
  352. {
  353. // Clear unused vertices
  354. m_textInfo.meshInfo[i].ClearUnusedVertices();
  355. mesh = m_subTextObjects[i].mesh;
  356. }
  357. //mesh.MarkDynamic();
  358. mesh.vertices = m_textInfo.meshInfo[i].vertices;
  359. mesh.uv = m_textInfo.meshInfo[i].uvs0;
  360. mesh.uv2 = m_textInfo.meshInfo[i].uvs2;
  361. //mesh.uv4 = m_textInfo.meshInfo[i].uvs4;
  362. mesh.colors32 = m_textInfo.meshInfo[i].colors32;
  363. mesh.RecalculateBounds();
  364. }
  365. }
  366. public void UpdateFontAsset()
  367. {
  368. LoadFontAsset();
  369. }
  370. private bool m_currentAutoSizeMode;
  371. public void CalculateLayoutInputHorizontal() { }
  372. public void CalculateLayoutInputVertical() { }
  373. }
  374. }