Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RichTextLabel doesn't set its size from the text bbox; uses 0×0 #18260

Closed
Tracked by #39144
garyo opened this issue Apr 17, 2018 · 46 comments · Fixed by #71330
Closed
Tracked by #39144

RichTextLabel doesn't set its size from the text bbox; uses 0×0 #18260

garyo opened this issue Apr 17, 2018 · 46 comments · Fixed by #71330
Assignees
Milestone

Comments

@garyo
Copy link
Contributor

garyo commented Apr 17, 2018

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: 7b5703b

@ghost ghost added the topic:core label Apr 26, 2018
@ghost
Copy link

ghost commented Apr 26, 2018

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

@garyo
Copy link
Contributor Author

garyo commented May 3, 2018

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

@garyo
Copy link
Contributor Author

garyo commented May 10, 2018

@Noshyaar can you repro the issue with this project?

@ghost
Copy link

ghost commented May 10, 2018

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.

@ghost ghost added the enhancement label May 10, 2018
@garyo
Copy link
Contributor Author

garyo commented May 10, 2018

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.

@harrypujols
Copy link

harrypujols commented Oct 29, 2018

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

@pawilon
Copy link

pawilon commented Nov 15, 2018

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.

@akien-mga akien-mga added bug and removed enhancement labels Nov 15, 2018
@jfmajor
Copy link

jfmajor commented Dec 20, 2018

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?

@jfmajor
Copy link

jfmajor commented Dec 20, 2018

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.
jfmajor@eed6215

@mjtorn
Copy link
Contributor

mjtorn commented Dec 22, 2018

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.

@jfmajor
Copy link

jfmajor commented Dec 22, 2018

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

@mjtorn
Copy link
Contributor

mjtorn commented Dec 23, 2018

@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 godot-escoria/escoria-demo-game@09d7101, 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

@girng
Copy link

girng commented Dec 31, 2018

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

@mjtorn
Copy link
Contributor

mjtorn commented Jan 14, 2019

@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.

@jupiterjosh
Copy link

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.

@girng
Copy link

girng commented Jan 26, 2019

@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)

@jupiterjosh
Copy link

@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.

@girng
Copy link

girng commented Jan 28, 2019

@jupiterjosh i'm speaking for someone? who?

@hedin-hiervard
Copy link
Contributor

hedin-hiervard commented Jan 30, 2019

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.

@hedin-hiervard
Copy link
Contributor

Any updates on the issue?

@smark91
Copy link

smark91 commented Apr 27, 2019

Hi there! Any news?

@RaaliOloth8
Copy link

Hello, waiting for proper size computation too

@yvesns
Copy link

yvesns commented May 22, 2019

Possible workaround:

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

@Pilvinen
Copy link

Pilvinen commented Jun 13, 2020

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.

@akien-mga akien-mga added this to the 4.0 milestone Jun 19, 2020
@akien-mga
Copy link
Member

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.

akien-mga added a commit to akien-mga/godot-debug-watermark that referenced this issue Nov 2, 2020
This requires working around two engine bugs:

- RichTextLabel doesn't properly set its minimum size:
  godotengine/godot#18260

- Custom tooltip placement fails if the custom tooltip is not visible
  beforehand:
  godotengine/godot#39677
  (This should be fixed in 3.2.4, but the workaround doesn't hurt.)
akien-mga added a commit to akien-mga/godot-debug-watermark that referenced this issue Nov 2, 2020
This requires working around two engine issues:

- RichTextLabel doesn't properly set its minimum size:
  godotengine/godot#18260

- Custom tooltip placement fails if the custom tooltip is not visible
  beforehand. It's not a bug per se, but documentation will need to be
  made clearer about this requirement:
  godotengine/godot#39677
@lucassardois
Copy link

This issue is still revelent in Godot 3.2.3 Stable.
With the following setup:

HBoxContainer
-- Label
-- RichTextLabel
-- Label

The RichTextLabel have a min size of 0x0 even when there is text inside. The option fit_content_height doesn't solve the width problem. Also, setting the horizontal or vertical size_flag does nothing.

@true2thepen
Copy link

true2thepen commented Jan 8, 2021

My solution:

Place the following on the RichTextLabel's parent.

extends [Parent Type]

func _ready():
	self.connect("resized", self, "_on_resize")

func _on_resize():
	var myChild = self.get_child(0) # Change this to find correct child if RichTextLabel isn't the only child
	myChild.set_size((self.rect_size)) # Change to fit if RichTextLabel isn't only child.

Works best if RichTextLabel is only child. Has jitter during resize; but,.... at least the text no longer runs outside.
This is by no means perfect but works with Godot 3.2.3 Stable.

@db0
Copy link

db0 commented Jul 10, 2021

I extended the RichTextLabel with this code to make this work more seamlessly.

func get_min_height() -> float:
    var theme : Theme = self.theme
    var label_font : Font
    if theme:
        label_font = theme.get_font("font", "RichTextLabel").duplicate()
    else:
        label_font = get("custom_fonts/normal_font").duplicate()
    return(label_font.get_height())

Then I extended set_bbcode():

func set_bbcode(value):
	.set_bbcode(value)
	rect_min_size.y = get_min_height()

@db0
Copy link

db0 commented Jul 10, 2021

Edit, d'oh, I just found out fit_content_height exists defaulted to false. Setting this to true makes this work without hacks o.O

@EpeonGamer
Copy link

Do we have a stuatus on anything for width?

@nathanfranke
Copy link
Contributor

nathanfranke commented Oct 16, 2021

You can get creative with Font.get_string_size and Font.get_wordwrap_string_size.

If you have a single line of text always, you can just use get_string_size by itself. If you want to have multiple lines with automatic width adjustment, you can use this code:

extends RichTextLabel

# TODO: Only run this code when the text is modified
func _process(_delta: float) -> void:
	rect_size = get_font("normal_font").get_wordwrap_string_size(text, INF)
	rect_size.x = 0.0
	for line in text.split("\n"):
		rect_size.x = max(rect_size.x, get_font("normal_font").get_string_size(line).x)

Note that this doesn't work with multiple sized fonts (e.g. bigger bold text).

example

@Calinou
Copy link
Member

Calinou commented Oct 16, 2021

Note that this doesn't work with multiple sized fonts (e.g. bigger bold text).

If you absolutely need this, you can use an uniwidth (≠ fixed-width) font such as Recursive to work around this.

@KoBeWi
Copy link
Member

KoBeWi commented Jan 12, 2022

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.

This isn't really needed. We need 2 things: option for RichTextLabel to expand to its maximum size in a direction (horizontally or vertically) and a maximum size setting. If you want a RTL to just take full width, set the expand to horizontal and leave maximum size at (0, 0), which would disable it. If you want to fit it in a somewhat fixed message box, set maximum size to the desired value, so that RTL will expand to that size and then wrap the text. The minimum size in the other axis would be easy to calculate.

@lpares12
Copy link
Contributor

lpares12 commented Dec 7, 2022

Is this gonna be implemented for Godot 4?

@KoBeWi do you have any work around for when the container should take the size of the RTL, even if it's smaller than the size set in the container? For example in the image posted by @pawilon:

48555446-8ca96f00-e8e1-11e8-8ca5-c58014eab91c

What if the text in the container was only "hello", then the container would take the manually set width, instead of fitting the word "hello"

@Calinou
Copy link
Member

Calinou commented Dec 7, 2022

Is this gonna be implemented for Godot 4?

Only if a motivated contributor steps up to do the required work 🙂

I don't know if @bruvzg has looked into this in the past, but it's not an easy problem to resolve. Handling fonts with different sizes in particular makes this more challenging.

@KoBeWi
Copy link
Member

KoBeWi commented Dec 8, 2022

do you have any work around for when the container should take the size of the RTL, even if it's smaller than the size set in the container? For example in the image posted by

I don't understand that image. The container does correctly resize to RIchTextLabel. I just tried the same setup and I don't have this problem. It might be some issue that was fixed since then.

@lpares12
Copy link
Contributor

lpares12 commented Dec 8, 2022

The issue is that RTL resizes according to the height, when the fit content height is set. But there's nothing equivalent for the width, meaning the max width is always set by the parent width, if that makes sense. With normal labels it is possible to write text and the parent container will expand horizontally according to it.

@abelbascu
Copy link

abelbascu commented Jul 23, 2024

I'm working on a visual novel and after much search I found this thread. I have a RichtextLabel inside a TextureButton. This combo is a player dialogue choice. There can be multiple dialogue choices inside a containerUI (like in Monkey Island games). The texts overlap, specially when the text autowraps to a second text line... it's like that after the autowrap, there is not any autoresize occurring on the parent node (TextureButton), so I guess I will need to check the height size of the RichTextLabel and notify that to the TextureButton to change its height on a method, so the containerUI that has all the player choices can automatically grow upwards to prevent the texts overlapping... Is there any easier solution? is there any advancement on this issue? Thanks in advance.

@KoBeWi
Copy link
Member

KoBeWi commented Jul 23, 2024

You could put TextureButton as a child of RichTextLabel, set anchors to Full Rect and enable draw_behind_parent. It should look more or less the same, but size automatically.

Or I guess you could put both in a MarginContainer as siblings. The container will fit to the biggest child.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.