I have a Label node “DisplayWord” that shows the word the user typed. Therefore it could be anything from ‘Cat’ to ‘Asphyxiation’.
I want DisplayWord to scale dynamically and occupy the entire canvas to fit whatever word is typed without clipping.
I placed DisplayWord in a PanelContainer node and scale the container dynamically. This does work as expected functionally, but the font looks ugly after scaling to a different size. There seem to be a lot of interpolation artifacts.
I want this to look crisp after scaling, much like “Nearest” interpolation for texture images.
extends Container
func _ready() -> void:
# Whenever pre_sort_children is emitted
pre_sort_children.connect(func():
for child in get_children():
# Find all the Label chidren
if not child is Label:
continue
child = child as Label
# Get the font from the theme
var font = child.get_theme_font("font")
# And start from the size of the container as its font_size
var font_size = floor(size.y)
# Keep the final text size here
var text_size = Vector2.ZERO
# In an infinite loop
while true:
# Get the size of the string from the font
text_size = font.get_string_size(child.text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size)
if text_size.x > size.x:
# And if it's bigger, lower the font size and try again
font_size -= 5
else:
# If not, then exit the loop
break
# Change their font_size
child.add_theme_font_size_override("font_size", font_size)
# And fit them into the container
fit_child_in_rect(child, Rect2(Vector2.ZERO, size))
)
Thank you!
This worked well for the default font and is great for prototyping.
However since I want to use a themed font in production, I would like to test out @mrcdk ‘s solution.
I couldn’t quite get this working. I tried anchoring the Label in the container in different ways too.
Could you please share your scene tree and any layout settings you may have changed to get this running?
[gd_scene load_steps=3 format=3 uid="uid://6m2sxb85ivd3"]
[sub_resource type="GDScript" id="GDScript_gtqu1"]
script/source = "extends VBoxContainer
@onready var line_edit: LineEdit = $LineEdit
@onready var label: Label = $Container/Label
func _ready() -> void:
line_edit.text_changed.connect(func(new_text: String):
label.text = new_text
)
"
[sub_resource type="GDScript" id="GDScript_6s3pd"]
script/source = "extends Container
func _ready() -> void:
# Whenever pre_sort_children is emitted
pre_sort_children.connect(func():
for child in get_children():
# Find all the Label chidren
if not child is Label:
continue
child = child as Label
# Get the font from the theme
var font = child.get_theme_font(\"font\")
# And start from the size of the container as its font_size
var font_size = floor(size.y)
# Keep the final text size here
var text_size = Vector2.ZERO
# In an infinite loop
while true:
# Get the size of the string from the font
text_size = font.get_string_size(child.text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size)
if text_size.x > size.x:
# And if it's bigger, lower the font size and try again
font_size -= 5
else:
# If not, then exit the loop
break
# Change their font_size
child.add_theme_font_size_override(\"font_size\", font_size)
# And fit them into the container
fit_child_in_rect(child, Rect2(Vector2.ZERO, size))
)
"
[node name="ResizeLabelExample" type="VBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 16
script = SubResource("GDScript_gtqu1")
[node name="Container" type="Container" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
script = SubResource("GDScript_6s3pd")
[node name="Label" type="Label" parent="Container"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 6
theme_override_font_sizes/font_size = 16
horizontal_alignment = 1
vertical_alignment = 1
[node name="LineEdit" type="LineEdit" parent="."]
layout_mode = 2