Hue Preserving Color Blending
TMP_TextUtilities.cs
1 using UnityEngine;
2 using System.Collections;
3 
4 
5 namespace TMPro
6 {
7  public enum CaretPosition { None, Left, Right }
8 
12  public struct CaretInfo
13  {
14  public int index;
15  public CaretPosition position;
16 
17  public CaretInfo(int index, CaretPosition position)
18  {
19  this.index = index;
20  this.position = position;
21  }
22  }
23 
24  public static class TMP_TextUtilities
25  {
26  private static Vector3[] m_rectWorldCorners = new Vector3[4];
27 
28 
29  // TEXT INPUT COMPONENT RELATED FUNCTIONS
30 
38  //public static CaretInfo GetCursorInsertionIndex(TMP_Text textComponent, Vector3 position, Camera camera)
39  //{
40  // int index = TMP_TextUtilities.FindNearestCharacter(textComponent, position, camera, false);
41 
42  // RectTransform rectTransform = textComponent.rectTransform;
43 
44  // // Convert position into Worldspace coordinates
45  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
46 
47  // TMP_CharacterInfo cInfo = textComponent.textInfo.characterInfo[index];
48 
49  // // Get Bottom Left and Top Right position of the current character
50  // Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
51  // //Vector3 tl = rectTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
52  // Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
53  // //Vector3 br = rectTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
54 
55  // float insertPosition = (position.x - bl.x) / (tr.x - bl.x);
56 
57  // if (insertPosition < 0.5f)
58  // return new CaretInfo(index, CaretPosition.Left);
59  // else
60  // return new CaretInfo(index, CaretPosition.Right);
61  //}
62 
63 
71  public static int GetCursorIndexFromPosition(TMP_Text textComponent, Vector3 position, Camera camera)
72  {
73  int index = TMP_TextUtilities.FindNearestCharacter(textComponent, position, camera, false);
74 
75  RectTransform rectTransform = textComponent.rectTransform;
76 
77  // Convert position into Worldspace coordinates
78  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
79 
80  TMP_CharacterInfo cInfo = textComponent.textInfo.characterInfo[index];
81 
82  // Get Bottom Left and Top Right position of the current character
83  Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
84  Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
85 
86  float insertPosition = (position.x - bl.x) / (tr.x - bl.x);
87 
88  if (insertPosition < 0.5f)
89  return index;
90  else
91  return index + 1;
92 
93  }
94 
95 
104  //public static int GetCursorIndexFromPosition(TMP_Text textComponent, Vector3 position, Camera camera, out CaretPosition cursor)
105  //{
106  // int index = TMP_TextUtilities.FindNearestCharacter(textComponent, position, camera, false);
107 
108  // RectTransform rectTransform = textComponent.rectTransform;
109 
110  // // Convert position into Worldspace coordinates
111  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
112 
113  // TMP_CharacterInfo cInfo = textComponent.textInfo.characterInfo[index];
114 
115  // // Get Bottom Left and Top Right position of the current character
116  // Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
117  // Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
118 
119  // float insertPosition = (position.x - bl.x) / (tr.x - bl.x);
120 
121  // if (insertPosition < 0.5f)
122  // {
123  // cursor = CaretPosition.Left;
124  // return index;
125  // }
126  // else
127  // {
128  // cursor = CaretPosition.Right;
129  // return index;
130  // }
131  //}
132 
133 
142  public static int GetCursorIndexFromPosition(TMP_Text textComponent, Vector3 position, Camera camera, out CaretPosition cursor)
143  {
144  int line = TMP_TextUtilities.FindNearestLine(textComponent, position, camera);
145 
146  int index = FindNearestCharacterOnLine(textComponent, position, line, camera, false);
147 
148  // Special handling if line contains only one character.
149  if (textComponent.textInfo.lineInfo[line].characterCount == 1)
150  {
151  cursor = CaretPosition.Left;
152  return index;
153  }
154 
155  RectTransform rectTransform = textComponent.rectTransform;
156 
157  // Convert position into Worldspace coordinates
158  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
159 
160  TMP_CharacterInfo cInfo = textComponent.textInfo.characterInfo[index];
161 
162  // Get Bottom Left and Top Right position of the current character
163  Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
164  Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
165 
166  float insertPosition = (position.x - bl.x) / (tr.x - bl.x);
167 
168  if (insertPosition < 0.5f)
169  {
170  cursor = CaretPosition.Left;
171  return index;
172  }
173  else
174  {
175  cursor = CaretPosition.Right;
176  return index;
177  }
178  }
179 
180 
188  public static int FindNearestLine(TMP_Text text, Vector3 position, Camera camera)
189  {
190  RectTransform rectTransform = text.rectTransform;
191 
192  float distance = Mathf.Infinity;
193  int closest = -1;
194 
195  // Convert position into Worldspace coordinates
196  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
197 
198  for (int i = 0; i < text.textInfo.lineCount; i++)
199  {
200  TMP_LineInfo lineInfo = text.textInfo.lineInfo[i];
201 
202  float ascender = rectTransform.TransformPoint(new Vector3(0, lineInfo.ascender, 0)).y;
203  float descender = rectTransform.TransformPoint(new Vector3(0, lineInfo.descender, 0)).y;
204 
205  if (ascender > position.y && descender < position.y)
206  {
207  //Debug.Log("Position is on line " + i);
208  return i;
209  }
210 
211  float d0 = Mathf.Abs(ascender - position.y);
212  float d1 = Mathf.Abs(descender - position.y);
213 
214  float d = Mathf.Min(d0, d1);
215  if (d < distance)
216  {
217  distance = d;
218  closest = i;
219  }
220  }
221 
222  //Debug.Log("Closest line to position is " + closest);
223  return closest;
224  }
225 
226 
235  public static int FindNearestCharacterOnLine(TMP_Text text, Vector3 position, int line, Camera camera, bool visibleOnly)
236  {
237  RectTransform rectTransform = text.rectTransform;
238 
239  // Convert position into Worldspace coordinates
240  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
241 
242  int firstCharacter = text.textInfo.lineInfo[line].firstCharacterIndex;
243  int lastCharacter = text.textInfo.lineInfo[line].lastCharacterIndex;
244 
245  float distanceSqr = Mathf.Infinity;
246  int closest = lastCharacter;
247 
248  for (int i = firstCharacter; i < lastCharacter; i++)
249  {
250  // Get current character info.
251  TMP_CharacterInfo cInfo = text.textInfo.characterInfo[i];
252  if (visibleOnly && !cInfo.isVisible) continue;
253 
254  // Get Bottom Left and Top Right position of the current character
255  Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
256  Vector3 tl = rectTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
257  Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
258  Vector3 br = rectTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
259 
260  if (PointIntersectRectangle(position, bl, tl, tr, br))
261  {
262  closest = i;
263  break;
264  }
265 
266  // Find the closest corner to position.
267  float dbl = DistanceToLine(bl, tl, position);
268  float dtl = DistanceToLine(tl, tr, position);
269  float dtr = DistanceToLine(tr, br, position);
270  float dbr = DistanceToLine(br, bl, position);
271 
272  float d = dbl < dtl ? dbl : dtl;
273  d = d < dtr ? d : dtr;
274  d = d < dbr ? d : dbr;
275 
276  if (distanceSqr > d)
277  {
278  distanceSqr = d;
279  closest = i;
280  }
281  }
282  return closest;
283  }
284 
285 
293  public static bool IsIntersectingRectTransform(RectTransform rectTransform, Vector3 position, Camera camera)
294  {
295  // Convert position into Worldspace coordinates
296  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
297 
298  rectTransform.GetWorldCorners(m_rectWorldCorners);
299 
300  if (PointIntersectRectangle(position, m_rectWorldCorners[0], m_rectWorldCorners[1], m_rectWorldCorners[2], m_rectWorldCorners[3]))
301  {
302  return true;
303  }
304 
305  return false;
306  }
307 
308 
309  // CHARACTER HANDLING
310 
319  public static int FindIntersectingCharacter(TMP_Text text, Vector3 position, Camera camera, bool visibleOnly)
320  {
321  RectTransform rectTransform = text.rectTransform;
322 
323  // Convert position into Worldspace coordinates
324  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
325 
326  for (int i = 0; i < text.textInfo.characterCount; i++)
327  {
328  // Get current character info.
329  TMP_CharacterInfo cInfo = text.textInfo.characterInfo[i];
330  if (visibleOnly && !cInfo.isVisible) continue;
331 
332  // Get Bottom Left and Top Right position of the current character
333  Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
334  Vector3 tl = rectTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
335  Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
336  Vector3 br = rectTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
337 
338  if (PointIntersectRectangle(position, bl, tl, tr, br))
339  return i;
340 
341  }
342  return -1;
343  }
344 
345 
354  //public static int FindIntersectingCharacter(TextMeshPro text, Vector3 position, Camera camera, bool visibleOnly)
355  //{
356  // Transform textTransform = text.transform;
357 
358  // // Convert position into Worldspace coordinates
359  // ScreenPointToWorldPointInRectangle(textTransform, position, camera, out position);
360 
361  // for (int i = 0; i < text.textInfo.characterCount; i++)
362  // {
363  // // Get current character info.
364  // TMP_CharacterInfo cInfo = text.textInfo.characterInfo[i];
365  // if ((visibleOnly && !cInfo.isVisible) || (text.OverflowMode == TextOverflowModes.Page && cInfo.pageNumber + 1 != text.pageToDisplay))
366  // continue;
367 
368  // // Get Bottom Left and Top Right position of the current character
369  // Vector3 bl = textTransform.TransformPoint(cInfo.bottomLeft);
370  // Vector3 tl = textTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
371  // Vector3 tr = textTransform.TransformPoint(cInfo.topRight);
372  // Vector3 br = textTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
373 
374  // if (PointIntersectRectangle(position, bl, tl, tr, br))
375  // return i;
376 
377  // }
378 
379  // return -1;
380  //}
381 
382 
391  public static int FindNearestCharacter(TMP_Text text, Vector3 position, Camera camera, bool visibleOnly)
392  {
393  RectTransform rectTransform = text.rectTransform;
394 
395  float distanceSqr = Mathf.Infinity;
396  int closest = 0;
397 
398  // Convert position into Worldspace coordinates
399  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
400 
401  for (int i = 0; i < text.textInfo.characterCount; i++)
402  {
403  // Get current character info.
404  TMP_CharacterInfo cInfo = text.textInfo.characterInfo[i];
405  if (visibleOnly && !cInfo.isVisible) continue;
406 
407  // Get Bottom Left and Top Right position of the current character
408  Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
409  Vector3 tl = rectTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
410  Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
411  Vector3 br = rectTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
412 
413  if (PointIntersectRectangle(position, bl, tl, tr, br))
414  return i;
415 
416  // Find the closest corner to position.
417  float dbl = DistanceToLine(bl, tl, position);
418  float dtl = DistanceToLine(tl, tr, position);
419  float dtr = DistanceToLine(tr, br, position);
420  float dbr = DistanceToLine(br, bl, position);
421 
422  float d = dbl < dtl ? dbl : dtl;
423  d = d < dtr ? d : dtr;
424  d = d < dbr ? d : dbr;
425 
426  if (distanceSqr > d)
427  {
428  distanceSqr = d;
429  closest = i;
430  }
431  }
432 
433  return closest;
434  }
435 
436 
445  //public static int FindNearestCharacter(TextMeshProUGUI text, Vector3 position, Camera camera, bool visibleOnly)
446  //{
447  // RectTransform rectTransform = text.rectTransform;
448 
449  // float distanceSqr = Mathf.Infinity;
450  // int closest = 0;
451 
452  // // Convert position into Worldspace coordinates
453  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
454 
455  // for (int i = 0; i < text.textInfo.characterCount; i++)
456  // {
457  // // Get current character info.
458  // TMP_CharacterInfo cInfo = text.textInfo.characterInfo[i];
459  // if ((visibleOnly && !cInfo.isVisible) || (text.OverflowMode == TextOverflowModes.Page && cInfo.pageNumber + 1 != text.pageToDisplay))
460  // continue;
461 
462  // // Get Bottom Left and Top Right position of the current character
463  // Vector3 bl = rectTransform.TransformPoint(cInfo.bottomLeft);
464  // Vector3 tl = rectTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
465  // Vector3 tr = rectTransform.TransformPoint(cInfo.topRight);
466  // Vector3 br = rectTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
467 
468  // if (PointIntersectRectangle(position, bl, tl, tr, br))
469  // return i;
470 
471  // // Find the closest corner to position.
472  // float dbl = DistanceToLine(bl, tl, position);
473  // float dtl = DistanceToLine(tl, tr, position);
474  // float dtr = DistanceToLine(tr, br, position);
475  // float dbr = DistanceToLine(br, bl, position);
476 
477  // float d = dbl < dtl ? dbl : dtl;
478  // d = d < dtr ? d : dtr;
479  // d = d < dbr ? d : dbr;
480 
481  // if (distanceSqr > d)
482  // {
483  // distanceSqr = d;
484  // closest = i;
485  // }
486  // }
487 
488  // //Debug.Log("Returning nearest character at index: " + closest);
489 
490  // return closest;
491  //}
492 
493 
502  //public static int FindNearestCharacter(TextMeshPro text, Vector3 position, Camera camera, bool visibleOnly)
503  //{
504  // Transform textTransform = text.transform;
505 
506  // float distanceSqr = Mathf.Infinity;
507  // int closest = 0;
508 
509  // // Convert position into Worldspace coordinates
510  // ScreenPointToWorldPointInRectangle(textTransform, position, camera, out position);
511 
512  // for (int i = 0; i < text.textInfo.characterCount; i++)
513  // {
514  // // Get current character info.
515  // TMP_CharacterInfo cInfo = text.textInfo.characterInfo[i];
516  // if ((visibleOnly && !cInfo.isVisible) || (text.OverflowMode == TextOverflowModes.Page && cInfo.pageNumber + 1 != text.pageToDisplay))
517  // continue;
518 
519  // // Get Bottom Left and Top Right position of the current character
520  // Vector3 bl = textTransform.TransformPoint(cInfo.bottomLeft);
521  // Vector3 tl = textTransform.TransformPoint(new Vector3(cInfo.bottomLeft.x, cInfo.topRight.y, 0));
522  // Vector3 tr = textTransform.TransformPoint(cInfo.topRight);
523  // Vector3 br = textTransform.TransformPoint(new Vector3(cInfo.topRight.x, cInfo.bottomLeft.y, 0));
524 
525  // if (PointIntersectRectangle(position, bl, tl, tr, br))
526  // return i;
527 
528  // // Find the closest corner to position.
529  // float dbl = DistanceToLine(bl, tl, position); // (position - bl).sqrMagnitude;
530  // float dtl = DistanceToLine(tl, tr, position); // (position - tl).sqrMagnitude;
531  // float dtr = DistanceToLine(tr, br, position); // (position - tr).sqrMagnitude;
532  // float dbr = DistanceToLine(br, bl, position); // (position - br).sqrMagnitude;
533 
534  // float d = dbl < dtl ? dbl : dtl;
535  // d = d < dtr ? d : dtr;
536  // d = d < dbr ? d : dbr;
537 
538  // if (distanceSqr > d)
539  // {
540  // distanceSqr = d;
541  // closest = i;
542  // }
543  // }
544 
545  // //Debug.Log("Returning nearest character at index: " + closest);
546 
547  // return closest;
548  //}
549 
550 
551  // WORD HANDLING
559  public static int FindIntersectingWord(TMP_Text text, Vector3 position, Camera camera)
560  {
561  RectTransform rectTransform = text.rectTransform;
562 
563  // Convert position into Worldspace coordinates
564  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
565 
566  for (int i = 0; i < text.textInfo.wordCount; i++)
567  {
568  TMP_WordInfo wInfo = text.textInfo.wordInfo[i];
569 
570  bool isBeginRegion = false;
571 
572  Vector3 bl = Vector3.zero;
573  Vector3 tl = Vector3.zero;
574  Vector3 br = Vector3.zero;
575  Vector3 tr = Vector3.zero;
576 
577  float maxAscender = -Mathf.Infinity;
578  float minDescender = Mathf.Infinity;
579 
580  // Iterate through each character of the word
581  for (int j = 0; j < wInfo.characterCount; j++)
582  {
583  int characterIndex = wInfo.firstCharacterIndex + j;
584  TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
585  int currentLine = currentCharInfo.lineNumber;
586 
587  bool isCharacterVisible = currentCharInfo.isVisible;
588 
589  // Track maximum Ascender and minimum Descender for each word.
590  maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
591  minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
592 
593  if (isBeginRegion == false && isCharacterVisible)
594  {
595  isBeginRegion = true;
596 
597  bl = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
598  tl = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
599 
600  //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
601 
602  // If Word is one character
603  if (wInfo.characterCount == 1)
604  {
605  isBeginRegion = false;
606 
607  br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
608  tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
609 
610  // Transform coordinates to be relative to transform and account min descender and max ascender.
611  bl = rectTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
612  tl = rectTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
613  tr = rectTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
614  br = rectTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
615 
616  // Check for Intersection
617  if (PointIntersectRectangle(position, bl, tl, tr, br))
618  return i;
619 
620  //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
621  }
622  }
623 
624  // Last Character of Word
625  if (isBeginRegion && j == wInfo.characterCount - 1)
626  {
627  isBeginRegion = false;
628 
629  br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
630  tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
631 
632  // Transform coordinates to be relative to transform and account min descender and max ascender.
633  bl = rectTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
634  tl = rectTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
635  tr = rectTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
636  br = rectTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
637 
638  // Check for Intersection
639  if (PointIntersectRectangle(position, bl, tl, tr, br))
640  return i;
641 
642  //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
643  }
644  // If Word is split on more than one line.
645  else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
646  {
647  isBeginRegion = false;
648 
649  br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
650  tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
651 
652  // Transform coordinates to be relative to transform and account min descender and max ascender.
653  bl = rectTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
654  tl = rectTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
655  tr = rectTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
656  br = rectTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
657 
658  maxAscender = -Mathf.Infinity;
659  minDescender = Mathf.Infinity;
660 
661  // Check for Intersection
662  if (PointIntersectRectangle(position, bl, tl, tr, br))
663  return i;
664 
665  //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
666  }
667  }
668 
669  //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
670 
671  }
672 
673  return -1;
674  }
675 
676 
684  //public static int FindIntersectingWord(TextMeshProUGUI text, Vector3 position, Camera camera)
685  //{
686  // RectTransform rectTransform = text.rectTransform;
687 
688  // // Convert position into Worldspace coordinates
689  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
690 
691  // for (int i = 0; i < text.textInfo.wordCount; i++)
692  // {
693  // TMP_WordInfo wInfo = text.textInfo.wordInfo[i];
694 
695  // bool isBeginRegion = false;
696 
697  // Vector3 bl = Vector3.zero;
698  // Vector3 tl = Vector3.zero;
699  // Vector3 br = Vector3.zero;
700  // Vector3 tr = Vector3.zero;
701 
702  // float maxAscender = -Mathf.Infinity;
703  // float minDescender = Mathf.Infinity;
704 
705  // // Iterate through each character of the word
706  // for (int j = 0; j < wInfo.characterCount; j++)
707  // {
708  // int characterIndex = wInfo.firstCharacterIndex + j;
709  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
710  // int currentLine = currentCharInfo.lineNumber;
711 
712  // bool isCharacterVisible = characterIndex > text.maxVisibleCharacters ||
713  // currentCharInfo.lineNumber > text.maxVisibleLines ||
714  // (text.OverflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) ? false : true;
715 
716  // // Track maximum Ascender and minimum Descender for each word.
717  // maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
718  // minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
719 
720  // if (isBeginRegion == false && isCharacterVisible)
721  // {
722  // isBeginRegion = true;
723 
724  // bl = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
725  // tl = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
726 
727  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
728 
729  // // If Word is one character
730  // if (wInfo.characterCount == 1)
731  // {
732  // isBeginRegion = false;
733 
734  // br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
735  // tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
736 
737  // // Transform coordinates to be relative to transform and account min descender and max ascender.
738  // bl = rectTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
739  // tl = rectTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
740  // tr = rectTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
741  // br = rectTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
742 
743  // // Check for Intersection
744  // if (PointIntersectRectangle(position, bl, tl, tr, br))
745  // return i;
746 
747  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
748  // }
749  // }
750 
751  // // Last Character of Word
752  // if (isBeginRegion && j == wInfo.characterCount - 1)
753  // {
754  // isBeginRegion = false;
755 
756  // br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
757  // tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
758 
759  // // Transform coordinates to be relative to transform and account min descender and max ascender.
760  // bl = rectTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
761  // tl = rectTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
762  // tr = rectTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
763  // br = rectTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
764 
765  // // Check for Intersection
766  // if (PointIntersectRectangle(position, bl, tl, tr, br))
767  // return i;
768 
769  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
770  // }
771  // // If Word is split on more than one line.
772  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
773  // {
774  // isBeginRegion = false;
775 
776  // br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
777  // tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
778 
779  // // Transform coordinates to be relative to transform and account min descender and max ascender.
780  // bl = rectTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
781  // tl = rectTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
782  // tr = rectTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
783  // br = rectTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
784 
785  // maxAscender = -Mathf.Infinity;
786  // minDescender = Mathf.Infinity;
787 
788  // // Check for Intersection
789  // if (PointIntersectRectangle(position, bl, tl, tr, br))
790  // return i;
791 
792  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
793  // }
794  // }
795 
796  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
797 
798  // }
799 
800  // return -1;
801  //}
802 
803 
811  //public static int FindIntersectingWord(TextMeshPro text, Vector3 position, Camera camera)
812  //{
813  // Transform textTransform = text.transform;
814 
815  // // Convert position into Worldspace coordinates
816  // ScreenPointToWorldPointInRectangle(textTransform, position, camera, out position);
817 
818  // for (int i = 0; i < text.textInfo.wordCount; i++)
819  // {
820  // TMP_WordInfo wInfo = text.textInfo.wordInfo[i];
821 
822  // bool isBeginRegion = false;
823 
824  // Vector3 bl = Vector3.zero;
825  // Vector3 tl = Vector3.zero;
826  // Vector3 br = Vector3.zero;
827  // Vector3 tr = Vector3.zero;
828 
829  // float maxAscender = -Mathf.Infinity;
830  // float minDescender = Mathf.Infinity;
831 
832  // // Iterate through each character of the word
833  // for (int j = 0; j < wInfo.characterCount; j++)
834  // {
835  // int characterIndex = wInfo.firstCharacterIndex + j;
836  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
837  // int currentLine = currentCharInfo.lineNumber;
838 
839  // bool isCharacterVisible = characterIndex > text.maxVisibleCharacters ||
840  // currentCharInfo.lineNumber > text.maxVisibleLines ||
841  // (text.OverflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) ? false : true;
842 
843  // // Track maximum Ascender and minimum Descender for each word.
844  // maxAscender = Mathf.Max(maxAscender, currentCharInfo.ascender);
845  // minDescender = Mathf.Min(minDescender, currentCharInfo.descender);
846 
847  // if (isBeginRegion == false && isCharacterVisible)
848  // {
849  // isBeginRegion = true;
850 
851  // bl = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0);
852  // tl = new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0);
853 
854  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
855 
856  // // If Word is one character
857  // if (wInfo.characterCount == 1)
858  // {
859  // isBeginRegion = false;
860 
861  // br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
862  // tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
863 
864  // // Transform coordinates to be relative to transform and account min descender and max ascender.
865  // bl = textTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
866  // tl = textTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
867  // tr = textTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
868  // br = textTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
869 
870  // // Check for Intersection
871  // if (PointIntersectRectangle(position, bl, tl, tr, br))
872  // return i;
873 
874  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
875  // }
876  // }
877 
878  // // Last Character of Word
879  // if (isBeginRegion && j == wInfo.characterCount - 1)
880  // {
881  // isBeginRegion = false;
882 
883  // br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
884  // tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
885 
886  // // Transform coordinates to be relative to transform and account min descender and max ascender.
887  // bl = textTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
888  // tl = textTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
889  // tr = textTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
890  // br = textTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
891 
892  // // Check for Intersection
893  // if (PointIntersectRectangle(position, bl, tl, tr, br))
894  // return i;
895 
896  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
897  // }
898  // // If Word is split on more than one line.
899  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
900  // {
901  // isBeginRegion = false;
902 
903  // br = new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0);
904  // tr = new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0);
905 
906  // // Transform coordinates to be relative to transform and account min descender and max ascender.
907  // bl = textTransform.TransformPoint(new Vector3(bl.x, minDescender, 0));
908  // tl = textTransform.TransformPoint(new Vector3(tl.x, maxAscender, 0));
909  // tr = textTransform.TransformPoint(new Vector3(tr.x, maxAscender, 0));
910  // br = textTransform.TransformPoint(new Vector3(br.x, minDescender, 0));
911 
912  // // Reset maxAscender and minDescender for next word segment.
913  // maxAscender = -Mathf.Infinity;
914  // minDescender = Mathf.Infinity;
915 
916  // // Check for Intersection
917  // if (PointIntersectRectangle(position, bl, tl, tr, br))
918  // return i;
919 
920  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
921  // }
922  // }
923  // }
924 
925  // return -1;
926  //}
927 
928 
936  public static int FindNearestWord(TMP_Text text, Vector3 position, Camera camera)
937  {
938  RectTransform rectTransform = text.rectTransform;
939 
940  float distanceSqr = Mathf.Infinity;
941  int closest = 0;
942 
943  // Convert position into Worldspace coordinates
944  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
945 
946  for (int i = 0; i < text.textInfo.wordCount; i++)
947  {
948  TMP_WordInfo wInfo = text.textInfo.wordInfo[i];
949 
950  bool isBeginRegion = false;
951 
952  Vector3 bl = Vector3.zero;
953  Vector3 tl = Vector3.zero;
954  Vector3 br = Vector3.zero;
955  Vector3 tr = Vector3.zero;
956 
957  // Iterate through each character of the word
958  for (int j = 0; j < wInfo.characterCount; j++)
959  {
960  int characterIndex = wInfo.firstCharacterIndex + j;
961  TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
962  int currentLine = currentCharInfo.lineNumber;
963 
964  bool isCharacterVisible = currentCharInfo.isVisible;
965 
966  if (isBeginRegion == false && isCharacterVisible)
967  {
968  isBeginRegion = true;
969 
970  bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
971  tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
972 
973  //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
974 
975  // If Word is one character
976  if (wInfo.characterCount == 1)
977  {
978  isBeginRegion = false;
979 
980  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
981  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
982 
983  // Check for Intersection
984  if (PointIntersectRectangle(position, bl, tl, tr, br))
985  return i;
986 
987  // Find the closest line segment to position.
988  float dbl = DistanceToLine(bl, tl, position);
989  float dtl = DistanceToLine(tl, tr, position);
990  float dtr = DistanceToLine(tr, br, position);
991  float dbr = DistanceToLine(br, bl, position);
992 
993  float d = dbl < dtl ? dbl : dtl;
994  d = d < dtr ? d : dtr;
995  d = d < dbr ? d : dbr;
996 
997  if (distanceSqr > d)
998  {
999  distanceSqr = d;
1000  closest = i;
1001  }
1002  }
1003  }
1004 
1005  // Last Character of Word
1006  if (isBeginRegion && j == wInfo.characterCount - 1)
1007  {
1008  isBeginRegion = false;
1009 
1010  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1011  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1012 
1013  // Check for Intersection
1014  if (PointIntersectRectangle(position, bl, tl, tr, br))
1015  return i;
1016 
1017  // Find the closest line segment to position.
1018  float dbl = DistanceToLine(bl, tl, position);
1019  float dtl = DistanceToLine(tl, tr, position);
1020  float dtr = DistanceToLine(tr, br, position);
1021  float dbr = DistanceToLine(br, bl, position);
1022 
1023  float d = dbl < dtl ? dbl : dtl;
1024  d = d < dtr ? d : dtr;
1025  d = d < dbr ? d : dbr;
1026 
1027  if (distanceSqr > d)
1028  {
1029  distanceSqr = d;
1030  closest = i;
1031  }
1032  }
1033  // If Word is split on more than one line.
1034  else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1035  {
1036  isBeginRegion = false;
1037 
1038  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1039  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1040 
1041  // Check for Intersection
1042  if (PointIntersectRectangle(position, bl, tl, tr, br))
1043  return i;
1044 
1045  // Find the closest line segment to position.
1046  float dbl = DistanceToLine(bl, tl, position);
1047  float dtl = DistanceToLine(tl, tr, position);
1048  float dtr = DistanceToLine(tr, br, position);
1049  float dbr = DistanceToLine(br, bl, position);
1050 
1051  float d = dbl < dtl ? dbl : dtl;
1052  d = d < dtr ? d : dtr;
1053  d = d < dbr ? d : dbr;
1054 
1055  if (distanceSqr > d)
1056  {
1057  distanceSqr = d;
1058  closest = i;
1059  }
1060  }
1061  }
1062 
1063  //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1064  }
1065 
1066  return closest;
1067  }
1068 
1076  //public static int FindNearestWord(TextMeshProUGUI text, Vector3 position, Camera camera)
1077  //{
1078  // RectTransform rectTransform = text.rectTransform;
1079 
1080  // float distanceSqr = Mathf.Infinity;
1081  // int closest = 0;
1082 
1083  // // Convert position into Worldspace coordinates
1084  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
1085 
1086  // for (int i = 0; i < text.textInfo.wordCount; i++)
1087  // {
1088  // TMP_WordInfo wInfo = text.textInfo.wordInfo[i];
1089 
1090  // bool isBeginRegion = false;
1091 
1092  // Vector3 bl = Vector3.zero;
1093  // Vector3 tl = Vector3.zero;
1094  // Vector3 br = Vector3.zero;
1095  // Vector3 tr = Vector3.zero;
1096 
1097  // // Iterate through each character of the word
1098  // for (int j = 0; j < wInfo.characterCount; j++)
1099  // {
1100  // int characterIndex = wInfo.firstCharacterIndex + j;
1101  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1102  // int currentLine = currentCharInfo.lineNumber;
1103 
1104  // bool isCharacterVisible = characterIndex > text.maxVisibleCharacters ||
1105  // currentCharInfo.lineNumber > text.maxVisibleLines ||
1106  // (text.OverflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) ? false : true;
1107 
1108  // if (isBeginRegion == false && isCharacterVisible)
1109  // {
1110  // isBeginRegion = true;
1111 
1112  // bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1113  // tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1114 
1115  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1116 
1117  // // If Word is one character
1118  // if (wInfo.characterCount == 1)
1119  // {
1120  // isBeginRegion = false;
1121 
1122  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1123  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1124 
1125  // // Check for Intersection
1126  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1127  // return i;
1128 
1129  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1130  // }
1131  // }
1132 
1133  // // Last Character of Word
1134  // if (isBeginRegion && j == wInfo.characterCount - 1)
1135  // {
1136  // isBeginRegion = false;
1137 
1138  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1139  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1140 
1141  // // Check for Intersection
1142  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1143  // return i;
1144 
1145  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1146  // }
1147  // // If Word is split on more than one line.
1148  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1149  // {
1150  // isBeginRegion = false;
1151 
1152  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1153  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1154 
1155  // // Check for Intersection
1156  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1157  // return i;
1158 
1159  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1160  // }
1161  // }
1162 
1163  // // Find the closest line segment to position.
1164  // float dbl = DistanceToLine(bl, tl, position); // (position - bl).sqrMagnitude;
1165  // float dtl = DistanceToLine(tl, tr, position); // (position - tl).sqrMagnitude;
1166  // float dtr = DistanceToLine(tr, br, position); // (position - tr).sqrMagnitude;
1167  // float dbr = DistanceToLine(br, bl, position); // (position - br).sqrMagnitude;
1168 
1169  // float d = dbl < dtl ? dbl : dtl;
1170  // d = d < dtr ? d : dtr;
1171  // d = d < dbr ? d : dbr;
1172 
1173  // if (distanceSqr > d)
1174  // {
1175  // distanceSqr = d;
1176  // closest = i;
1177  // }
1178  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1179 
1180  // }
1181 
1182  // return closest;
1183  //}
1184 
1185 
1193  //public static int FindNearestWord(TextMeshPro text, Vector3 position, Camera camera)
1194  //{
1195  // Transform textTransform = text.transform;
1196 
1197  // float distanceSqr = Mathf.Infinity;
1198  // int closest = 0;
1199 
1200  // // Convert position into Worldspace coordinates
1201  // ScreenPointToWorldPointInRectangle(textTransform, position, camera, out position);
1202 
1203  // for (int i = 0; i < text.textInfo.wordCount; i++)
1204  // {
1205  // TMP_WordInfo wInfo = text.textInfo.wordInfo[i];
1206 
1207  // bool isBeginRegion = false;
1208 
1209  // Vector3 bl = Vector3.zero;
1210  // Vector3 tl = Vector3.zero;
1211  // Vector3 br = Vector3.zero;
1212  // Vector3 tr = Vector3.zero;
1213 
1214  // // Iterate through each character of the word
1215  // for (int j = 0; j < wInfo.characterCount; j++)
1216  // {
1217  // int characterIndex = wInfo.firstCharacterIndex + j;
1218  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1219  // int currentLine = currentCharInfo.lineNumber;
1220 
1221  // bool isCharacterVisible = characterIndex > text.maxVisibleCharacters ||
1222  // currentCharInfo.lineNumber > text.maxVisibleLines ||
1223  // (text.OverflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) ? false : true;
1224 
1225  // if (isBeginRegion == false && isCharacterVisible)
1226  // {
1227  // isBeginRegion = true;
1228 
1229  // bl = textTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1230  // tl = textTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1231 
1232  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1233 
1234  // // If Word is one character
1235  // if (wInfo.characterCount == 1)
1236  // {
1237  // isBeginRegion = false;
1238 
1239  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1240  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1241 
1242  // // Check for Intersection
1243  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1244  // return i;
1245 
1246  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1247  // }
1248  // }
1249 
1250  // // Last Character of Word
1251  // if (isBeginRegion && j == wInfo.characterCount - 1)
1252  // {
1253  // isBeginRegion = false;
1254 
1255  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1256  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1257 
1258  // // Check for Intersection
1259  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1260  // return i;
1261 
1262  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1263  // }
1264  // // If Word is split on more than one line.
1265  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1266  // {
1267  // isBeginRegion = false;
1268 
1269  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1270  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1271 
1272  // // Check for Intersection
1273  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1274  // return i;
1275 
1276  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1277  // }
1278  // }
1279 
1280  // // Find the closest line segment to position.
1281  // float dbl = DistanceToLine(bl, tl, position);
1282  // float dtl = DistanceToLine(tl, tr, position);
1283  // float dtr = DistanceToLine(tr, br, position);
1284  // float dbr = DistanceToLine(br, bl, position);
1285 
1286  // float d = dbl < dtl ? dbl : dtl;
1287  // d = d < dtr ? d : dtr;
1288  // d = d < dbr ? d : dbr;
1289 
1290  // if (distanceSqr > d)
1291  // {
1292  // distanceSqr = d;
1293  // closest = i;
1294  // }
1295  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1296 
1297  // }
1298 
1299  // return closest;
1300 
1301  //}
1302 
1303 
1311  public static int FindIntersectingLine(TMP_Text text, Vector3 position, Camera camera)
1312  {
1313  RectTransform rectTransform = text.rectTransform;
1314 
1315  int closest = -1;
1316 
1317  // Convert position into Worldspace coordinates
1318  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
1319 
1320  for (int i = 0; i < text.textInfo.lineCount; i++)
1321  {
1322  TMP_LineInfo lineInfo = text.textInfo.lineInfo[i];
1323 
1324  float ascender = rectTransform.TransformPoint(new Vector3(0, lineInfo.ascender, 0)).y;
1325  float descender = rectTransform.TransformPoint(new Vector3(0, lineInfo.descender, 0)).y;
1326 
1327  if (ascender > position.y && descender < position.y)
1328  {
1329  //Debug.Log("Position is on line " + i);
1330  return i;
1331  }
1332  }
1333 
1334  //Debug.Log("Closest line to position is " + closest);
1335  return closest;
1336  }
1337 
1338 
1346  public static int FindIntersectingLink(TMP_Text text, Vector3 position, Camera camera)
1347  {
1348  Transform rectTransform = text.transform;
1349 
1350  // Convert position into Worldspace coordinates
1351  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
1352 
1353  for (int i = 0; i < text.textInfo.linkCount; i++)
1354  {
1355  TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
1356 
1357  bool isBeginRegion = false;
1358 
1359  Vector3 bl = Vector3.zero;
1360  Vector3 tl = Vector3.zero;
1361  Vector3 br = Vector3.zero;
1362  Vector3 tr = Vector3.zero;
1363 
1364  // Iterate through each character of the word
1365  for (int j = 0; j < linkInfo.linkTextLength; j++)
1366  {
1367  int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
1368  TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1369  int currentLine = currentCharInfo.lineNumber;
1370 
1371  // Check if Link characters are on the current page
1372  if (text.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) continue;
1373 
1374  if (isBeginRegion == false)
1375  {
1376  isBeginRegion = true;
1377 
1378  bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1379  tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1380 
1381  //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1382 
1383  // If Word is one character
1384  if (linkInfo.linkTextLength == 1)
1385  {
1386  isBeginRegion = false;
1387 
1388  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1389  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1390 
1391  // Check for Intersection
1392  if (PointIntersectRectangle(position, bl, tl, tr, br))
1393  return i;
1394 
1395  //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1396  }
1397  }
1398 
1399  // Last Character of Word
1400  if (isBeginRegion && j == linkInfo.linkTextLength - 1)
1401  {
1402  isBeginRegion = false;
1403 
1404  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1405  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1406 
1407  // Check for Intersection
1408  if (PointIntersectRectangle(position, bl, tl, tr, br))
1409  return i;
1410 
1411  //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1412  }
1413  // If Word is split on more than one line.
1414  else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1415  {
1416  isBeginRegion = false;
1417 
1418  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1419  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1420 
1421  // Check for Intersection
1422  if (PointIntersectRectangle(position, bl, tl, tr, br))
1423  return i;
1424 
1425  //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1426  }
1427  }
1428 
1429  //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1430 
1431  }
1432 
1433  return -1;
1434  }
1435 
1443  //public static int FindIntersectingLink(TextMeshProUGUI text, Vector3 position, Camera camera)
1444  //{
1445  // Transform rectTransform = text.transform;
1446 
1447  // // Convert position into Worldspace coordinates
1448  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
1449 
1450  // for (int i = 0; i < text.textInfo.linkCount; i++)
1451  // {
1452  // TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
1453 
1454  // bool isBeginRegion = false;
1455 
1456  // Vector3 bl = Vector3.zero;
1457  // Vector3 tl = Vector3.zero;
1458  // Vector3 br = Vector3.zero;
1459  // Vector3 tr = Vector3.zero;
1460 
1461  // // Iterate through each character of the word
1462  // for (int j = 0; j < linkInfo.linkTextLength; j++)
1463  // {
1464  // int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
1465  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1466  // int currentLine = currentCharInfo.lineNumber;
1467 
1468  // // Check if Link characters are on the current page
1469  // if (text.OverflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) continue;
1470 
1471  // if (isBeginRegion == false)
1472  // {
1473  // isBeginRegion = true;
1474 
1475  // bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1476  // tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1477 
1478  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1479 
1480  // // If Word is one character
1481  // if (linkInfo.linkTextLength == 1)
1482  // {
1483  // isBeginRegion = false;
1484 
1485  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1486  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1487 
1488  // // Check for Intersection
1489  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1490  // return i;
1491 
1492  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1493  // }
1494  // }
1495 
1496  // // Last Character of Word
1497  // if (isBeginRegion && j == linkInfo.linkTextLength - 1)
1498  // {
1499  // isBeginRegion = false;
1500 
1501  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1502  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1503 
1504  // // Check for Intersection
1505  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1506  // return i;
1507 
1508  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1509  // }
1510  // // If Word is split on more than one line.
1511  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1512  // {
1513  // isBeginRegion = false;
1514 
1515  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1516  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1517 
1518  // // Check for Intersection
1519  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1520  // return i;
1521 
1522  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1523  // }
1524  // }
1525 
1526  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1527 
1528  // }
1529 
1530  // return -1;
1531  //}
1532 
1533 
1541  //public static int FindIntersectingLink(TextMeshPro text, Vector3 position, Camera camera)
1542  //{
1543  // Transform textTransform = text.transform;
1544 
1545  // // Convert position into Worldspace coordinates
1546  // ScreenPointToWorldPointInRectangle(textTransform, position, camera, out position);
1547 
1548  // for (int i = 0; i < text.textInfo.linkCount; i++)
1549  // {
1550  // TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
1551 
1552  // bool isBeginRegion = false;
1553 
1554  // Vector3 bl = Vector3.zero;
1555  // Vector3 tl = Vector3.zero;
1556  // Vector3 br = Vector3.zero;
1557  // Vector3 tr = Vector3.zero;
1558 
1559  // // Iterate through each character of the word
1560  // for (int j = 0; j < linkInfo.linkTextLength; j++)
1561  // {
1562  // int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
1563  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1564  // int currentLine = currentCharInfo.lineNumber;
1565 
1566  // // Check if Link characters are on the current page
1567  // if (text.OverflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) continue;
1568 
1569  // if (isBeginRegion == false)
1570  // {
1571  // isBeginRegion = true;
1572 
1573  // bl = textTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1574  // tl = textTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1575 
1576  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1577 
1578  // // If Word is one character
1579  // if (linkInfo.linkTextLength == 1)
1580  // {
1581  // isBeginRegion = false;
1582 
1583  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1584  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1585 
1586  // // Check for Intersection
1587  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1588  // return i;
1589 
1590  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1591  // }
1592  // }
1593 
1594  // // Last Character of Word
1595  // if (isBeginRegion && j == linkInfo.linkTextLength - 1)
1596  // {
1597  // isBeginRegion = false;
1598 
1599  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1600  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1601 
1602  // // Check for Intersection
1603  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1604  // return i;
1605 
1606  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1607  // }
1608  // // If Word is split on more than one line.
1609  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1610  // {
1611  // isBeginRegion = false;
1612 
1613  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1614  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1615 
1616  // // Check for Intersection
1617  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1618  // return i;
1619 
1620  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1621  // }
1622  // }
1623 
1624  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1625 
1626  // }
1627 
1628  // return -1;
1629  //}
1630 
1631 
1639  public static int FindNearestLink(TMP_Text text, Vector3 position, Camera camera)
1640  {
1641  RectTransform rectTransform = text.rectTransform;
1642 
1643  // Convert position into Worldspace coordinates
1644  ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
1645 
1646  float distanceSqr = Mathf.Infinity;
1647  int closest = 0;
1648 
1649  for (int i = 0; i < text.textInfo.linkCount; i++)
1650  {
1651  TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
1652 
1653  bool isBeginRegion = false;
1654 
1655  Vector3 bl = Vector3.zero;
1656  Vector3 tl = Vector3.zero;
1657  Vector3 br = Vector3.zero;
1658  Vector3 tr = Vector3.zero;
1659 
1660  // Iterate through each character of the link
1661  for (int j = 0; j < linkInfo.linkTextLength; j++)
1662  {
1663  int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
1664  TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1665  int currentLine = currentCharInfo.lineNumber;
1666 
1667  // Check if Link characters are on the current page
1668  if (text.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) continue;
1669 
1670  if (isBeginRegion == false)
1671  {
1672  isBeginRegion = true;
1673 
1674  //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1675 
1676  bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1677  tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1678 
1679  // If Link is one character
1680  if (linkInfo.linkTextLength == 1)
1681  {
1682  isBeginRegion = false;
1683 
1684  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1685  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1686 
1687  // Check for Intersection
1688  if (PointIntersectRectangle(position, bl, tl, tr, br))
1689  return i;
1690 
1691  // Find the closest line segment to position.
1692  float dbl = DistanceToLine(bl, tl, position);
1693  float dtl = DistanceToLine(tl, tr, position);
1694  float dtr = DistanceToLine(tr, br, position);
1695  float dbr = DistanceToLine(br, bl, position);
1696 
1697  float d = dbl < dtl ? dbl : dtl;
1698  d = d < dtr ? d : dtr;
1699  d = d < dbr ? d : dbr;
1700 
1701  if (distanceSqr > d)
1702  {
1703  distanceSqr = d;
1704  closest = i;
1705  }
1706 
1707  }
1708  }
1709 
1710  // Last Character of Word
1711  if (isBeginRegion && j == linkInfo.linkTextLength - 1)
1712  {
1713  isBeginRegion = false;
1714 
1715  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1716  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1717 
1718  // Check for Intersection
1719  if (PointIntersectRectangle(position, bl, tl, tr, br))
1720  return i;
1721 
1722  // Find the closest line segment to position.
1723  float dbl = DistanceToLine(bl, tl, position);
1724  float dtl = DistanceToLine(tl, tr, position);
1725  float dtr = DistanceToLine(tr, br, position);
1726  float dbr = DistanceToLine(br, bl, position);
1727 
1728  float d = dbl < dtl ? dbl : dtl;
1729  d = d < dtr ? d : dtr;
1730  d = d < dbr ? d : dbr;
1731 
1732  if (distanceSqr > d)
1733  {
1734  distanceSqr = d;
1735  closest = i;
1736  }
1737 
1738  }
1739  // If Link is split on more than one line.
1740  else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1741  {
1742  isBeginRegion = false;
1743 
1744  br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1745  tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1746 
1747  // Check for Intersection
1748  if (PointIntersectRectangle(position, bl, tl, tr, br))
1749  return i;
1750 
1751  // Find the closest line segment to position.
1752  float dbl = DistanceToLine(bl, tl, position);
1753  float dtl = DistanceToLine(tl, tr, position);
1754  float dtr = DistanceToLine(tr, br, position);
1755  float dbr = DistanceToLine(br, bl, position);
1756 
1757  float d = dbl < dtl ? dbl : dtl;
1758  d = d < dtr ? d : dtr;
1759  d = d < dbr ? d : dbr;
1760 
1761  if (distanceSqr > d)
1762  {
1763  distanceSqr = d;
1764  closest = i;
1765  }
1766  }
1767  }
1768 
1769  //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1770 
1771  }
1772 
1773  return closest;
1774  }
1775 
1776 
1784  //public static int FindNearestLink(TextMeshProUGUI text, Vector3 position, Camera camera)
1785  //{
1786  // RectTransform rectTransform = text.rectTransform;
1787 
1788  // // Convert position into Worldspace coordinates
1789  // ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
1790 
1791  // float distanceSqr = Mathf.Infinity;
1792  // int closest = 0;
1793 
1794  // for (int i = 0; i < text.textInfo.linkCount; i++)
1795  // {
1796  // TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
1797 
1798  // bool isBeginRegion = false;
1799 
1800  // Vector3 bl = Vector3.zero;
1801  // Vector3 tl = Vector3.zero;
1802  // Vector3 br = Vector3.zero;
1803  // Vector3 tr = Vector3.zero;
1804 
1805  // // Iterate through each character of the word
1806  // for (int j = 0; j < linkInfo.linkTextLength; j++)
1807  // {
1808  // int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
1809  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1810  // int currentLine = currentCharInfo.lineNumber;
1811 
1812  // if (isBeginRegion == false)
1813  // {
1814  // isBeginRegion = true;
1815 
1816  // bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1817  // tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1818 
1819  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1820 
1821  // // If Word is one character
1822  // if (linkInfo.linkTextLength == 1)
1823  // {
1824  // isBeginRegion = false;
1825 
1826  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1827  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1828 
1829  // // Check for Intersection
1830  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1831  // return i;
1832 
1833  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1834  // }
1835  // }
1836 
1837  // // Last Character of Word
1838  // if (isBeginRegion && j == linkInfo.linkTextLength - 1)
1839  // {
1840  // isBeginRegion = false;
1841 
1842  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1843  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1844 
1845  // // Check for Intersection
1846  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1847  // return i;
1848 
1849  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1850  // }
1851  // // If Word is split on more than one line.
1852  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1853  // {
1854  // isBeginRegion = false;
1855 
1856  // br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1857  // tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1858 
1859  // // Check for Intersection
1860  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1861  // return i;
1862 
1863  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1864  // }
1865  // }
1866 
1867  // // Find the closest line segment to position.
1868  // float dbl = DistanceToLine(bl, tl, position); // (position - bl).sqrMagnitude;
1869  // float dtl = DistanceToLine(tl, tr, position); // (position - tl).sqrMagnitude;
1870  // float dtr = DistanceToLine(tr, br, position); // (position - tr).sqrMagnitude;
1871  // float dbr = DistanceToLine(br, bl, position); // (position - br).sqrMagnitude;
1872 
1873  // float d = dbl < dtl ? dbl : dtl;
1874  // d = d < dtr ? d : dtr;
1875  // d = d < dbr ? d : dbr;
1876 
1877  // if (distanceSqr > d)
1878  // {
1879  // distanceSqr = d;
1880  // closest = i;
1881  // }
1882  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1883 
1884  // }
1885 
1886  // return closest;
1887  //}
1888 
1889 
1897  //public static int FindNearestLink(TextMeshPro text, Vector3 position, Camera camera)
1898  //{
1899  // Transform textTransform = text.transform;
1900 
1901  // // Convert position into Worldspace coordinates
1902  // ScreenPointToWorldPointInRectangle(textTransform, position, camera, out position);
1903 
1904  // float distanceSqr = Mathf.Infinity;
1905  // int closest = 0;
1906 
1907  // for (int i = 0; i < text.textInfo.linkCount; i++)
1908  // {
1909  // TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
1910 
1911  // bool isBeginRegion = false;
1912 
1913  // Vector3 bl = Vector3.zero;
1914  // Vector3 tl = Vector3.zero;
1915  // Vector3 br = Vector3.zero;
1916  // Vector3 tr = Vector3.zero;
1917 
1918  // // Iterate through each character of the word
1919  // for (int j = 0; j < linkInfo.linkTextLength; j++)
1920  // {
1921  // int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
1922  // TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
1923  // int currentLine = currentCharInfo.lineNumber;
1924 
1925  // if (isBeginRegion == false)
1926  // {
1927  // isBeginRegion = true;
1928 
1929  // bl = textTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
1930  // tl = textTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
1931 
1932  // //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
1933 
1934  // // If Word is one character
1935  // if (linkInfo.linkTextLength == 1)
1936  // {
1937  // isBeginRegion = false;
1938 
1939  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1940  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1941 
1942  // // Check for Intersection
1943  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1944  // return i;
1945 
1946  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1947  // }
1948  // }
1949 
1950  // // Last Character of Word
1951  // if (isBeginRegion && j == linkInfo.linkTextLength - 1)
1952  // {
1953  // isBeginRegion = false;
1954 
1955  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1956  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1957 
1958  // // Check for Intersection
1959  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1960  // return i;
1961 
1962  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1963  // }
1964  // // If Word is split on more than one line.
1965  // else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
1966  // {
1967  // isBeginRegion = false;
1968 
1969  // br = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
1970  // tr = textTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
1971 
1972  // // Check for Intersection
1973  // if (PointIntersectRectangle(position, bl, tl, tr, br))
1974  // return i;
1975 
1976  // //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
1977  // }
1978  // }
1979 
1980  // // Find the closest line segment to position.
1981  // float dbl = DistanceToLine(bl, tl, position);
1982  // float dtl = DistanceToLine(tl, tr, position);
1983  // float dtr = DistanceToLine(tr, br, position);
1984  // float dbr = DistanceToLine(br, bl, position);
1985 
1986  // float d = dbl < dtl ? dbl : dtl;
1987  // d = d < dtr ? d : dtr;
1988  // d = d < dbr ? d : dbr;
1989 
1990  // if (distanceSqr > d)
1991  // {
1992  // distanceSqr = d;
1993  // closest = i;
1994  // }
1995  // //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
1996 
1997  // }
1998  // return closest;
1999  //}
2000 
2001 
2002 
2012  private static bool PointIntersectRectangle(Vector3 m, Vector3 a, Vector3 b, Vector3 c, Vector3 d)
2013  {
2014  Vector3 ab = b - a;
2015  Vector3 am = m - a;
2016  Vector3 bc = c - b;
2017  Vector3 bm = m - b;
2018 
2019  float abamDot = Vector3.Dot(ab, am);
2020  float bcbmDot = Vector3.Dot(bc, bm);
2021 
2022  return 0 <= abamDot && abamDot <= Vector3.Dot(ab, ab) && 0 <= bcbmDot && bcbmDot <= Vector3.Dot(bc, bc);
2023  }
2024 
2025 
2034  public static bool ScreenPointToWorldPointInRectangle(Transform transform, Vector2 screenPoint, Camera cam, out Vector3 worldPoint)
2035  {
2036  worldPoint = (Vector3)Vector2.zero;
2037  Ray ray = RectTransformUtility.ScreenPointToRay(cam, screenPoint);
2038  float enter;
2039  if (!new Plane(transform.rotation * Vector3.back, transform.position).Raycast(ray, out enter))
2040  return false;
2041  worldPoint = ray.GetPoint(enter);
2042  return true;
2043  }
2044 
2045 
2046  private struct LineSegment
2047  {
2048  public Vector3 Point1;
2049  public Vector3 Point2;
2050 
2051  public LineSegment(Vector3 p1, Vector3 p2)
2052  {
2053  Point1 = p1;
2054  Point2 = p2;
2055  }
2056  }
2057 
2058 
2067  private static bool IntersectLinePlane(LineSegment line, Vector3 point, Vector3 normal, out Vector3 intersectingPoint)
2068  {
2069  intersectingPoint = Vector3.zero;
2070  Vector3 u = line.Point2 - line.Point1;
2071  Vector3 w = line.Point1 - point;
2072 
2073  float D = Vector3.Dot(normal, u);
2074  float N = -Vector3.Dot(normal, w);
2075 
2076  if (Mathf.Abs(D) < Mathf.Epsilon) // if line is parallel & co-planar to plane
2077  {
2078  if (N == 0)
2079  return true;
2080  else
2081  return false;
2082  }
2083 
2084  float sI = N / D;
2085 
2086  if (sI < 0 || sI > 1) // Line parallel to plane
2087  return false;
2088 
2089  intersectingPoint = line.Point1 + sI * u;
2090 
2091  return true;
2092  }
2093 
2094 
2102  public static float DistanceToLine(Vector3 a, Vector3 b, Vector3 point)
2103  {
2104  Vector3 n = b - a;
2105  Vector3 pa = a - point;
2106 
2107  float c = Vector3.Dot( n, pa );
2108 
2109  // Closest point is a
2110  if ( c > 0.0f )
2111  return Vector3.Dot( pa, pa );
2112 
2113  Vector3 bp = point - b;
2114 
2115  // Closest point is b
2116  if (Vector3.Dot( n, bp ) > 0.0f )
2117  return Vector3.Dot( bp, bp );
2118 
2119  // Closest point is between a and b
2120  Vector3 e = pa - n * (c / Vector3.Dot( n, n ));
2121 
2122  return Vector3.Dot( e, e );
2123  }
2124 
2125 
2134  //public static float DistanceToLineDirectional(Vector3 a, Vector3 b, Vector3 point, ref int direction)
2135  //{
2136  // Vector3 n = b - a;
2137  // Vector3 pa = a - point;
2138 
2139  // float c = Vector3.Dot(n, pa);
2140  // direction = -1;
2141 
2142  // // Closest point is a
2143  // if (c > 0.0f)
2144  // return Vector3.Dot(pa, pa);
2145 
2146  // Vector3 bp = point - b;
2147  // direction = 1;
2148 
2149  // // Closest point is b
2150  // if (Vector3.Dot(n, bp) > 0.0f)
2151  // return Vector3.Dot(bp, bp);
2152 
2153  // // Closest point is between a and b
2154  // Vector3 e = pa - n * (c / Vector3.Dot(n, n));
2155 
2156  // direction = 0;
2157  // return Vector3.Dot(e, e);
2158  //}
2159 
2160 
2164  const string k_lookupStringL = "-------------------------------- !-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-";
2165 
2169  const string k_lookupStringU = "-------------------------------- !-#$%&-()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[-]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~-";
2170 
2171 
2175  public static char ToLowerFast(char c)
2176  {
2177  if (c > k_lookupStringL.Length - 1)
2178  return c;
2179 
2180  return k_lookupStringL[c];
2181  }
2182 
2186  public static char ToUpperFast(char c)
2187  {
2188  if (c > k_lookupStringU.Length - 1)
2189  return c;
2190 
2191  return k_lookupStringU[c];
2192  }
2193 
2198  public static int GetSimpleHashCode(string s)
2199  {
2200  int hashCode = 0; // 5381;
2201 
2202  for (int i = 0; i < s.Length; i++)
2203  hashCode = (hashCode << 5) + hashCode ^ s[i];
2204 
2205  return hashCode;
2206  }
2207 
2212  public static uint GetSimpleHashCodeLowercase(string s)
2213  {
2214  uint hashCode = 5381;
2215 
2216  for (int i = 0; i < s.Length; i++)
2217  hashCode = (hashCode << 5) + hashCode ^ ToLowerFast(s[i]);
2218 
2219  return hashCode;
2220  }
2221 
2222 
2228  public static int HexToInt(char hex)
2229  {
2230  switch (hex)
2231  {
2232  case '0': return 0;
2233  case '1': return 1;
2234  case '2': return 2;
2235  case '3': return 3;
2236  case '4': return 4;
2237  case '5': return 5;
2238  case '6': return 6;
2239  case '7': return 7;
2240  case '8': return 8;
2241  case '9': return 9;
2242  case 'A': return 10;
2243  case 'B': return 11;
2244  case 'C': return 12;
2245  case 'D': return 13;
2246  case 'E': return 14;
2247  case 'F': return 15;
2248  case 'a': return 10;
2249  case 'b': return 11;
2250  case 'c': return 12;
2251  case 'd': return 13;
2252  case 'e': return 14;
2253  case 'f': return 15;
2254  }
2255  return 15;
2256  }
2257 
2258 
2264  public static int StringToInt(string s)
2265  {
2266  int value = 0;
2267 
2268  for (int i = 0; i < s.Length; i++)
2269  {
2270  value += HexToInt(s[i]) * (int)Mathf.Pow(16, (s.Length - 1) - i);
2271  }
2272 
2273  return value;
2274  }
2275 
2276  }
2277 }
Structure which contains the character index and position of caret relative to the character.
Base class which contains common properties and functions shared between the TextMeshPro and TextMesh...
Definition: TMP_Text.cs:110
new RectTransform rectTransform
Returns are reference to the RectTransform
Definition: TMP_Text.cs:1063
TMP custom data type to represent 32 bit characters.
TMP_TextInfo textInfo
Returns data about the text object which includes information about each character,...
Definition: TMP_Text.cs:1014