Search Unity

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:
    106
    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.