Is there auto font size like in Unity

Edit:
@dinotor I’m sorry, after reworking the system a couple times, here is the actual multiline system, respecting word wrap, only actually going smaller once it truly becomes necessary (when the next line wouldn’t be visible anymore)… We get about a max of 8 iterations with mostly 3 iterations with this algorithm, depending on the min max font size values.
For some reason it doesn’t work as well, when using a FontVariation. I think there is no fix to that though… The backend of Godot would have to be adapted.

(Godots Text/Font System needs to be overhauled asap xd. It actually is horrible…)

AutoSizer.gd

class_name AutoSizer

static func get_text_paragraph() -> TextParagraph:
	var line := TextParagraph.new()
	line.justification_flags = TextServer.JUSTIFICATION_NONE
	line.alignment = HORIZONTAL_ALIGNMENT_LEFT
	
	return line

static func update_font_size_by_height(label: AutoSizeRichLabel) -> void:
	var font_size_range := Vector2i(label.min_font_size, label.max_font_size)
	var font := label.get_theme_font("normal_font")
	
	var paragraph := get_text_paragraph()
	paragraph.width = label.size.x
	paragraph.break_flags = TextServer.BREAK_MANDATORY | TextServer.BREAK_WORD_BOUND | TextServer.BREAK_ADAPTIVE
	
	while true:
		paragraph.clear()
		
		var mid_font_size := font_size_range.x + roundi((font_size_range.y - font_size_range.x) * 0.5)
		if !paragraph.add_string(label.text, font, mid_font_size):
			push_warning("Could not create a string!")
			return
		
		var text_height: int = paragraph.get_size().y
		
		if text_height > label.size.y:
			if font_size_range.y == mid_font_size:
				break
			
			font_size_range.y = mid_font_size
		
		if text_height <= label.size.y:
			if font_size_range.x == mid_font_size:
				break
			
			font_size_range.x = mid_font_size
	
	label.add_theme_font_size_override("normal_font_size", font_size_range.x)


AutoSizeRichLabel.gd

@tool
class_name AutoSizeRichLabel extends RichTextLabel

@export var min_font_size := 8 :
	set(v):
		min_font_size = clampi(v, 1, max_font_size)
		update()

@export var max_font_size := 56 :
	set(v):
		max_font_size = clampi(v, min_font_size, 191)
		update()

func _ready() -> void:
	item_rect_changed.connect(update)

func _set(property: StringName, value: Variant) -> bool:
	# Listen for changes to text
	if property == "text":
		text = value
		update()
		return true
	
	return false

func update() -> void:
	return AutoSizer.update_font_size_by_height(self)
1 Like