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 How to extend TextMeshProUGUI <mark> to have a different shape

Discussion in 'UGUI & TextMesh Pro' started by FernandoHC, Apr 13, 2018.

  1. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    338
    Hello everyone,

    I would like to have a stylized background color for specific areas of the text.

    In order to display a colored background, I was able to find a solution here. And it works fine as this:


    However, I would like to go one step further and customize the shape of the background, in that case the tag <mark>. I would like to add rounded borders to it and a bigger filled space around it.

    Would it be possible to extend how TextMeshPro implements the highlight feature(used as background in this case)?
    If not, is there another way to achieve this, while still being inside TextMeshPro?

    Thanks in advance.
     
    MilenaRocha likes this.
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    There is no quick / trivial way of achieving that right now.

    One potential way would be to use the textInfo.characterInfo[characterIndex] to get the position of the first and last character that you wish to highlight with your special shape and to place / size another object using some 9 sliced texture like UI Image with a sprite behind the text object. This object would be from first character top left + padding to last character bottom right + padding.

    Assuming you are using the Canvas system, you would need to create a new child object to the text for each marked region. These child objects would have an image component with a sliced sprite representing your shape. This should work.

    All the information you need to do this is contained in the textInfo and sub structures.
     
    FernandoHC likes this.
  3. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    338
    Thank you for the helpful response, Stephan.I played with it a bit and was able to get some rects out of it, seems to work fine, but I'm getting the height of each character, based on it's actual size, so I had to do it based on the highest one. I've made a crude code on it for now, would you recommend any improvements on it for the rect precision?

    I did it based on the links I use on my text so I already have some reference for character locations.

    Code (CSharp):
    1.             List<Rect> backgroundRects = new List<Rect>();
    2.             Rect currentRect = new Rect();
    3.             int countLineCharacters = 0;
    4.             int currentLine = text.textInfo.characterInfo[linkInfo.linkTextfirstCharacterIndex].lineNumber;
    5.             for (int i = linkInfo.linkTextfirstCharacterIndex; i <= linkInfo.linkTextfirstCharacterIndex + linkInfo.linkTextLength; i++)
    6.             {
    7.                 if (text.textInfo.characterInfo[i].lineNumber > currentLine)
    8.                 {
    9.                     currentRect.width = text.textInfo.characterInfo[i - 1].bottomRight.x - currentRect.x;
    10.                     currentLine = text.textInfo.characterInfo[i].lineNumber;
    11.                     countLineCharacters = 0;
    12.                     backgroundRects.Add(currentRect);
    13.                     continue;
    14.                 }
    15.                 if (countLineCharacters == 0)
    16.                 {
    17.                     currentRect = new Rect();
    18.                     currentRect.x = text.textInfo.characterInfo[i].topLeft.x;
    19.                     currentRect.y = text.textInfo.characterInfo[i].topLeft.y;
    20.                 }
    21.                 float height = text.textInfo.characterInfo[i].topLeft.y - text.textInfo.characterInfo[i].bottomLeft.y;
    22.                 currentRect.height = height > currentRect.height ? height : currentRect.height;
    23.                 if (i == linkInfo.linkTextfirstCharacterIndex + linkInfo.linkTextLength)
    24.                 {
    25.                     currentRect.width = text.textInfo.characterInfo[i].bottomRight.x - currentRect.x;
    26.                     backgroundRects.Add(currentRect);
    27.  
    28.                 }
    29.                 countLineCharacters++;
    30.             }
    31.             foreach (Rect r in backgroundRects)
    32.             {
    33.                 Debug.Log("Rect: " + r.ToString());
    34.             }
     
    EAWilliams likes this.