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.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

TextMesh Pro Single-line TextMeshPro Input field won't move to start / reset scroll

Discussion in 'UGUI & TextMesh Pro' started by lordyluke, Jun 24, 2023.

  1. lordyluke

    lordyluke

    Joined:
    Oct 28, 2017
    Posts:
    9
    Hello,

    I'm having issues reseting TMP Input field scroll on end edit. I have a TrackMania style nickname coloring (player using wildcards to color text) in my game and the input field looks like this when the game starts:
    upload_2023-6-24_18-14-4.png

    Upon clicking into the field, the colored text is transformed to a wildcard text, such as:
    upload_2023-6-24_18-15-22.png

    Player can then change colors and formating using the "*" wildcards, e.g. "*F00" is translated into <color=red> in the background.

    I'm using OnSelect and OnEndEdit to convert the text between the wildcard form and colored form.

    The issue happens when the nickname including wildcards is longer than the input element and player scrolls to the end of the field, then exits the field by clicking outside:
    upload_2023-6-24_18-18-2.png

    I noticed the text and caret rectTransform position stays the same after clicking out of the field (-425):
    upload_2023-6-24_18-20-8.png

    I cannot find a working way to move/scroll/reset the input field back to the start position after clicking out of the field (after converting the text from the usually longer wildcard text into the usually shorter colored text).

    I tried all tips I found around the forums, but I think the most obvious one - MoveTextStart should work and it does not for me. I tried waiting for end of frame, or even for some seconds, tried swapping the order of changing the text and using the MoveToStart, etc. but the move to start never happens and the text and caret remain scrolled:

    Code (CSharp):
    1.     public void OnStartEdit()
    2.     {
    3.         if (graphic != null) graphic.SetActive(false);
    4.         StartCoroutine(OnStartEditCoroutine());
    5.     }
    6.  
    7.     public void OnEndEdit()
    8.     {
    9.         if (graphic != null) graphic.SetActive(true);
    10.         StartCoroutine(OnEndEditCoroutine());
    11.     }
    12.  
    13.     private IEnumerator OnStartEditCoroutine()
    14.     {
    15.         yield return new WaitForEndOfFrame();
    16.         input.text = TextColorUtil.FromTextMeshPro(input.text);
    17.     }
    18.  
    19.     private IEnumerator OnEndEditCoroutine()
    20.     {
    21.         yield return new WaitForSeconds(1);
    22.         input.text = TextColorUtil.ToTextMeshPro(input.text);
    23.         yield return new WaitForSeconds(1);
    24.         input.MoveTextStart(true);
    25.         yield return new WaitForSeconds(1);
    26.         input.caretPosition = 0;
    27.     }
    Note: The OnStartEdit and OnEndEdit methods are linked from the object inspector, directly from the input component.

    I also tried resetting the position of the text component myself, that worked, but led to a very inconsistent state of the input field, e.g. when clicking inside again, the caret position was broken, the text selection was offset from the mouse, etc.

    Does anybody have any suggestions?
     
  2. hwk9120

    hwk9120

    Joined:
    May 9, 2023
    Posts:
    15
    Hi,
    Could you tell me exactly what the function you intended is?
    Should the front of the text be displayed when you type it in the input field and then click outside?

    ---
    I've tried something and I found this solution works. But I think using GameObject.Find("Caret") is not goooooooood.

    Code (CSharp):
    1. public void OnEndEdit()
    2. {
    3.     inputField.caretPosition = 0; // maybe useless code
    4.     inputField.textComponent.rectTransform.localPosition = Vector3.zero;
    5.     GameObject.Find("Caret").GetComponent<RectTransform>().localPosition = Vector3.zero;
    6. }
     
    Last edited: Jun 28, 2023
  3. lordyluke

    lordyluke

    Joined:
    Oct 28, 2017
    Posts:
    9
    Hello hwk9120,

    Your answer steered me in the right direction and the issue is solved now, thank you a lot! :)

    The code I ended up with is
    Code (CSharp):
    1.  
    2. // Convert the text from wildcard format into colored TMP format.
    3. input.text = TextColorUtil.ToTextMeshPro(input.text);
    4.        
    5. /* The below is a fix for Unity TM Input field not resetting scroll when exiting the field. This makes the
    6. input field scroll back so that the player sees the beginning of the text when exiting the field. */
    7. _textComponent.rectTransform.SetLeft(0);
    8. _textComponent.rectTransform.SetRight(0);
    9. _caretComponent.rectTransform.SetLeft(0);
    10. _caretComponent.rectTransform.SetRight(0)
    11. ;
    SetLeft and SetRight being just simple extension methods to zero the rectTransform.

    Setting the caretPosition to 0 was not needed in the end.

    Same as you, I didn't like the Find("Caret"). So I basically just created a custom MonoBehavior class called ColoredInputField, where I find the appropriate Caret in Awake method, like this:
    Code (CSharp):
    1. _caretComponent = input.GetComponentInChildren<TMP_SelectionCaret>();
    I mean, definitely not perfect, but works reliably for me now.
     
    hwk9120 likes this.
  4. hwk9120

    hwk9120

    Joined:
    May 9, 2023
    Posts:
    15
    Good to hear that!