Search Unity

Indent word-wrapped lines

Discussion in 'UGUI & TextMesh Pro' started by Yerkisk, Mar 15, 2020.

  1. Yerkisk

    Yerkisk

    Joined:
    Jul 28, 2015
    Posts:
    38
    I've been looking all over for an easy way to indent word-wrapped lines for my TextMeshProUGUI, but no luck. I've built a multiplayer chat framework for our online mobile game, and all I'm trying to do is have the 2nd and + lines be indented by a certain amount (not the first line).

    For example :
    Code (CSharp):
    1. Myself : This is a long line of text with wrapping that
    2. fails to do what I want it to do
    Should be :
    Code (CSharp):
    1. Myself : This is a long line of text with wrapping that
    2.          fails to do what I want it to do
    I don't mind If the second line fits with the start of the first line of text or not, but I do want to have some kind of indentation so that it's easy to see who sent the message.

    Any idea on how to do that? the Indent tag indents all line including the first one, and line-indent doesn't work with word-wrapping.

    Thanks
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    The <indent> tag should achieve the desired result. Here is an example using the following text.

    "Myself : <indent=20%>This is a long line of text with wrapping that fails to do what I want it to do."

    upload_2020-3-15_0-38-50.png

    The <indent> tag value can be specified in pixel <indent=100>, in font units <indent=2em> or as percentage of width of the text container <indent=25%>.

    Please note that your original text appears to contain a few hidden carriage returns <CR> which would certainly mess up the indentation.

    Also see example 10 - Bullets & Numbered List Example included in the TMP Examples & Extras.
     
  3. Yerkisk

    Yerkisk

    Joined:
    Jul 28, 2015
    Posts:
    38
    @Stephan_B Yeah sorry, that doesn't work. I forgot to mention that the first line indentation must be of dynamic size due to the name of the person being of different length. As for the <CR>, don't mind them, I just typed the text as an example, it wasn't coming from our game.

    Using the options you proposed, the first line indent has to always be the same percentage or size, which isn't the case in a multiplayer chat where the name of the person isn't a fixed size.

    Thanks,
     
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    Ok... I think it would be possible to add another option to the <indent> tag where the indent value would be based on the current advance value of where the tag is placed. To be more specific, the space just after ":" would represent the indent value.

    The question now is to come up with a format for specifying this option. We already have <indent=value> with suffix of "px" for pixel units, "em" for font units "em" and "%" for percentage "%". There doesn't appear to be an established unit to denote current position.

    So how to we represent this new mode <indent=5px position=absolute> <indent=5px position=relative> ?

    Thoughts / Suggestions?
     
    Yerkisk likes this.
  5. Yerkisk

    Yerkisk

    Joined:
    Jul 28, 2015
    Posts:
    38
    I remember reading in another post a suggestion that you had to specify a "from" that would specify the first line where the indent would start, ie from=2 would start the indent only at the second line. If you can make that work for word-wrapped lines that would be actually perfect and probably easier to understand than trying to set a position. And in that case, it might make more sense to have that as an option of the line-indent than the indent tag (but again you'd have to make line-indent work with word-wrapped lines).

    As for the position option, you would have to set the <indent> in the middle of the text for it to be relative to a specific position, would you not? Otherwise how would you say after which character would the indent start considering that the start of the string could be of a random length. I don't think that giving a number of characters from the start of the string as the starting indent position is a good idea, even less trying to calculate the size of the characters to give the position in % or pixels.

    If we have to insert the <indent> tag inside the text, for example after the "Myself : " in my example above, that should give the position of the start of the indent. In that case instead of a position option I'd go with a bool, something like <indent=5px alignwrap=true>.
     
    Psyker likes this.
  6. Yerkisk

    Yerkisk

    Joined:
    Jul 28, 2015
    Posts:
    38
    On a side note, but related to the same issue, initially I wanted to use two TextMeshProUGUI, one for the username, and one for the message (to allow clicking on the username to receive user details etc). But for some reasons I was unable to make that work.

    I have a scrollview, and it's content is set with a Content Size Fitter set to preferred size for vertical fit (unconstrained for horizontal). The content also has a vertical Layout group.

    I instantiate a 'chat message' prefab parented to the scrollview's content. That prefab has a horizontal layout group, and has 2 TextMeshProUGUI as childs.

    textmeshprefab.png

    textmeshhorizontal.png

    No matter what settings I set on the horizontal layout group of the prefab, I'm unable to have the two child TextMesh object behave correctly. Ideally, the first one containing the username would have a content size fitter that would fit the width of the username, and the second child would fill the remaining space of the parent. First one is also set to not wrap, while the second one should be set to wrap (second one also has a content size fitter to fit the height of the text).

    textmeshnormal.png

    Set this way, it almost work, until the second text starts wrapping, in which case it'll start to slowly shrink the first text instead of staying in place and wrapping and extending downward.

    textmeshextend1.png

    The more text you add, the more it starts moving left.

    textmeshextend2.png
    Considering that the first text (username) is of dynamic length, is there a way to have the second text not overlap it and only extend downward during wrap?

    Thanks

    ps : That is related to the first issue, but really I think this would look worst as each messages from different users would actually start a different positions based on the length of their username. The initial issue of this thread and the indent method would make it much more viable for different scenarios.
     
  7. BCook99

    BCook99

    Joined:
    Feb 17, 2015
    Posts:
    16
    Note that using line-indent with a negative value achieves the desired effect of making the 2nd and subsequent lines appear indented. You just have to adjust the position of the overall text since this makes it moves left.
    E.g. <line-indent=-5%>This is a long line of test text test text test text test text test text test text test text.