Search Unity

Bug TMPro Input field selection doesn't work when horizontal

Discussion in 'UGUI & TextMesh Pro' started by smoketh, Oct 6, 2020.

  1. smoketh

    smoketh

    Joined:
    Sep 14, 2012
    Posts:
    29
    Steps to reproduce
    1. Create a worldspace canvas.
    2. Place it so that it's facing Upwards (y).
    3. Add TMPro input field, multiline.
    4. Add more than 1 line of text
    5. Try selecting lines/placing caret below first one

    Discovered bug/patch
    The bug resides in TMP_TextUtilities.cs
    public static int FindNearestLine {}

    Originally:
    Code (CSharp):
    1. public static int FindNearestLine(TMP_Text text, Vector3 position, Camera camera)
    2.         {
    3.             RectTransform rectTransform = text.rectTransform;
    4.  
    5.             float distance = Mathf.Infinity;
    6.             int closest = -1;
    7.  
    8.             // Convert position into Worldspace coordinates
    9.             ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
    10.  
    11.             for (int i = 0; i < text.textInfo.lineCount; i++)
    12.             {
    13.                 TMP_LineInfo lineInfo = text.textInfo.lineInfo[i];
    14.  
    15.                 float ascender = rectTransform.TransformPoint(new Vector3(0, lineInfo.ascender, 0)).y;
    16.                 float descender = rectTransform.TransformPoint(new Vector3(0, lineInfo.descender, 0)).y;
    17.  
    18.                 if (ascender > position.y && descender < position.y)
    19.                 {
    20.                     //Debug.Log("Position is on line " + i);
    21.                     return i;
    22.                 }
    23.  
    24.                 float d0 = Mathf.Abs(ascender - position.y);
    25.                 float d1 = Mathf.Abs(descender - position.y);
    26.  
    27.                 float d = Mathf.Min(d0, d1);
    28.                 if (d < distance)
    29.                 {
    30.                     distance = d;
    31.                     closest = i;
    32.                 }
    33.             }
    34.  
    35.             //Debug.Log("Closest line to position is " + closest);
    36.             return closest;
    37.         }
    As you can see, originally starting line 15 - it checks against Y. The problem is - it's Y in world coords, so that's obviously a bug. Have this been a vertical-only object - fine. It isn't. It can be rotated in which-ever direction.
    Fix:
    Code (CSharp):
    1.         public static int FindNearestLine(TMP_Text text, Vector3 position, Camera camera)
    2.         {
    3.             RectTransform rectTransform = text.rectTransform;
    4.  
    5.             float distance = Mathf.Infinity;
    6.             int closest = -1;
    7.  
    8.             // Convert position into Worldspace coordinates
    9.             ScreenPointToWorldPointInRectangle(rectTransform, position, camera, out position);
    10.             for (int i = 0; i < text.textInfo.lineCount; i++)
    11.             {
    12.                 TMP_LineInfo lineInfo = text.textInfo.lineInfo[i];
    13.                 Vector3 ascender = rectTransform.TransformPoint(new Vector3(0, lineInfo.ascender, 0));
    14.                 Vector3 descender = rectTransform.TransformPoint(new Vector3(0, lineInfo.descender, 0));
    15.  
    16.                 float d0 = Vector3.Distance(ascender, position);
    17.                 float d1 = Vector3.Distance(descender, position);
    18.                 float d = Mathf.Min(d0, d1);
    19.                 if (d < distance)
    20.                 {
    21.                     distance = d;
    22.                     closest = i;
    23.                 }
    24.             }
    25.  
    26.             //Debug.Log("Closest line to position is " + closest);
    27.             return closest;
    28.         }
    Replace with fully 3 dimensional distance check.
     
    Last edited: Oct 6, 2020