# https://gist.github.com/MattUV/469ad2be96961c0afe8dfc1bf0932f76 class_name ExpandableTextEdit extends TextEdit export(bool) var expand := true export(int) var max_lines := 5 var scroll_bar onready var font = get_font("font") var line_spacing var line_height var line_count = -1 func _ready(): scroll_bar = _get_vscroll_bar() line_spacing = _get_line_spacing() line_height = font.get_height() + line_spacing line_count = _get_real_line_count() _update_height(line_count) connect("text_changed", self, "_on_text_changed") func _get_line_spacing(): var spacing = 4 if get_constant("linespacing") != null: spacing = get_constant("line_spacing") return spacing func _get_real_line_count(): var count = get_line_count() var lines_to_add = 0 var scroll_size = scroll_bar.rect_size.x if scroll_bar.visible else 0 # Loop over every actual line in the TextEdit for i in count: var line = get_line(i) # Get the string of the line var width = font.get_string_size(line).x if width > rect_size.x - scroll_size: lines_to_add += int(width / (rect_size.x - scroll_size)) return count + lines_to_add func _get_vscroll_bar(): for c in get_children(): if c is VScrollBar: return c func _update_height(count): if !expand: return var lines_to_show = count if lines_to_show > max_lines: lines_to_show = max_lines rect_min_size.y = lines_to_show * (line_height + line_spacing * 1.45) rect_size.y = rect_min_size.y update() func _on_text_changed(force := false): var new_line_count = _get_real_line_count() if force or line_count != new_line_count: line_count = new_line_count _update_height(new_line_count)