TMP_TextInfoDebugTool.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. using System;
  2. using UnityEngine;
  3. using System.Collections;
  4. using UnityEditor;
  5. namespace TMPro.Examples
  6. {
  7. public class TMP_TextInfoDebugTool : MonoBehaviour
  8. {
  9. // Since this script is used for debugging, we exclude it from builds.
  10. // TODO: Rework this script to make it into an editor utility.
  11. #if UNITY_EDITOR
  12. public bool ShowCharacters;
  13. public bool ShowWords;
  14. public bool ShowLinks;
  15. public bool ShowLines;
  16. public bool ShowMeshBounds;
  17. public bool ShowTextBounds;
  18. [Space(10)]
  19. [TextArea(2, 2)]
  20. public string ObjectStats;
  21. [SerializeField]
  22. private TMP_Text m_TextComponent;
  23. private Transform m_Transform;
  24. private TMP_TextInfo m_TextInfo;
  25. private float m_ScaleMultiplier;
  26. private float m_HandleSize;
  27. void OnDrawGizmos()
  28. {
  29. if (m_TextComponent == null)
  30. {
  31. m_TextComponent = GetComponent<TMP_Text>();
  32. if (m_TextComponent == null)
  33. return;
  34. }
  35. m_Transform = m_TextComponent.transform;
  36. // Get a reference to the text object's textInfo
  37. m_TextInfo = m_TextComponent.textInfo;
  38. // Update Text Statistics
  39. ObjectStats = "Characters: " + m_TextInfo.characterCount + " Words: " + m_TextInfo.wordCount + " Spaces: " + m_TextInfo.spaceCount + " Sprites: " + m_TextInfo.spriteCount + " Links: " + m_TextInfo.linkCount
  40. + "\nLines: " + m_TextInfo.lineCount + " Pages: " + m_TextInfo.pageCount;
  41. // Get the handle size for drawing the various
  42. m_ScaleMultiplier = m_TextComponent.GetType() == typeof(TextMeshPro) ? 1 : 0.1f;
  43. m_HandleSize = HandleUtility.GetHandleSize(m_Transform.position) * m_ScaleMultiplier;
  44. // Draw line metrics
  45. #region Draw Lines
  46. if (ShowLines)
  47. DrawLineBounds();
  48. #endregion
  49. // Draw word metrics
  50. #region Draw Words
  51. if (ShowWords)
  52. DrawWordBounds();
  53. #endregion
  54. // Draw character metrics
  55. #region Draw Characters
  56. if (ShowCharacters)
  57. DrawCharactersBounds();
  58. #endregion
  59. // Draw Quads around each of the words
  60. #region Draw Links
  61. if (ShowLinks)
  62. DrawLinkBounds();
  63. #endregion
  64. // Draw Quad around the bounds of the text
  65. #region Draw Bounds
  66. if (ShowMeshBounds)
  67. DrawBounds();
  68. #endregion
  69. // Draw Quad around the rendered region of the text.
  70. #region Draw Text Bounds
  71. if (ShowTextBounds)
  72. DrawTextBounds();
  73. #endregion
  74. }
  75. /// <summary>
  76. /// Method to draw a rectangle around each character.
  77. /// </summary>
  78. /// <param name="text"></param>
  79. void DrawCharactersBounds()
  80. {
  81. int characterCount = m_TextInfo.characterCount;
  82. for (int i = 0; i < characterCount; i++)
  83. {
  84. // Draw visible as well as invisible characters
  85. TMP_CharacterInfo characterInfo = m_TextInfo.characterInfo[i];
  86. bool isCharacterVisible = i < m_TextComponent.maxVisibleCharacters &&
  87. characterInfo.lineNumber < m_TextComponent.maxVisibleLines &&
  88. i >= m_TextComponent.firstVisibleCharacter;
  89. if (m_TextComponent.overflowMode == TextOverflowModes.Page)
  90. isCharacterVisible = isCharacterVisible && characterInfo.pageNumber + 1 == m_TextComponent.pageToDisplay;
  91. if (!isCharacterVisible)
  92. continue;
  93. float dottedLineSize = 6;
  94. // Get Bottom Left and Top Right position of the current character
  95. Vector3 bottomLeft = m_Transform.TransformPoint(characterInfo.bottomLeft);
  96. Vector3 topLeft = m_Transform.TransformPoint(new Vector3(characterInfo.topLeft.x, characterInfo.topLeft.y, 0));
  97. Vector3 topRight = m_Transform.TransformPoint(characterInfo.topRight);
  98. Vector3 bottomRight = m_Transform.TransformPoint(new Vector3(characterInfo.bottomRight.x, characterInfo.bottomRight.y, 0));
  99. // Draw character bounds
  100. if (characterInfo.isVisible)
  101. {
  102. Color color = Color.green;
  103. DrawDottedRectangle(bottomLeft, topRight, color);
  104. }
  105. else
  106. {
  107. Color color = Color.grey;
  108. float whiteSpaceAdvance = Math.Abs(characterInfo.origin - characterInfo.xAdvance) > 0.01f ? characterInfo.xAdvance : characterInfo.origin + (characterInfo.ascender - characterInfo.descender) * 0.03f;
  109. DrawDottedRectangle(m_Transform.TransformPoint(new Vector3(characterInfo.origin, characterInfo.descender, 0)), m_Transform.TransformPoint(new Vector3(whiteSpaceAdvance, characterInfo.ascender, 0)), color, 4);
  110. }
  111. float origin = characterInfo.origin;
  112. float advance = characterInfo.xAdvance;
  113. float ascentline = characterInfo.ascender;
  114. float baseline = characterInfo.baseLine;
  115. float descentline = characterInfo.descender;
  116. //Draw Ascent line
  117. Vector3 ascentlineStart = m_Transform.TransformPoint(new Vector3(origin, ascentline, 0));
  118. Vector3 ascentlineEnd = m_Transform.TransformPoint(new Vector3(advance, ascentline, 0));
  119. Handles.color = Color.cyan;
  120. Handles.DrawDottedLine(ascentlineStart, ascentlineEnd, dottedLineSize);
  121. // Draw Cap Height & Mean line
  122. float capline = characterInfo.fontAsset == null ? 0 : baseline + characterInfo.fontAsset.faceInfo.capLine * characterInfo.scale;
  123. Vector3 capHeightStart = new Vector3(topLeft.x, m_Transform.TransformPoint(new Vector3(0, capline, 0)).y, 0);
  124. Vector3 capHeightEnd = new Vector3(topRight.x, m_Transform.TransformPoint(new Vector3(0, capline, 0)).y, 0);
  125. float meanline = characterInfo.fontAsset == null ? 0 : baseline + characterInfo.fontAsset.faceInfo.meanLine * characterInfo.scale;
  126. Vector3 meanlineStart = new Vector3(topLeft.x, m_Transform.TransformPoint(new Vector3(0, meanline, 0)).y, 0);
  127. Vector3 meanlineEnd = new Vector3(topRight.x, m_Transform.TransformPoint(new Vector3(0, meanline, 0)).y, 0);
  128. if (characterInfo.isVisible)
  129. {
  130. // Cap line
  131. Handles.color = Color.cyan;
  132. Handles.DrawDottedLine(capHeightStart, capHeightEnd, dottedLineSize);
  133. // Mean line
  134. Handles.color = Color.cyan;
  135. Handles.DrawDottedLine(meanlineStart, meanlineEnd, dottedLineSize);
  136. }
  137. //Draw Base line
  138. Vector3 baselineStart = m_Transform.TransformPoint(new Vector3(origin, baseline, 0));
  139. Vector3 baselineEnd = m_Transform.TransformPoint(new Vector3(advance, baseline, 0));
  140. Handles.color = Color.cyan;
  141. Handles.DrawDottedLine(baselineStart, baselineEnd, dottedLineSize);
  142. //Draw Descent line
  143. Vector3 descentlineStart = m_Transform.TransformPoint(new Vector3(origin, descentline, 0));
  144. Vector3 descentlineEnd = m_Transform.TransformPoint(new Vector3(advance, descentline, 0));
  145. Handles.color = Color.cyan;
  146. Handles.DrawDottedLine(descentlineStart, descentlineEnd, dottedLineSize);
  147. // Draw Origin
  148. Vector3 originPosition = m_Transform.TransformPoint(new Vector3(origin, baseline, 0));
  149. DrawCrosshair(originPosition, 0.05f / m_ScaleMultiplier, Color.cyan);
  150. // Draw Horizontal Advance
  151. Vector3 advancePosition = m_Transform.TransformPoint(new Vector3(advance, baseline, 0));
  152. DrawSquare(advancePosition, 0.025f / m_ScaleMultiplier, Color.yellow);
  153. DrawCrosshair(advancePosition, 0.0125f / m_ScaleMultiplier, Color.yellow);
  154. // Draw text labels for metrics
  155. if (m_HandleSize < 0.5f)
  156. {
  157. GUIStyle style = new GUIStyle(GUI.skin.GetStyle("Label"));
  158. style.normal.textColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
  159. style.fontSize = 12;
  160. style.fixedWidth = 200;
  161. style.fixedHeight = 20;
  162. Vector3 labelPosition;
  163. float center = (origin + advance) / 2;
  164. //float baselineMetrics = 0;
  165. //float ascentlineMetrics = ascentline - baseline;
  166. //float caplineMetrics = capline - baseline;
  167. //float meanlineMetrics = meanline - baseline;
  168. //float descentlineMetrics = descentline - baseline;
  169. // Ascent Line
  170. labelPosition = m_Transform.TransformPoint(new Vector3(center, ascentline, 0));
  171. style.alignment = TextAnchor.UpperCenter;
  172. Handles.Label(labelPosition, "Ascent Line", style);
  173. //Handles.Label(labelPosition, "Ascent Line (" + ascentlineMetrics.ToString("f3") + ")" , style);
  174. // Base Line
  175. labelPosition = m_Transform.TransformPoint(new Vector3(center, baseline, 0));
  176. Handles.Label(labelPosition, "Base Line", style);
  177. //Handles.Label(labelPosition, "Base Line (" + baselineMetrics.ToString("f3") + ")" , style);
  178. // Descent line
  179. labelPosition = m_Transform.TransformPoint(new Vector3(center, descentline, 0));
  180. Handles.Label(labelPosition, "Descent Line", style);
  181. //Handles.Label(labelPosition, "Descent Line (" + descentlineMetrics.ToString("f3") + ")" , style);
  182. if (characterInfo.isVisible)
  183. {
  184. // Cap Line
  185. labelPosition = m_Transform.TransformPoint(new Vector3(center, capline, 0));
  186. style.alignment = TextAnchor.UpperCenter;
  187. Handles.Label(labelPosition, "Cap Line", style);
  188. //Handles.Label(labelPosition, "Cap Line (" + caplineMetrics.ToString("f3") + ")" , style);
  189. // Mean Line
  190. labelPosition = m_Transform.TransformPoint(new Vector3(center, meanline, 0));
  191. style.alignment = TextAnchor.UpperCenter;
  192. Handles.Label(labelPosition, "Mean Line", style);
  193. //Handles.Label(labelPosition, "Mean Line (" + ascentlineMetrics.ToString("f3") + ")" , style);
  194. // Origin
  195. labelPosition = m_Transform.TransformPoint(new Vector3(origin, baseline, 0));
  196. style.alignment = TextAnchor.UpperRight;
  197. Handles.Label(labelPosition, "Origin ", style);
  198. // Advance
  199. labelPosition = m_Transform.TransformPoint(new Vector3(advance, baseline, 0));
  200. style.alignment = TextAnchor.UpperLeft;
  201. Handles.Label(labelPosition, " Advance", style);
  202. }
  203. }
  204. }
  205. }
  206. /// <summary>
  207. /// Method to draw rectangles around each word of the text.
  208. /// </summary>
  209. /// <param name="text"></param>
  210. void DrawWordBounds()
  211. {
  212. for (int i = 0; i < m_TextInfo.wordCount; i++)
  213. {
  214. TMP_WordInfo wInfo = m_TextInfo.wordInfo[i];
  215. bool isBeginRegion = false;
  216. Vector3 bottomLeft = Vector3.zero;
  217. Vector3 topLeft = Vector3.zero;
  218. Vector3 bottomRight = Vector3.zero;
  219. Vector3 topRight = Vector3.zero;
  220. float maxAscender = -Mathf.Infinity;
  221. float minDescender = Mathf.Infinity;
  222. Color wordColor = Color.green;
  223. // Iterate through each character of the word
  224. for (int j = 0; j < wInfo.characterCount; j++)
  225. {
  226. int characterIndex = wInfo.firstCharacterIndex + j;
  227. TMP_CharacterInfo currentCharInfo = m_TextInfo.characterInfo[characterIndex];
  228. int currentLine = currentCharInfo.lineNumber;
  229. bool isCharacterVisible = characterIndex > m_TextComponent.maxVisibleCharacters ||
  230. currentCharInfo.lineNumber > m_TextComponent.maxVisibleLines ||
  231. (m_TextComponent.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != m_TextComponent.pageToDisplay) ? false : true;
  232. // Track Max Ascender and Min Descender
  233. maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
  234. minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
  235. if (isBeginRegion == false && isCharacterVisible)
  236. {
  237. isBeginRegion = true;
  238. bottomLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
  239. topLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
  240. //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
  241. // If Word is one character
  242. if (wInfo.characterCount == 1)
  243. {
  244. isBeginRegion = false;
  245. topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
  246. bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
  247. bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
  248. topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
  249. // Draw Region
  250. DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor);
  251. //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
  252. }
  253. }
  254. // Last Character of Word
  255. if (isBeginRegion && j == wInfo.characterCount - 1)
  256. {
  257. isBeginRegion = false;
  258. topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
  259. bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
  260. bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
  261. topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
  262. // Draw Region
  263. DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor);
  264. //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
  265. }
  266. // If Word is split on more than one line.
  267. else if (isBeginRegion && currentLine != m_TextInfo.characterInfo[characterIndex + 1].lineNumber)
  268. {
  269. isBeginRegion = false;
  270. topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
  271. bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
  272. bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
  273. topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
  274. // Draw Region
  275. DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, wordColor);
  276. //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
  277. maxAscender = -Mathf.Infinity;
  278. minDescender = Mathf.Infinity;
  279. }
  280. }
  281. //Debug.Log(wInfo.GetWord(m_TextMeshPro.textInfo.characterInfo));
  282. }
  283. }
  284. /// <summary>
  285. /// Draw rectangle around each of the links contained in the text.
  286. /// </summary>
  287. /// <param name="text"></param>
  288. void DrawLinkBounds()
  289. {
  290. TMP_TextInfo textInfo = m_TextComponent.textInfo;
  291. for (int i = 0; i < textInfo.linkCount; i++)
  292. {
  293. TMP_LinkInfo linkInfo = textInfo.linkInfo[i];
  294. bool isBeginRegion = false;
  295. Vector3 bottomLeft = Vector3.zero;
  296. Vector3 topLeft = Vector3.zero;
  297. Vector3 bottomRight = Vector3.zero;
  298. Vector3 topRight = Vector3.zero;
  299. float maxAscender = -Mathf.Infinity;
  300. float minDescender = Mathf.Infinity;
  301. Color32 linkColor = Color.cyan;
  302. // Iterate through each character of the link text
  303. for (int j = 0; j < linkInfo.linkTextLength; j++)
  304. {
  305. int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
  306. TMP_CharacterInfo currentCharInfo = textInfo.characterInfo[characterIndex];
  307. int currentLine = currentCharInfo.lineNumber;
  308. bool isCharacterVisible = characterIndex > m_TextComponent.maxVisibleCharacters ||
  309. currentCharInfo.lineNumber > m_TextComponent.maxVisibleLines ||
  310. (m_TextComponent.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != m_TextComponent.pageToDisplay) ? false : true;
  311. // Track Max Ascender and Min Descender
  312. maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
  313. minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
  314. if (isBeginRegion == false && isCharacterVisible)
  315. {
  316. isBeginRegion = true;
  317. bottomLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
  318. topLeft = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
  319. //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
  320. // If Link is one character
  321. if (linkInfo.linkTextLength == 1)
  322. {
  323. isBeginRegion = false;
  324. topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
  325. bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
  326. bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
  327. topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
  328. // Draw Region
  329. DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor);
  330. //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
  331. }
  332. }
  333. // Last Character of Link
  334. if (isBeginRegion && j == linkInfo.linkTextLength - 1)
  335. {
  336. isBeginRegion = false;
  337. topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
  338. bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
  339. bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
  340. topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
  341. // Draw Region
  342. DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor);
  343. //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
  344. }
  345. // If Link is split on more than one line.
  346. else if (isBeginRegion && currentLine != textInfo.characterInfo[characterIndex + 1].lineNumber)
  347. {
  348. isBeginRegion = false;
  349. topLeft = m_Transform.TransformPoint(new Vector3(topLeft.x, maxAscender, 0));
  350. bottomLeft = m_Transform.TransformPoint(new Vector3(bottomLeft.x, minDescender, 0));
  351. bottomRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, minDescender, 0));
  352. topRight = m_Transform.TransformPoint(new Vector3(currentCharInfo.topRight.x, maxAscender, 0));
  353. // Draw Region
  354. DrawRectangle(bottomLeft, topLeft, topRight, bottomRight, linkColor);
  355. maxAscender = -Mathf.Infinity;
  356. minDescender = Mathf.Infinity;
  357. //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
  358. }
  359. }
  360. //Debug.Log(wInfo.GetWord(m_TextMeshPro.textInfo.characterInfo));
  361. }
  362. }
  363. /// <summary>
  364. /// Draw Rectangles around each lines of the text.
  365. /// </summary>
  366. /// <param name="text"></param>
  367. void DrawLineBounds()
  368. {
  369. int lineCount = m_TextInfo.lineCount;
  370. for (int i = 0; i < lineCount; i++)
  371. {
  372. TMP_LineInfo lineInfo = m_TextInfo.lineInfo[i];
  373. TMP_CharacterInfo firstCharacterInfo = m_TextInfo.characterInfo[lineInfo.firstCharacterIndex];
  374. TMP_CharacterInfo lastCharacterInfo = m_TextInfo.characterInfo[lineInfo.lastCharacterIndex];
  375. bool isLineVisible = (lineInfo.characterCount == 1 && (firstCharacterInfo.character == 10 || firstCharacterInfo.character == 11 || firstCharacterInfo.character == 0x2028 || firstCharacterInfo.character == 0x2029)) ||
  376. i > m_TextComponent.maxVisibleLines ||
  377. (m_TextComponent.overflowMode == TextOverflowModes.Page && firstCharacterInfo.pageNumber + 1 != m_TextComponent.pageToDisplay) ? false : true;
  378. if (!isLineVisible) continue;
  379. float lineBottomLeft = firstCharacterInfo.bottomLeft.x;
  380. float lineTopRight = lastCharacterInfo.topRight.x;
  381. float ascentline = lineInfo.ascender;
  382. float baseline = lineInfo.baseline;
  383. float descentline = lineInfo.descender;
  384. float dottedLineSize = 12;
  385. // Draw line extents
  386. DrawDottedRectangle(m_Transform.TransformPoint(lineInfo.lineExtents.min), m_Transform.TransformPoint(lineInfo.lineExtents.max), Color.green, 4);
  387. // Draw Ascent line
  388. Vector3 ascentlineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, ascentline, 0));
  389. Vector3 ascentlineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, ascentline, 0));
  390. Handles.color = Color.yellow;
  391. Handles.DrawDottedLine(ascentlineStart, ascentlineEnd, dottedLineSize);
  392. // Draw Base line
  393. Vector3 baseLineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, baseline, 0));
  394. Vector3 baseLineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, baseline, 0));
  395. Handles.color = Color.yellow;
  396. Handles.DrawDottedLine(baseLineStart, baseLineEnd, dottedLineSize);
  397. // Draw Descent line
  398. Vector3 descentLineStart = m_Transform.TransformPoint(new Vector3(lineBottomLeft, descentline, 0));
  399. Vector3 descentLineEnd = m_Transform.TransformPoint(new Vector3(lineTopRight, descentline, 0));
  400. Handles.color = Color.yellow;
  401. Handles.DrawDottedLine(descentLineStart, descentLineEnd, dottedLineSize);
  402. // Draw text labels for metrics
  403. if (m_HandleSize < 1.0f)
  404. {
  405. GUIStyle style = new GUIStyle();
  406. style.normal.textColor = new Color(0.8f, 0.8f, 0.8f, 1.0f);
  407. style.fontSize = 12;
  408. style.fixedWidth = 200;
  409. style.fixedHeight = 20;
  410. Vector3 labelPosition;
  411. // Ascent Line
  412. labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, ascentline, 0));
  413. style.padding = new RectOffset(0, 10, 0, 5);
  414. style.alignment = TextAnchor.MiddleRight;
  415. Handles.Label(labelPosition, "Ascent Line", style);
  416. // Base Line
  417. labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, baseline, 0));
  418. Handles.Label(labelPosition, "Base Line", style);
  419. // Descent line
  420. labelPosition = m_Transform.TransformPoint(new Vector3(lineBottomLeft, descentline, 0));
  421. Handles.Label(labelPosition, "Descent Line", style);
  422. }
  423. }
  424. }
  425. /// <summary>
  426. /// Draw Rectangle around the bounds of the text object.
  427. /// </summary>
  428. void DrawBounds()
  429. {
  430. Bounds meshBounds = m_TextComponent.bounds;
  431. // Get Bottom Left and Top Right position of each word
  432. Vector3 bottomLeft = m_TextComponent.transform.position + meshBounds.min;
  433. Vector3 topRight = m_TextComponent.transform.position + meshBounds.max;
  434. DrawRectangle(bottomLeft, topRight, new Color(1, 0.5f, 0));
  435. }
  436. void DrawTextBounds()
  437. {
  438. Bounds textBounds = m_TextComponent.textBounds;
  439. Vector3 bottomLeft = m_TextComponent.transform.position + (textBounds.center - textBounds.extents);
  440. Vector3 topRight = m_TextComponent.transform.position + (textBounds.center + textBounds.extents);
  441. DrawRectangle(bottomLeft, topRight, new Color(0f, 0.5f, 0.5f));
  442. }
  443. // Draw Rectangles
  444. void DrawRectangle(Vector3 BL, Vector3 TR, Color color)
  445. {
  446. Gizmos.color = color;
  447. Gizmos.DrawLine(new Vector3(BL.x, BL.y, 0), new Vector3(BL.x, TR.y, 0));
  448. Gizmos.DrawLine(new Vector3(BL.x, TR.y, 0), new Vector3(TR.x, TR.y, 0));
  449. Gizmos.DrawLine(new Vector3(TR.x, TR.y, 0), new Vector3(TR.x, BL.y, 0));
  450. Gizmos.DrawLine(new Vector3(TR.x, BL.y, 0), new Vector3(BL.x, BL.y, 0));
  451. }
  452. void DrawDottedRectangle(Vector3 bottomLeft, Vector3 topRight, Color color, float size = 5.0f)
  453. {
  454. Handles.color = color;
  455. Handles.DrawDottedLine(bottomLeft, new Vector3(bottomLeft.x, topRight.y, bottomLeft.z), size);
  456. Handles.DrawDottedLine(new Vector3(bottomLeft.x, topRight.y, bottomLeft.z), topRight, size);
  457. Handles.DrawDottedLine(topRight, new Vector3(topRight.x, bottomLeft.y, bottomLeft.z), size);
  458. Handles.DrawDottedLine(new Vector3(topRight.x, bottomLeft.y, bottomLeft.z), bottomLeft, size);
  459. }
  460. void DrawSolidRectangle(Vector3 bottomLeft, Vector3 topRight, Color color, float size = 5.0f)
  461. {
  462. Handles.color = color;
  463. Rect rect = new Rect(bottomLeft, topRight - bottomLeft);
  464. Handles.DrawSolidRectangleWithOutline(rect, color, Color.black);
  465. }
  466. void DrawSquare(Vector3 position, float size, Color color)
  467. {
  468. Handles.color = color;
  469. Vector3 bottomLeft = new Vector3(position.x - size, position.y - size, position.z);
  470. Vector3 topLeft = new Vector3(position.x - size, position.y + size, position.z);
  471. Vector3 topRight = new Vector3(position.x + size, position.y + size, position.z);
  472. Vector3 bottomRight = new Vector3(position.x + size, position.y - size, position.z);
  473. Handles.DrawLine(bottomLeft, topLeft);
  474. Handles.DrawLine(topLeft, topRight);
  475. Handles.DrawLine(topRight, bottomRight);
  476. Handles.DrawLine(bottomRight, bottomLeft);
  477. }
  478. void DrawCrosshair(Vector3 position, float size, Color color)
  479. {
  480. Handles.color = color;
  481. Handles.DrawLine(new Vector3(position.x - size, position.y, position.z), new Vector3(position.x + size, position.y, position.z));
  482. Handles.DrawLine(new Vector3(position.x, position.y - size, position.z), new Vector3(position.x, position.y + size, position.z));
  483. }
  484. // Draw Rectangles
  485. void DrawRectangle(Vector3 bl, Vector3 tl, Vector3 tr, Vector3 br, Color color)
  486. {
  487. Gizmos.color = color;
  488. Gizmos.DrawLine(bl, tl);
  489. Gizmos.DrawLine(tl, tr);
  490. Gizmos.DrawLine(tr, br);
  491. Gizmos.DrawLine(br, bl);
  492. }
  493. // Draw Rectangles
  494. void DrawDottedRectangle(Vector3 bl, Vector3 tl, Vector3 tr, Vector3 br, Color color)
  495. {
  496. var cam = Camera.current;
  497. float dotSpacing = (cam.WorldToScreenPoint(br).x - cam.WorldToScreenPoint(bl).x) / 75f;
  498. UnityEditor.Handles.color = color;
  499. UnityEditor.Handles.DrawDottedLine(bl, tl, dotSpacing);
  500. UnityEditor.Handles.DrawDottedLine(tl, tr, dotSpacing);
  501. UnityEditor.Handles.DrawDottedLine(tr, br, dotSpacing);
  502. UnityEditor.Handles.DrawDottedLine(br, bl, dotSpacing);
  503. }
  504. #endif
  505. }
  506. }