Godot: RichTextLabel doesn't set its size from the text bbox; uses 0脳0

Created on 17 Apr 2018  路  32Comments  路  Source: godotengine/godot

The regular Label automatically sizes itself based on its text when placed in a container. So for instance three labels in an HBoxContainer will size themselves appropriately horizontally, and set the height of the container to the max height needed to display all the labels. They act as if their min size is the enclosing bbox of the text.

RichTextLabel doesn't do that; if you put three RichTextLabels in an HBox, all three will be invisible because their min size is 0, so they all end up 0x0. Setting Expand size flag doesn't help. This makes it very hard to use RichTextLabel in a responsive design.

This is somewhat related to other RichTextLabel issues: #8049 and #5633, and #10924.

Godot version:
Godot 3.1-dev: 7b5703bc4

bug confirmed gui

Most helpful comment

Another image to better visualize how not scaling the size with the text looks in practice:

image

Using RichTextLabel on the left and Label with autowrap on the right, identical container settings. When I type more text on the right, the label and the parent containers resize to fit the text. RichTextLabel doesn't do it.

This makes it hard to use RichTextLabel for dynamic text where a user doesn't know upfront how long the text will be.

All 32 comments

394e6d5 can't reproduce. Example project is appreciated.

Here's a test project.
richtextlabel-test.zip

It has three labels in an HBoxContainer. The first and last are regular labels; they are visible. The middle one is a RichTextLabel; you can't see it because its size is 0x0.
To create this, I just created the components in order, didn't change any settings other than the label text. And yes the RichTextLabel does have a text string, so if it behaved the same way as Label, it would have a nonzero size in the HBoxContainer.
image

@Noshyaar can you repro the issue with this project?

f20af4b

What I'm able to reproduce: text inside RTL doesn't set its min size.

The way normal Label works is that, when it's not set to autowrap, it sets its min size by the text boundary. So, it'll push the parent container outward and you can't shrink it more. If you turn on autowrap it'll act the same as an RTL.

What I can't: "Setting Expand size flag doesn't help"

Setting Horizontal Expand flag does help for me. It will NOT push the parent container outward. You have to set the parent container size properly. In the project, if you set expand flag and enlarge the parent, it appears.

Well, of course adding Horizontal Expand _and_ enlarging the parent make it work -- but if the text is dynamic I have no idea how much to expand the parent. The general idea of responsive design is the container should adapt to its content.
If RTL gets a fix to set its min size based on its content, then that's a good start.
However, note that in my test project, if you do set the min size of the HBoxContainer large enough, the RTL does show up but its vertical alignment is weird:
image
Perhaps that's related to #5633.

Because of this issue, I'm unable to use RichTextLabel for dynamic text.
Is there a workaround I can grow the RichTextLabel according to the size of the text?
This question is unanswered.
https://godotengine.org/qa/30459/label-or-richtextlabel-auto-width

Another image to better visualize how not scaling the size with the text looks in practice:

image

Using RichTextLabel on the left and Label with autowrap on the right, identical container settings. When I type more text on the right, the label and the parent containers resize to fit the text. RichTextLabel doesn't do it.

This makes it hard to use RichTextLabel for dynamic text where a user doesn't know upfront how long the text will be.

I dug a big into this since I need a way to resize my RichTextLabels according to the size of the text.
I noticed if I set the fixed_width(not currently exposed in gdscript or editor) to something other than -1, the RTL's size in Y get's properly updated like @pawilon 's example(on the right).
I'm guessing get_minimum_size() returning get_content_height() being why it works.
Not quite sure why fixed_width even exists. Shouldn't it use min_size instead?

Made a fix on our end. Not 100% happy with it. I think it should involve removing fixed_width which appears to be a hack. The scrollbars being the behavior I'm not sure how to work around in an elegant way. I understand we might not want the text to grow the control's size automatically if we do want scrollbars.
For now, you can view our changelist. Borrows from fixed_width but will use the minimum_size instead.
https://github.com/jfmajor/godot/commit/eed621588351c0caed157b198ae4849aea54367f

Wouldn't fixed width exist exactly for the reason that you don't, under any circumstances, want to resize anything?

RichTextLabel does try a bit[1] to resize itself when setting a size smaller than its content width, so I'd suppose having a fixed width would alter this behavior.

I look forward to trying your patch as soon as possible, these kinds of problems are the worst when trying to use Godot :)

[1] Doesn't work at least on Mac and 3.0.6, I'll probably open an issue next year, if I first try some different fonts and whatnot.

@mjtorn the patch adds a Auto Resize To Text option you need to check. Did you set it?

@jfmajor I haven't had time yet... I have a lot of accounting and reporting to do between xmas and new year, so it might be until early January.

But setting the width of something, eg. like we do with tooltips in Escoria since godotengine/escoria@09d710182c90bd8a56d54fd1e7f063acf36b381b, mostly works. I wish I had tested more on Mac before writing that commit message ;)

Beside that it's that we don't have VAlign. Content margins with an auto-growing RTL (which your commit seems to address) might be a better solution than simply aligning vertically. Let's see.

This might be going off-topic, but I'd attach this work-in-progress screenshot of our game with the German localization in any issue I'd create.

iscw-demo-kugelschreiber-hans

hope this can make it in soon. this would help so much for creating dynamic tooltips that fit their bbcode size appropriately. you can do a trick where you have a rogue label and set its modulate.a=0, then set the RTL to the label's rect_size. however, that works great for short bbcode. problem is, if you do [color=red]mytext[/color] and other bbcode tags, the label's rect will be very long, and then the RTL's width will become very long as well. actually.. you could go even further and just strip the bbcode tags in the label's text via regex, and you would get a more accurate size

or, the other partial solution is to just set a fixed width, and use the height from the rogue label. but then, you have to use a fixed width. if there were a setting so it works just like a label, that would be ideal imo

@jfmajor i'm going to compile and use your code. i'll re-edit this when i'm back
edit: @jfmajor i found an issue. when it resizes, it increases the height by too much, example gif. it also doesn't expand the width based on the letters like a label would. am not sure

@jfmajor sorry that I haven't had the opportunity to try your code yet, I'm stuck doing billable work and such for a while now :( But is it good enough to become a PR into Godot? If it works, I'd use it anyway, but now I need to look after other things first.

This is biting me too :-( I will look at source after I get my game out the door and money (if any :-p ) coming in.

@jupiterjosh would love this feature =]

basically, to reduce this issue/request into a one liner:

  • Add an option to RichtTextLabel to set the size based on the text/content (like how label works)

@girng please don't paraphrase someone else. If you want to quote someone or respond to someone then great, but speaking for someone isn't appropriate.

@jupiterjosh i'm speaking for someone? who?

My 5c:
I'm using get_minimum_size() method on Labels to detemine their real size right after I programmatically set the string. It's the only way to rearrange controls in the same block without waiting for next frames etc.

This doesn't work for RichTextLabel, I think the reason is the same - the lack of proper size computation.

Any updates on the issue?

Hi there! Any news?

Hello, waiting for proper size computation too

Possible workaround:

size_flags_horizontal = SIZE_EXPAND_FILL
scroll_following = true
yield(get_tree(), "idle_frame")
rect_min_size.y = get_v_scroll().value

Possible workaround:

size_flags_horizontal = SIZE_EXPAND_FILL
scroll_following = true
yield(get_tree(), "idle_frame")
rect_min_size.y = get_v_scroll().value

It doesn't work for me (it sets some arbitrary large values far more than the actual height).

Using Godot 3.1.1.stable.official this is a tolerable hack for vertically resizing a RichTextLabel and its parent (which is a PanelContainer in my case).

onready var container:PanelContainer = $PanelContainer
onready var label:RichTextLabel = $PanelContainer/RichTextLabel
onready var panel:Panel = container.get("custom_styles/panel") # for calculating the proper y padding
var recalc_height_required := false

func _ready() -> void:
    label.size_flags_vertical = Control.SIZE_EXPAND_FILL
    label.scroll_active = false # to prevent the scrollbar from briefly appearing (due to the idle_frame yield)
    label.scroll_following = false # to avoid a long content to jump as it's waiting for the label height being adjusted

func _process(_delta:float) -> void:
    if recalc_height_required:
        recalc_height_required  = false
        _recalc_height()

func _update_label(markup:String) -> void:
    label.bbcode_text = markup
    yield(get_tree(), "idle_frame")
    _recalc_height()
    recalc_height_required = true

func _recalc_height() -> void:
    label.rect_size.y = label.get_v_scroll().get_max()
    container.rect_size.y = label.rect_size.y
    container.rect_size.y += panel.content_margin_top
    container.rect_size.y += panel.content_margin_bottom

Using Godot 3.1.1.stable.official this is a tolerable hack for vertically resizing a RichTextLabel and its parent (which is a PanelContainer in my case).

onready var container:PanelContainer = $PanelContainer
onready var label:RichTextLabel = $PanelContainer/RichTextLabel
onready var panel:Panel = container.get("custom_styles/panel") # for calculating the proper y padding
var recalc_height_required := false

func _ready() -> void:
    label.size_flags_vertical = Control.SIZE_EXPAND_FILL
    label.scroll_active = false # to prevent the scrollbar from briefly appearing (due to the idle_frame yield)
    label.scroll_following = false # to avoid a long content to jump as it's waiting for the label height being adjusted

func _process(_delta:float) -> void:
    if recalc_height_required:
        recalc_height_required  = false
        _recalc_height()

func _update_label(markup:String) -> void:
    label.bbcode_text = markup
    yield(get_tree(), "idle_frame")
    _recalc_height()
    recalc_height_required = true

func _recalc_height() -> void:
    label.rect_size.y = label.get_v_scroll().get_max()
    container.rect_size.y = label.rect_size.y
    container.rect_size.y += panel.content_margin_top
    container.rect_size.y += panel.content_margin_bottom

This doesn't work as well.

It'd be nice if this would be fixed soon. As it stands RichTextLabel is practically useless due to the fact that it doesn't size itself along the y axis. The only way to get it to show is to expand vertically, but that is undesirable due to the fact that it leads to excess space.

Just adding my "me too". At the moment, the only solution I have found is to avoid using RichTextLabel altogether. Which is a sad solution.

Had me scratching my head for a while, was projecting RichTexts onto a canvas in 3D, couldn't figure out why the RichText wouldn't show but normal labels would. Found this, setting a manual minsize fixed, will just have to play around with numbers for each piece of text I suppose. Hope to see this fixed.

Having the same problem when trying to get the RichTextLabel dimensions for a dynamic text in order to align the text in the center of a text bubble.

Having a quick look at the implementation it seems that RichTextLabel is not very aware if it's minimum required width and you can only get the content height (with get_content_height function).

Still very much a problem.

I posted my solution, written in C#, here (waiting for approval):
https://godotengine.org/qa/30459/label-or-richtextlabel-auto-width

Well, it's taking it's sweet time so here's a gist with the same code:
https://gist.github.com/c3a858e2fabe87f3ead967dd15a25d98

You're welcome.

This issue is now worked around by the new fit_content_height option in RichTextLabel (in 3.2.2 and 4.0).

But a different fix will likely end up being implemented for a more though "width-for-height" adjustment system for containers as seen e.g. in GTK.

Was this page helpful?
0 / 5 - 0 ratings