Search Unity

Moving an InputField according to the TextMeshPro text

Discussion in 'Scripting' started by Micio_del_Cheshire, Sep 21, 2018.

  1. Micio_del_Cheshire

    Micio_del_Cheshire

    Joined:
    Oct 24, 2013
    Posts:
    28
    I'm trying to simulate a terminal.
    I have a TextMesh Pro text field which display all the text (from top to bottom).
    And I have an Input Field.
    Initially it's at the top of the empty text field, and every time the user writes something, the text field fills up and the input field should move down a line.
    All like a normal bash/cmd terminal.

    But, I can't do that. Even if there is no line spacing, and they have the same font size, when I move down the input field for a while, the gap increases (or decreseas, tweaking with millimetric precision).

    Is there a way to do it?

    Thanks for the help ^^
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    TextMeshPro has a function called GetPreferredValues() that can tell you how much space the current text takes up. (You can specify either the width or the height in order to see what the other dimension should be within that constraint.)
     
  3. Micio_del_Cheshire

    Micio_del_Cheshire

    Joined:
    Oct 24, 2013
    Posts:
    28
    GetPreferredValues returns the size of the TexMesh Pro rect, and in my case it has a fixed size.
    To be more clear, here's a little image (great artist skills here)

    https://imgur.com/cufCOBW
     
    Last edited: Sep 22, 2018
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Uh...I've written a bunch of different UI components that resize to the amount of text content by using GetPreferredValues(), so I'm reasonably confident it's giving values based on the text, not the transform.

    For instance, this component will resize its transform based on the amount of space needed for text in a specified object. It can be used directly on the same object as the text, or on a parent container.

    Code (CSharp):
    1. using UnityEngine;
    2. using TMPro;
    3.  
    4. // Resizes this object based on the preferred size of a TMP Text
    5. [ExecuteInEditMode]
    6. public class TextSizer : MonoBehaviour
    7. {
    8.     public TextMeshProUGUI text;
    9.     public Vector2 padding;
    10.     public Vector2 maxSize = new Vector2(1000, float.PositiveInfinity);
    11.     public Vector2 minSize;
    12.  
    13.     public enum Mode
    14.     {
    15.         None        = 0,
    16.         Horizontal  = 0x1,
    17.         Vertical    = 0x2,
    18.         Both        = Horizontal | Vertical
    19.     }
    20.     public Mode controlAxes = Mode.Both;
    21.  
    22.     protected string lastText = null;
    23.     protected Vector2 lastSize;
    24.     protected bool forceRefresh = false;
    25.  
    26.     protected virtual float MinX { get {
    27.             if ((controlAxes & Mode.Horizontal) != 0) return minSize.x;
    28.             return GetComponent<RectTransform>().rect.width - padding.x;
    29.         } }
    30.     protected virtual float MinY { get {
    31.             if ((controlAxes & Mode.Vertical) != 0) return minSize.y;
    32.             return GetComponent<RectTransform>().rect.height - padding.y;
    33.         } }
    34.     protected virtual float MaxX { get {
    35.             if ((controlAxes & Mode.Horizontal) != 0) return maxSize.x;
    36.             return GetComponent<RectTransform>().rect.width - padding.x;
    37.         } }
    38.     protected virtual float MaxY { get {
    39.             if ((controlAxes & Mode.Vertical) != 0) return maxSize.y;
    40.             return GetComponent<RectTransform>().rect.height - padding.y;
    41.         } }
    42.  
    43.     protected virtual void Update ()
    44.     {
    45.         RectTransform rt = GetComponent<RectTransform>();
    46.         if (text != null && (text.text != lastText || lastSize != rt.rect.size || forceRefresh))
    47.         {
    48.             lastText = text.text;
    49.             Vector2 preferredSize = text.GetPreferredValues(MaxX, MaxY);
    50.             preferredSize.x = Mathf.Clamp(preferredSize.x, MinX, MaxX);
    51.             preferredSize.y = Mathf.Clamp(preferredSize.y, MinY, MaxY);
    52.             preferredSize += padding;
    53.  
    54.             if ((controlAxes & Mode.Horizontal) != 0)
    55.             {
    56.                 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, preferredSize.x);
    57.             }
    58.             if ((controlAxes & Mode.Vertical) != 0)
    59.             {
    60.                 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, preferredSize.y);
    61.             }
    62.             lastSize = rt.rect.size;
    63.             forceRefresh = false;
    64.         }
    65.     }
    66.  
    67.     // Forces a size recalculation on next Update
    68.     public virtual void Refresh()
    69.     {
    70.         forceRefresh = true;
    71.     }
    72. }
     
  5. Micio_del_Cheshire

    Micio_del_Cheshire

    Joined:
    Oct 24, 2013
    Posts:
    28
    Maybe you're right. What am I saying, probably you're totally right. Thanks for teaching me and sharing me that code.

    I discovered that it was because a scroll rect fault: it had child size vertical control, so the size of the text field was clamped to the max size of the scroll view. My bad. Now I solved it.

    Thank you again for your time and your help ^^