Text.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. using System;
  2. using System.Collections.Generic;
  3. namespace UnityEngine.UI
  4. {
  5. [RequireComponent(typeof(CanvasRenderer))]
  6. [AddComponentMenu("UI/Text", 10)]
  7. /// <summary>
  8. /// The default Graphic to draw font data to screen.
  9. /// </summary>
  10. public class Text : MaskableGraphic, ILayoutElement
  11. {
  12. [SerializeField] private FontData m_FontData = FontData.defaultFontData;
  13. #if UNITY_EDITOR
  14. // needed to track font changes from the inspector
  15. private Font m_LastTrackedFont;
  16. #endif
  17. [TextArea(3, 10)][SerializeField] protected string m_Text = String.Empty;
  18. private TextGenerator m_TextCache;
  19. private TextGenerator m_TextCacheForLayout;
  20. static protected Material s_DefaultText = null;
  21. // We use this flag instead of Unregistering/Registering the callback to avoid allocation.
  22. [NonSerialized] protected bool m_DisableFontTextureRebuiltCallback = false;
  23. protected Text()
  24. {
  25. useLegacyMeshGeneration = false;
  26. }
  27. /// <summary>
  28. /// The cached TextGenerator used when generating visible Text.
  29. /// </summary>
  30. public TextGenerator cachedTextGenerator
  31. {
  32. get { return m_TextCache ?? (m_TextCache = (m_Text.Length != 0 ? new TextGenerator(m_Text.Length) : new TextGenerator())); }
  33. }
  34. /// <summary>
  35. /// The cached TextGenerator used when determine Layout
  36. /// </summary>
  37. public TextGenerator cachedTextGeneratorForLayout
  38. {
  39. get { return m_TextCacheForLayout ?? (m_TextCacheForLayout = new TextGenerator()); }
  40. }
  41. /// <summary>
  42. /// Text's texture comes from the font.
  43. /// </summary>
  44. public override Texture mainTexture
  45. {
  46. get
  47. {
  48. if (font != null && font.material != null && font.material.mainTexture != null)
  49. return font.material.mainTexture;
  50. if (m_Material != null)
  51. return m_Material.mainTexture;
  52. return base.mainTexture;
  53. }
  54. }
  55. /// <summary>
  56. /// Called by the FontUpdateTracker when the texture associated with a font is modified.
  57. /// </summary>
  58. public void FontTextureChanged()
  59. {
  60. // Only invoke if we are not destroyed.
  61. if (!this)
  62. return;
  63. if (m_DisableFontTextureRebuiltCallback)
  64. return;
  65. cachedTextGenerator.Invalidate();
  66. if (!IsActive())
  67. return;
  68. // this is a bit hacky, but it is currently the
  69. // cleanest solution....
  70. // if we detect the font texture has changed and are in a rebuild loop
  71. // we just regenerate the verts for the new UV's
  72. if (CanvasUpdateRegistry.IsRebuildingGraphics() || CanvasUpdateRegistry.IsRebuildingLayout())
  73. UpdateGeometry();
  74. else
  75. {
  76. SetAllDirty();
  77. }
  78. }
  79. /// <summary>
  80. /// The Font used by the text.
  81. /// </summary>
  82. /// <remarks>
  83. /// This is the font used by the Text component. Use it to alter or return the font from the Text. There are many free fonts available online.
  84. /// </remarks>
  85. /// <example>
  86. /// <code>
  87. /// //Create a new Text GameObject by going to Create>UI>Text in the Editor. Attach this script to the Text GameObject. Then, choose or click and drag your own font into the Font section in the Inspector window.
  88. ///
  89. /// using UnityEngine;
  90. /// using UnityEngine.UI;
  91. ///
  92. /// public class TextFontExample : MonoBehaviour
  93. /// {
  94. /// Text m_Text;
  95. /// //Attach your own Font in the Inspector
  96. /// public Font m_Font;
  97. ///
  98. /// void Start()
  99. /// {
  100. /// //Fetch the Text component from the GameObject
  101. /// m_Text = GetComponent<Text>();
  102. /// }
  103. ///
  104. /// void Update()
  105. /// {
  106. /// if (Input.GetKey(KeyCode.Space))
  107. /// {
  108. /// //Change the Text Font to the Font attached in the Inspector
  109. /// m_Text.font = m_Font;
  110. /// //Change the Text to the message below
  111. /// m_Text.text = "My Font Changed!";
  112. /// }
  113. /// }
  114. /// }
  115. /// </code>
  116. /// </example>
  117. public Font font
  118. {
  119. get
  120. {
  121. return m_FontData.font;
  122. }
  123. set
  124. {
  125. if (m_FontData.font == value)
  126. return;
  127. if (isActiveAndEnabled)
  128. FontUpdateTracker.UntrackText(this);
  129. m_FontData.font = value;
  130. if (isActiveAndEnabled)
  131. FontUpdateTracker.TrackText(this);
  132. #if UNITY_EDITOR
  133. // needed to track font changes from the inspector
  134. m_LastTrackedFont = value;
  135. #endif
  136. SetAllDirty();
  137. }
  138. }
  139. /// <summary>
  140. /// Text that's being displayed by the Text.
  141. /// </summary>
  142. /// <remarks>
  143. /// This is the string value of a Text component. Use this to read or edit the message displayed in Text.
  144. /// </remarks>
  145. /// <example>
  146. /// <code>
  147. /// using UnityEngine;
  148. /// using UnityEngine.UI;
  149. ///
  150. /// public class Example : MonoBehaviour
  151. /// {
  152. /// public Text m_MyText;
  153. ///
  154. /// void Start()
  155. /// {
  156. /// //Text sets your text to say this message
  157. /// m_MyText.text = "This is my text";
  158. /// }
  159. ///
  160. /// void Update()
  161. /// {
  162. /// //Press the space key to change the Text message
  163. /// if (Input.GetKey(KeyCode.Space))
  164. /// {
  165. /// m_MyText.text = "My text has now changed.";
  166. /// }
  167. /// }
  168. /// }
  169. /// </code>
  170. /// </example>
  171. public virtual string text
  172. {
  173. get
  174. {
  175. return m_Text;
  176. }
  177. set
  178. {
  179. if (String.IsNullOrEmpty(value))
  180. {
  181. if (String.IsNullOrEmpty(m_Text))
  182. return;
  183. m_Text = "";
  184. SetVerticesDirty();
  185. }
  186. else if (m_Text != value)
  187. {
  188. m_Text = value;
  189. SetVerticesDirty();
  190. SetLayoutDirty();
  191. }
  192. }
  193. }
  194. /// <summary>
  195. /// Whether this Text will support rich text.
  196. /// </summary>
  197. public bool supportRichText
  198. {
  199. get
  200. {
  201. return m_FontData.richText;
  202. }
  203. set
  204. {
  205. if (m_FontData.richText == value)
  206. return;
  207. m_FontData.richText = value;
  208. SetVerticesDirty();
  209. SetLayoutDirty();
  210. }
  211. }
  212. /// <summary>
  213. /// Should the text be allowed to auto resized.
  214. /// </summary>
  215. public bool resizeTextForBestFit
  216. {
  217. get
  218. {
  219. return m_FontData.bestFit;
  220. }
  221. set
  222. {
  223. if (m_FontData.bestFit == value)
  224. return;
  225. m_FontData.bestFit = value;
  226. SetVerticesDirty();
  227. SetLayoutDirty();
  228. }
  229. }
  230. /// <summary>
  231. /// The minimum size the text is allowed to be.
  232. /// </summary>
  233. public int resizeTextMinSize
  234. {
  235. get
  236. {
  237. return m_FontData.minSize;
  238. }
  239. set
  240. {
  241. if (m_FontData.minSize == value)
  242. return;
  243. m_FontData.minSize = value;
  244. SetVerticesDirty();
  245. SetLayoutDirty();
  246. }
  247. }
  248. /// <summary>
  249. /// The maximum size the text is allowed to be. 1 = infinitely large.
  250. /// </summary>
  251. public int resizeTextMaxSize
  252. {
  253. get
  254. {
  255. return m_FontData.maxSize;
  256. }
  257. set
  258. {
  259. if (m_FontData.maxSize == value)
  260. return;
  261. m_FontData.maxSize = value;
  262. SetVerticesDirty();
  263. SetLayoutDirty();
  264. }
  265. }
  266. /// <summary>
  267. /// The positioning of the text reliative to its [[RectTransform]].
  268. /// </summary>
  269. /// <remarks>
  270. /// This is the positioning of the Text relative to its RectTransform. You can alter this via script or in the Inspector of a Text component using the buttons in the Alignment section.
  271. /// </remarks>
  272. /// <example>
  273. /// <code>
  274. /// //Create a Text GameObject by going to __Create__>__UI__>__Text__. Attach this script to the GameObject to see it working.
  275. ///
  276. /// using UnityEngine;
  277. /// using UnityEngine.UI;
  278. ///
  279. /// public class UITextAlignment : MonoBehaviour
  280. /// {
  281. /// Text m_Text;
  282. ///
  283. /// void Start()
  284. /// {
  285. /// //Fetch the Text Component
  286. /// m_Text = GetComponent<Text>();
  287. /// //Switch the Text alignment to the middle
  288. /// m_Text.alignment = TextAnchor.MiddleCenter;
  289. /// }
  290. ///
  291. /// //This is a legacy function used for an instant demonstration. See the <a href="https://unity3d.com/learn/tutorials/s/user-interface-ui">UI Tutorials pages </a> and [[wiki:UISystem|UI Section]] of the manual for more information on creating your own buttons etc.
  292. /// void OnGUI()
  293. /// {
  294. /// //Press this Button to change the Text alignment to the lower right
  295. /// if (GUI.Button(new Rect(0, 0, 100, 40), "Lower Right"))
  296. /// {
  297. /// m_Text.alignment = TextAnchor.LowerRight;
  298. /// }
  299. ///
  300. /// //Press this Button to change the Text alignment to the upper left
  301. /// if (GUI.Button(new Rect(150, 0, 100, 40), "Upper Left"))
  302. /// {
  303. /// m_Text.alignment = TextAnchor.UpperLeft;
  304. /// }
  305. /// }
  306. /// }
  307. /// </code>
  308. /// </example>
  309. public TextAnchor alignment
  310. {
  311. get
  312. {
  313. return m_FontData.alignment;
  314. }
  315. set
  316. {
  317. if (m_FontData.alignment == value)
  318. return;
  319. m_FontData.alignment = value;
  320. SetVerticesDirty();
  321. SetLayoutDirty();
  322. }
  323. }
  324. /// <summary>
  325. /// Use the extents of glyph geometry to perform horizontal alignment rather than glyph metrics.
  326. /// </summary>
  327. /// <remarks>
  328. /// This can result in better fitting left and right alignment, but may result in incorrect positioning when attempting to overlay multiple fonts (such as a specialized outline font) on top of each other.
  329. /// </remarks>
  330. public bool alignByGeometry
  331. {
  332. get
  333. {
  334. return m_FontData.alignByGeometry;
  335. }
  336. set
  337. {
  338. if (m_FontData.alignByGeometry == value)
  339. return;
  340. m_FontData.alignByGeometry = value;
  341. SetVerticesDirty();
  342. }
  343. }
  344. /// <summary>
  345. /// The size that the Font should render at. Unit of measure is Points.
  346. /// </summary>
  347. /// <remarks>
  348. /// This is the size of the Font of the Text. Use this to fetch or change the size of the Font. When changing the Font size, remember to take into account the RectTransform of the Text. Larger Font sizes or messages may not fit in certain rectangle sizes and do not show in the Scene.
  349. /// Note: Point size is not consistent from one font to another.
  350. /// </remarks>
  351. /// <example>
  352. /// <code>
  353. /// //For this script to work, create a new Text GameObject by going to Create>U>Text. Attach the script to the Text GameObject. Make sure the GameObject has a RectTransform component.
  354. ///
  355. /// using UnityEngine;
  356. /// using UnityEngine.UI;
  357. ///
  358. /// public class Example : MonoBehaviour
  359. /// {
  360. /// Text m_Text;
  361. /// RectTransform m_RectTransform;
  362. ///
  363. /// void Start()
  364. /// {
  365. /// //Fetch the Text and RectTransform components from the GameObject
  366. /// m_Text = GetComponent<Text>();
  367. /// m_RectTransform = GetComponent<RectTransform>();
  368. /// }
  369. ///
  370. /// void Update()
  371. /// {
  372. /// //Press the space key to change the Font size
  373. /// if (Input.GetKey(KeyCode.Space))
  374. /// {
  375. /// changeFontSize();
  376. /// }
  377. /// }
  378. ///
  379. /// void changeFontSize()
  380. /// {
  381. /// //Change the Font Size to 16
  382. /// m_Text.fontSize = 30;
  383. ///
  384. /// //Change the RectTransform size to allow larger fonts and sentences
  385. /// m_RectTransform.sizeDelta = new Vector2(m_Text.fontSize * 10, 100);
  386. ///
  387. /// //Change the m_Text text to the message below
  388. /// m_Text.text = "I changed my Font size!";
  389. /// }
  390. /// }
  391. /// </code>
  392. /// </example>
  393. public int fontSize
  394. {
  395. get
  396. {
  397. return m_FontData.fontSize;
  398. }
  399. set
  400. {
  401. if (m_FontData.fontSize == value)
  402. return;
  403. m_FontData.fontSize = value;
  404. SetVerticesDirty();
  405. SetLayoutDirty();
  406. }
  407. }
  408. /// <summary>
  409. /// Horizontal overflow mode.
  410. /// </summary>
  411. /// <remarks>
  412. /// When set to HorizontalWrapMode.Overflow, text can exceed the horizontal boundaries of the Text graphic. When set to HorizontalWrapMode.Wrap, text will be word-wrapped to fit within the boundaries.
  413. /// </remarks>
  414. public HorizontalWrapMode horizontalOverflow
  415. {
  416. get
  417. {
  418. return m_FontData.horizontalOverflow;
  419. }
  420. set
  421. {
  422. if (m_FontData.horizontalOverflow == value)
  423. return;
  424. m_FontData.horizontalOverflow = value;
  425. SetVerticesDirty();
  426. SetLayoutDirty();
  427. }
  428. }
  429. /// <summary>
  430. /// Vertical overflow mode.
  431. /// </summary>
  432. public VerticalWrapMode verticalOverflow
  433. {
  434. get
  435. {
  436. return m_FontData.verticalOverflow;
  437. }
  438. set
  439. {
  440. if (m_FontData.verticalOverflow == value)
  441. return;
  442. m_FontData.verticalOverflow = value;
  443. SetVerticesDirty();
  444. SetLayoutDirty();
  445. }
  446. }
  447. /// <summary>
  448. /// Line spacing, specified as a factor of font line height. A value of 1 will produce normal line spacing.
  449. /// </summary>
  450. public float lineSpacing
  451. {
  452. get
  453. {
  454. return m_FontData.lineSpacing;
  455. }
  456. set
  457. {
  458. if (m_FontData.lineSpacing == value)
  459. return;
  460. m_FontData.lineSpacing = value;
  461. SetVerticesDirty();
  462. SetLayoutDirty();
  463. }
  464. }
  465. /// <summary>
  466. /// Font style used by the Text's text.
  467. /// </summary>
  468. public FontStyle fontStyle
  469. {
  470. get
  471. {
  472. return m_FontData.fontStyle;
  473. }
  474. set
  475. {
  476. if (m_FontData.fontStyle == value)
  477. return;
  478. m_FontData.fontStyle = value;
  479. SetVerticesDirty();
  480. SetLayoutDirty();
  481. }
  482. }
  483. /// <summary>
  484. /// Provides information about how fonts are scale to the screen.
  485. /// </summary>
  486. /// <remarks>
  487. /// For dynamic fonts, the value is equivalent to the scale factor of the canvas. For non-dynamic fonts, the value is calculated from the requested text size and the size from the font.
  488. /// </remarks>
  489. public float pixelsPerUnit
  490. {
  491. get
  492. {
  493. var localCanvas = canvas;
  494. if (!localCanvas)
  495. return 1;
  496. // For dynamic fonts, ensure we use one pixel per pixel on the screen.
  497. if (!font || font.dynamic)
  498. return localCanvas.scaleFactor;
  499. // For non-dynamic fonts, calculate pixels per unit based on specified font size relative to font object's own font size.
  500. if (m_FontData.fontSize <= 0 || font.fontSize <= 0)
  501. return 1;
  502. return font.fontSize / (float)m_FontData.fontSize;
  503. }
  504. }
  505. protected override void OnEnable()
  506. {
  507. base.OnEnable();
  508. cachedTextGenerator.Invalidate();
  509. FontUpdateTracker.TrackText(this);
  510. }
  511. protected override void OnDisable()
  512. {
  513. FontUpdateTracker.UntrackText(this);
  514. base.OnDisable();
  515. }
  516. protected override void UpdateGeometry()
  517. {
  518. if (font != null)
  519. {
  520. base.UpdateGeometry();
  521. }
  522. }
  523. #if UNITY_EDITOR
  524. protected override void Reset()
  525. {
  526. AssignDefaultFont();
  527. }
  528. #endif
  529. internal void AssignDefaultFont()
  530. {
  531. font = Resources.GetBuiltinResource<Font>("Arial.ttf");
  532. }
  533. /// <summary>
  534. /// Convenience function to populate the generation setting for the text.
  535. /// </summary>
  536. /// <param name="extents">The extents the text can draw in.</param>
  537. /// <returns>Generated settings.</returns>
  538. public TextGenerationSettings GetGenerationSettings(Vector2 extents)
  539. {
  540. var settings = new TextGenerationSettings();
  541. settings.generationExtents = extents;
  542. if (font != null && font.dynamic)
  543. {
  544. settings.fontSize = m_FontData.fontSize;
  545. settings.resizeTextMinSize = m_FontData.minSize;
  546. settings.resizeTextMaxSize = m_FontData.maxSize;
  547. }
  548. // Other settings
  549. settings.textAnchor = m_FontData.alignment;
  550. settings.alignByGeometry = m_FontData.alignByGeometry;
  551. settings.scaleFactor = pixelsPerUnit;
  552. settings.color = color;
  553. settings.font = font;
  554. settings.pivot = rectTransform.pivot;
  555. settings.richText = m_FontData.richText;
  556. settings.lineSpacing = m_FontData.lineSpacing;
  557. settings.fontStyle = m_FontData.fontStyle;
  558. settings.resizeTextForBestFit = m_FontData.bestFit;
  559. settings.updateBounds = false;
  560. settings.horizontalOverflow = m_FontData.horizontalOverflow;
  561. settings.verticalOverflow = m_FontData.verticalOverflow;
  562. return settings;
  563. }
  564. /// <summary>
  565. /// Convenience function to determine the vector offset of the anchor.
  566. /// </summary>
  567. static public Vector2 GetTextAnchorPivot(TextAnchor anchor)
  568. {
  569. switch (anchor)
  570. {
  571. case TextAnchor.LowerLeft: return new Vector2(0, 0);
  572. case TextAnchor.LowerCenter: return new Vector2(0.5f, 0);
  573. case TextAnchor.LowerRight: return new Vector2(1, 0);
  574. case TextAnchor.MiddleLeft: return new Vector2(0, 0.5f);
  575. case TextAnchor.MiddleCenter: return new Vector2(0.5f, 0.5f);
  576. case TextAnchor.MiddleRight: return new Vector2(1, 0.5f);
  577. case TextAnchor.UpperLeft: return new Vector2(0, 1);
  578. case TextAnchor.UpperCenter: return new Vector2(0.5f, 1);
  579. case TextAnchor.UpperRight: return new Vector2(1, 1);
  580. default: return Vector2.zero;
  581. }
  582. }
  583. readonly UIVertex[] m_TempVerts = new UIVertex[4];
  584. protected override void OnPopulateMesh(VertexHelper toFill)
  585. {
  586. if (font == null)
  587. return;
  588. // We don't care if we the font Texture changes while we are doing our Update.
  589. // The end result of cachedTextGenerator will be valid for this instance.
  590. // Otherwise we can get issues like Case 619238.
  591. m_DisableFontTextureRebuiltCallback = true;
  592. Vector2 extents = rectTransform.rect.size;
  593. var settings = GetGenerationSettings(extents);
  594. cachedTextGenerator.PopulateWithErrors(text, settings, gameObject);
  595. // Apply the offset to the vertices
  596. IList<UIVertex> verts = cachedTextGenerator.verts;
  597. float unitsPerPixel = 1 / pixelsPerUnit;
  598. int vertCount = verts.Count;
  599. // We have no verts to process just return (case 1037923)
  600. if (vertCount <= 0)
  601. {
  602. toFill.Clear();
  603. return;
  604. }
  605. Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
  606. roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;
  607. toFill.Clear();
  608. if (roundingOffset != Vector2.zero)
  609. {
  610. for (int i = 0; i < vertCount; ++i)
  611. {
  612. int tempVertsIndex = i & 3;
  613. m_TempVerts[tempVertsIndex] = verts[i];
  614. m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
  615. m_TempVerts[tempVertsIndex].position.x += roundingOffset.x;
  616. m_TempVerts[tempVertsIndex].position.y += roundingOffset.y;
  617. if (tempVertsIndex == 3)
  618. toFill.AddUIVertexQuad(m_TempVerts);
  619. }
  620. }
  621. else
  622. {
  623. for (int i = 0; i < vertCount; ++i)
  624. {
  625. int tempVertsIndex = i & 3;
  626. m_TempVerts[tempVertsIndex] = verts[i];
  627. m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
  628. if (tempVertsIndex == 3)
  629. toFill.AddUIVertexQuad(m_TempVerts);
  630. }
  631. }
  632. m_DisableFontTextureRebuiltCallback = false;
  633. }
  634. public virtual void CalculateLayoutInputHorizontal() {}
  635. public virtual void CalculateLayoutInputVertical() {}
  636. public virtual float minWidth
  637. {
  638. get { return 0; }
  639. }
  640. public virtual float preferredWidth
  641. {
  642. get
  643. {
  644. var settings = GetGenerationSettings(Vector2.zero);
  645. return cachedTextGeneratorForLayout.GetPreferredWidth(m_Text, settings) / pixelsPerUnit;
  646. }
  647. }
  648. public virtual float flexibleWidth { get { return -1; } }
  649. public virtual float minHeight
  650. {
  651. get { return 0; }
  652. }
  653. public virtual float preferredHeight
  654. {
  655. get
  656. {
  657. var settings = GetGenerationSettings(new Vector2(GetPixelAdjustedRect().size.x, 0.0f));
  658. return cachedTextGeneratorForLayout.GetPreferredHeight(m_Text, settings) / pixelsPerUnit;
  659. }
  660. }
  661. public virtual float flexibleHeight { get { return -1; } }
  662. public virtual int layoutPriority { get { return 0; } }
  663. #if UNITY_EDITOR
  664. public override void OnRebuildRequested()
  665. {
  666. // After a Font asset gets re-imported the managed side gets deleted and recreated,
  667. // that means the delegates are not persisted.
  668. // so we need to properly enforce a consistent state here.
  669. if (isActiveAndEnabled)
  670. {
  671. FontUpdateTracker.UntrackText(this);
  672. FontUpdateTracker.TrackText(this);
  673. }
  674. // Also the textgenerator is no longer valid.
  675. cachedTextGenerator.Invalidate();
  676. base.OnRebuildRequested();
  677. }
  678. // The Text inspector editor can change the font, and we need a way to track changes so that we get the appropriate rebuild callbacks
  679. // We can intercept changes in OnValidate, and keep track of the previous font reference
  680. protected override void OnValidate()
  681. {
  682. if (!IsActive())
  683. {
  684. base.OnValidate();
  685. return;
  686. }
  687. if (m_FontData.font != m_LastTrackedFont)
  688. {
  689. Font newFont = m_FontData.font;
  690. m_FontData.font = m_LastTrackedFont;
  691. if (isActiveAndEnabled)
  692. FontUpdateTracker.UntrackText(this);
  693. m_FontData.font = newFont;
  694. if (isActiveAndEnabled)
  695. FontUpdateTracker.TrackText(this);
  696. m_LastTrackedFont = newFont;
  697. }
  698. base.OnValidate();
  699. }
  700. #endif // if UNITY_EDITOR
  701. }
  702. }