Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

TextMesh Pro Sharing code for GetRenderedValues that doesn't return stupid values

Discussion in 'UGUI & TextMesh Pro' started by tomkail_betterup, Sep 7, 2022.

  1. tomkail_betterup

    tomkail_betterup

    Joined:
    Nov 17, 2021
    Posts:
    105
    Absolutely LOVE TMP, but we've had no end of problems using GetRenderedValues; it just loves to return Infinity, NaN, or other stupid values.
    Would sort of love to see this get fixed, but in the meantime here's a function that makes it work as you'd expect, and also allows passing a custom string, just like GetPreferredValues(text) does.

    Gist here, which I'll update with improvements as they come.

    Code (CSharp):
    1. // Gets the tightest bounds for the text by updating the text and using GetRenderedValues
    2.     // Note this uses sizeDelta for sizing so won't work when using anchors.
    3.     // This is wayyyy more reliable than the actual GetRenderedValues because it won't return stupid values, as GetRenderedValues is prone to doing.
    4.     public static Vector2 GetRenderedValues (this TMP_Text textMeshPro, string text, float maxWidth = Mathf.Infinity, float maxHeight = Mathf.Infinity, bool onlyVisibleCharacters = true) {
    5.         if(string.IsNullOrEmpty(text)) return Vector2.zero;
    6.  
    7.         var originalRenderMode = textMeshPro.renderMode;
    8.         var originalText = textMeshPro.text;
    9.         var originalDeltaSize = textMeshPro.rectTransform.sizeDelta;
    10.      
    11.         textMeshPro.renderMode = TextRenderFlags.DontRender;
    12.         textMeshPro.text = text;
    13.         textMeshPro.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, maxWidth);
    14.         textMeshPro.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, maxHeight);
    15.         textMeshPro.ForceMeshUpdate(true);
    16.  
    17.         if(text.Length == 0) return Vector2.zero;
    18.         // This doesn't work if the component is disabled - but it's better! I'm not even sure this function works while disabled...
    19.         // if(textMeshPro.textInfo.characterCount == 0) return Vector2.zero;
    20.  
    21.         // If width/height is Infinity/<0 renderedSize can be NaN. In that case, use preferredValues
    22.         var renderedSize = textMeshPro.GetRenderedValues(onlyVisibleCharacters);
    23.         if(IsInvalidFloat(renderedSize.x) || IsInvalidFloat(renderedSize.y)) {
    24.             var preferredSize = textMeshPro.GetPreferredValues(text, maxWidth, maxHeight);
    25.             // I've seen this come out as -4294967000.00 when the string has only a zero-width space (\u200B) with onlyVisibleCharacters true. In any case it makes no sense for the size to be < 0.
    26.             preferredSize = new Vector2(Mathf.Max(preferredSize.x, 0), Mathf.Max(preferredSize.y, 0));
    27.             if(IsInvalidFloat(renderedSize.x)) renderedSize.x = preferredSize.x;
    28.             if(IsInvalidFloat(renderedSize.y)) renderedSize.y = preferredSize.y;
    29.         }
    30.  
    31.         bool IsInvalidFloat (float f) {return float.IsNaN(f) || f == Mathf.Infinity || f < 0;}
    32.      
    33.         textMeshPro.renderMode = originalRenderMode;
    34.         textMeshPro.text = originalText;
    35.         textMeshPro.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, originalDeltaSize.x);
    36.         textMeshPro.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, originalDeltaSize.y);
    37.         textMeshPro.ForceMeshUpdate(true);  
    38.      
    39.         return renderedSize;
    40.     }
     
    josguerra99 likes this.