Search Unity

TextMeshProUGUI preferredWidth incorrect when text contains tabs

Discussion in 'UGUI & TextMesh Pro' started by JoeStrout, Mar 18, 2020.

  1. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Here's an example:

    upload_2020-3-18_13-16-37.png

    The magenta box around each line shows the object bounds, which is set by calling preferredWidth. It's correct for lines which are not intended. For lines indented with one tab (like "c = a+b"), it's too short, by about a tab width. For lines indented with two tabs (like the two print statements in the middle), it's short by even more.

    All I want to do is size the bounds of each TextMeshProUGUI correctly, so I can then find the widest line and correctly adjust my scrollbars. Is there any workaround for this issue?

    (Tested using TMPro 1.4.1 in Unity 2018.4.15f1.)
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Since I made a lot of changes in subsequent releases of the TMP package. Can you please test with version 1.5.0-preview.8 to see if the report width appears to remain incorrect?
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I tried, but it generates an error:
    EDIT: but after changing the scripting runtime to 4.x, it works, and the bug is gone. preferredWidth appears to return a correct answer even in the presence of tabs.

    Now, since my code here is itself an asset in the Asset Store, I'd like to include the work-around for people using an older version of TMPro... is there anywhere I can get the TMPro version number at runtime?
     
    Last edited: Mar 18, 2020
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    To get the version number you would have to go through the Package Manager API which should allow you to query what version of packages are in use. I haven't looked at this API myself but I know this functionality is there.
     
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    @Stephan_B, I'm sad to say this bug is back (in TMPro version 2.0.1, running in Unity 2019.3.9f1), with both 4.x runtime and 2.0 runtime.

    upload_2021-1-17_7-7-3.png

    The white boxes (and the one yellow one for line selected in the hierarchy) indicate bounds of the TMProUGUI objects, whose width was set with preferredWidth. The code looks like this:
    Code (CSharp):
    1.             var tmPro = uiText as TextMeshProUGUI;
    2.             tmPro.text = s;
    3.             if (sizeToFit) {
    4.                 tmPro.ForceMeshUpdate(true);
    5.                 float x = tmPro.preferredWidth;
    6.                 uiText.rectTransform.sizeDelta = new Vector2(x, uiText.rectTransform.sizeDelta.y);
    7.             }
    8.  
    As you can see, it works fine for the unindented lines (lines 1 and 8 in the example above). But for lines with an initial tab, it's returning a width that is much too short. The more initial tabs there are, the more wrong it is.

    In case it provides some clue, the inspector for the selected line looks like:

    upload_2021-1-17_7-10-41.png

    ...and the face info for the font looks like:
    upload_2021-1-17_7-11-32.png

    I need to ship this software soon. Perhaps if you can pin down what the problem is under the hood, you can suggest a reliable workaround?
     
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Version 2.0.1 is an older version of the TMP package which is now version 2.1.3 for Unity 2019.4.

    Please make sure you didn't upgrade from a newer version in 2018.4 like 1.5.3 to an older 2.0.1 in Unity 2019.4. If that is the case, also make sure text alignment didn't get messed up.
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Wait. You're saying 1.5.3 is newer than 2.0.1? What strange versioning system is this (and more importantly, where can I read more about it so I'm not so confused)?

    EDIT: Package Manager says I'm up to date:
    upload_2021-1-17_19-51-32.png
     
  8. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Version 2.0.1 was the first release for Unity 2019.x and goes back to May 2019.

    As seen below in Package Manager the latest for 2019.4 is version 2.1.3.

    upload_2021-1-17_23-3-4.png

    In terms of the versioning, it is the result of API changes and other changes in Unity that ended up requiring different versions of the package for Unity 2018.x, 2019,x and 2020.x. As such, version 1.x is for Unity 2018.4, version 2.x for Unity 2019.x and version 3.x for Unity 2020.

    Unfortunately, it is not possible to have different versions of a package with the same version number. So after version 1.x was released for Unity 2018.x, UGUI became a package in 2019.x which required a separate version of the TMP package which became 2.0.1 for Unity 2019.x. Since most of the users were still on 2018.4, updates for the TMP package became 1.1, 1.2, 1.3, etc. whereas the updates for 2019.x became 2.0, 2.1, etc. Then Unity 2020 requiring the introduction of a new package where it was introduced as 3.x. I agree the above can be confusing and I did my best to communicate this information via the release notes, sticky posts and in numerous threads.

    For instance, here are the release notes for the latest releases

     
    Last edited: Jan 18, 2021
  9. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    For testing, I created a new project in 2019.4 where version 2.1.1 of the TMP package is included with the Editor and this version was in fact the version added to the project by default. You can also see that package manager is indicating that version 2.1.3 is available to update to.

    upload_2021-1-17_23-24-54.png

    I am not certain why / how you ended up with version 2.0.1 in your case.

    Having said that, provided you didn't open and re-save any scenes, you should be able to update the package to version 2.1.3 and everything should be fine. If you did open / re-save some scenes or prefabs, you will likely need to go back to a backup of your project and then update TMP to version 2.1.3 before starting to work on stuff.

    Let me know if you run into any issues in regards to the above and I can help you navigate through that and once again sorry about the confusion on this.
     
  10. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I'm not sure what you mean by this. I've been working on this project for several years now; obviously I open and save scenes pretty much every time I work on it. And what backup of my project would you mean? I haven't changed TMP in this project for many months.

    I guess I could try upgrading to 2.1.3, and if it breaks things horribly, just revert. I'll let you know how that goes.
     
  11. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Assuming you were using version 1.5.3 of TMP before migrating to 2019.4, upgrading to version 2.1.3 should be fine as serialized data is of the same layout / format between those releases.

    I would suggest updating to 2.1.3 and let me know if you run into any issues.
     
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK. Updating to 2.1.3 does seem to fix the preferredWidth tab problem.

    As for other issues, it caused some (but not all) of my TextMeshProUGUIs to switch to Top alignment instead of Middle; and oddest of all, I now have to use a character spacing option of -20 em to prevent the letters from being super spread apart, when using the ProFont IIX font shown in my screen shots above. Previously I needed only -4 em to get the spacing shown.

    It's not a huge deal, and I can adjust my text properties. But I thought you might want to know about it.
     
  13. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    This was expected when migrating from a newer version of TMP to an older version and back again to newer release.

    Horizontal and Vertical text alignment used to be serialized in a single property whereas in the newer release they are split into two serialized properties to provide better control over these. When migrating from the older version to newer, a conversion occurs to the new layout which preserve alignment. However, going the other way around doesn't work and results in the issue you outlined when those objects are re-serialized.

    This is the result of a change to correct a long standing issue where spacing was incorrect and inconsistent.

    Spacing options in the Inspector are now in 1/100 em where 1em = 1 pixel * point size. Assuming the point size of the text object is 50 then 1em will be 50 pixels.

    Values in rich text tags are now consistent where <cspacing=50px> will be 50 pixels and again if the point size of the text object is 50 point size then <cspacing=1em> will be 1 pixel * 50 or 50 pixels

    With regards to tab spacing, it is now based on the new Tab Width which comes from the font file * Tab Multiple.

    The spacing for the styles like Normal or Bold are now also in 1/100 em. In the case of bold style, it would increase the spacing by the given amount which would be calculated the same as in the previous examples.

    The conversion from old value to new should be as follows:

    newLineSpacingValue = lineSpacingValue / (fontSize * 0.01f) * fontSize / samplingPointSize;

    fontSize is the font size of the text object.
    samplingPointSize of the font asset.

    Depending on the number of text objects / scenes and prefabs that need to be updated, I did end up creating a custom tool to update those values. Let me know if you need this tool.