Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Bug TMP_TextUtilities.FindIntersectingLink is bugged on TextOverflowModes.Link

Discussion in 'UGUI & TextMesh Pro' started by unity_3u_mH0oppRw7WA, Aug 22, 2023.

  1. unity_3u_mH0oppRw7WA

    unity_3u_mH0oppRw7WA

    Joined:
    Jan 31, 2021
    Posts:
    1
    If I have multiple Text(UI) components connected to each other by TextOverflowMode -> Linked, the linked text boxes will not support TMP_TextUtilities.FindIntersectingLink.

    Example:

    • Text1: Contains some links and is connected to Text2 by TextOverflowMode -> Linked
    • Text2: Contains some links and is connected to Text3 by TextOverflowMode -> Linked
    • Text3: Contains some links and is set as Overflow

    If i run FindIntersectingLink, Text1 finds the links correctly, Text2 doesn't, Text3 does.

    Cause:
    When FindIntersectingLink is run on Text2, it iterates through ALL the links found, including the ones that are in Text1.

    From implementation of TMP_TextUtilities: 1399
    Code (CSharp):
    1. // Last Character of Word
    2. if (isBeginRegion && j == linkInfo.linkTextLength - 1)
    3. {
    4.     isBeginRegion = false;
    5.  
    6.     br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
    7.     tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
    8.  
    9.     // Check for Intersection
    10.     if (PointIntersectRectangle(position, bl, tl, tr, br))
    11.         return i;
    12.  
    13.     //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
    14. }


    This will make PointIntersectRectangle(position, bl, tl, tr, br) to return true when bl == br and tl == tr since the point found in Text1 is invalid and will be set at the origin of the transform.

    Result: whenever Text2 is hovered, it will think that the first link in Text 1has being hovered.
     
  2. smallg2023

    smallg2023

    Joined:
    Sep 2, 2018
    Posts:
    112
    yes, just come across this bug too, the FindIntersectingLink() function is always returning 0 for the second box no matter which link you actually click

    edit:
    sort of fixed it by modifying the FindIntersectingLink code
    you can exit the loop early if the character isn't visible

    edit2: still breaks if the link is split between the 2 boxes.. not sure how to fix that yet (i guess it's ok if you make sure you have 1 word links)

    Code (CSharp):
    1. if (linkInfo.linkTextfirstCharacterIndex < text.firstVisibleCharacter)
    2.       {
    3.         continue;
    4.       }
    so extract out these 3 functions to your own file and call the FindIntersectingLink() from that script instead
    Code (CSharp):
    1. public static int FindIntersectingLink(TMP_Text text, Vector3 position, Camera camera)
    2.   {
    3.     Transform rectTransform = text.transform;
    4.  
    5.     // Convert position into Worldspace coordinates
    6.     ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
    7.  
    8.     for (int i = 0; i < text.textInfo.linkCount; i++)
    9.     {
    10.       TMP_LinkInfo linkInfo = text.textInfo.linkInfo[i];
    11.  
    12.       bool isBeginRegion = false;
    13.  
    14.       Vector3 bl = Vector3.zero;
    15.       Vector3 tl = Vector3.zero;
    16.       Vector3 br = Vector3.zero;
    17.       Vector3 tr = Vector3.zero;
    18.  
    19.       if (linkInfo.linkTextfirstCharacterIndex < text.firstVisibleCharacter)
    20.       {
    21.         continue;
    22.       }
    23.  
    24.       // Iterate through each character of the word
    25.       for (int j = 0; j < linkInfo.linkTextLength; j++)
    26.       {
    27.         int characterIndex = linkInfo.linkTextfirstCharacterIndex + j;
    28.         TMP_CharacterInfo currentCharInfo = text.textInfo.characterInfo[characterIndex];
    29.         int currentLine = currentCharInfo.lineNumber;
    30.  
    31.         // Check if Link characters are on the current page
    32.         if (text.overflowMode == TextOverflowModes.Page && currentCharInfo.pageNumber + 1 != text.pageToDisplay) continue;
    33.  
    34.         if (isBeginRegion == false)
    35.         {
    36.           isBeginRegion = true;
    37.  
    38.           bl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.descender, 0));
    39.           tl = rectTransform.TransformPoint(new Vector3(currentCharInfo.bottomLeft.x, currentCharInfo.ascender, 0));
    40.  
    41.           //Debug.Log("Start Word Region at [" + currentCharInfo.character + "]");
    42.  
    43.           // If Word is one character
    44.           if (linkInfo.linkTextLength == 1)
    45.           {
    46.             isBeginRegion = false;
    47.  
    48.             br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
    49.             tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
    50.  
    51.             // Check for Intersection
    52.             if (PointIntersectRectangle(position, bl, tl, tr, br))
    53.               return i;
    54.  
    55.             //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
    56.           }
    57.         }
    58.  
    59.         // Last Character of Word
    60.         if (isBeginRegion && j == linkInfo.linkTextLength - 1)
    61.         {
    62.           isBeginRegion = false;
    63.  
    64.           br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
    65.           tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
    66.  
    67.           // Check for Intersection
    68.           if (PointIntersectRectangle(position, bl, tl, tr, br))
    69.             return i;
    70.  
    71.           //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
    72.         }
    73.         // If Word is split on more than one line.
    74.         else if (isBeginRegion && currentLine != text.textInfo.characterInfo[characterIndex + 1].lineNumber)
    75.         {
    76.           isBeginRegion = false;
    77.  
    78.           br = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.descender, 0));
    79.           tr = rectTransform.TransformPoint(new Vector3(currentCharInfo.topRight.x, currentCharInfo.ascender, 0));
    80.  
    81.           // Check for Intersection
    82.           if (PointIntersectRectangle(position, bl, tl, tr, br))
    83.             return i;
    84.  
    85.           //Debug.Log("End Word Region at [" + currentCharInfo.character + "]");
    86.         }
    87.       }
    88.  
    89.       //Debug.Log("Word at Index: " + i + " is located at (" + bl + ", " + tl + ", " + tr + ", " + br + ").");
    90.  
    91.     }
    92.  
    93.     return -1;
    94.   }
    95.  
    96.   public static bool ScreenPointToWorldPointInRectangle(Transform transform, Vector2 screenPoint, Camera cam, out Vector3 worldPoint)
    97.   {
    98.     worldPoint = (Vector3)Vector2.zero;
    99.     Ray ray = RectTransformUtility.ScreenPointToRay(cam, screenPoint);
    100.  
    101.     float enter;
    102.     if (!new Plane(transform.rotation * Vector3.back, transform.position).Raycast(ray, out enter))
    103.       return false;
    104.  
    105.     worldPoint = ray.GetPoint(enter);
    106.  
    107.     return true;
    108.   }
    109.  
    110.   private static bool PointIntersectRectangle(Vector3 m, Vector3 a, Vector3 b, Vector3 c, Vector3 d)
    111.   {
    112.     Vector3 ab = b - a;
    113.     Vector3 am = m - a;
    114.     Vector3 bc = c - b;
    115.     Vector3 bm = m - b;
    116.  
    117.     float abamDot = Vector3.Dot(ab, am);
    118.     float bcbmDot = Vector3.Dot(bc, bm);
    119.  
    120.     return 0 <= abamDot && abamDot <= Vector3.Dot(ab, ab) && 0 <= bcbmDot && bcbmDot <= Vector3.Dot(bc, bc);
    121.   }
     
    Last edited: Oct 13, 2023
    unity_03shiju123 and nithinsb like this.
  3. unity_03shiju123

    unity_03shiju123

    Joined:
    Apr 3, 2020
    Posts:
    3
    You saved me!!!!!!!!!!