GUI text node size after set_text

Hello!
I can’t understand how text node size property works.
For example, I have a text node"text" with size (10, 10, 0) and “Line Break” is on. I run the following code:

local text_label = gui.get_node("text")
print("Before: ", gui.get_size(text_label))
gui.set_text(text_label, "Very long message that definitely will be wrapped")
print("After: ", gui.get_size(text_label))

which returns me:

DEBUG:SCRIPT: Before: 	vmath.vector3(10, 10, 0)
DEBUG:SCRIPT: After: 	vmath.vector3(10, 10, 0)

But my goal is to get the new real size of the wrapped text to resize its parent components. How can I do this?

1 Like

@nikolay.romashchenko In order to do so, you need to know how many pixels your string will take up. I achieved this by trial and error. Make a text node with a few words, and fit a box node behind it until you get it to the visible size of the string. Now you divide that amount by the number of characters in the string, including spaces. This will give you the size, in pixels, of each character in that font. You can then multiply this number by the number of characters in your string to see how large any node is in the future. NOTE: this doesn’t include linebreak. You can use the custom linebreak function below if you need to do so.

Once you have the character size in pixels, you can use this function for linebreaking:

local linebreak = ""

function fit_text(text,chars,width,margin) -- In order: Inputted string, Size of one font character in pixels, Width of node, Desired padding space on edges of node.
	numChars = string.len(text)
	chatSpace = numChars * chars
	width = width - margin
	lineSpace = math.ceil(width/chars)
	mock_lineSpace = lineSpace*chars
	lines = 1
	for l=0,50,1 do
		if chatSpace > mock_lineSpace then
			lines = lines + 1
			mock_lineSpace = mock_lineSpace + lineSpace*chars
			print("GETTING LINES")
		end
	end
	print("GOT LINES: " .. lines)
	for b=0,lines,1 do
		if lines ~= 1 then
			print("lines: " .. lines)
			print("takeaway table: " .. b .. " | characters/line: " .. lineSpace)
			takeaway = b * lineSpace
			print("taking away: " .. takeaway .. " characters")
			print("string length: " .. string.len(text))
			thisLine = text
			if takeaway ~= 0 then
				takeaway = takeaway + 2
				thisLine = string.reverse(thisLine)
				thisLine = string.sub(thisLine,1,-takeaway)
				thisLine = string.reverse(thisLine)
				if b ~= 0 then
					takeaway = b + 1
					takeaway = takeaway * lineSpace
					takeaway = string.len(text) - takeaway
					thisLine = string.sub(thisLine,1,-takeaway)
				end
				print("remaining characters: " .. string.len(thisLine))
			else
				takeaway = numChars - lineSpace
				thisLine = string.sub(thisLine,1,-takeaway)
			end
			if b ~= lines - 1 then  -- If end has not been reached
				linebreak = linebreak .. thisLine .. "\n"
			else
				linebreak = linebreak .. thisLine
			end
		else
			linebreak = text
		end
	end
	nextOffset = lines * (chars/3 + chars) + offset
	return linebreak
end

Hi @nikolay.romashchenko!

The size of the text box tells the engine how to wrap the text. This property doesn’t change when you set text.

To calculate the size of your desired text you should use gui.get_text_metrics() (or gui.get_text_metrics_from_node() if you already have the text set)

9 Likes

Is this method deprecated? (given how old this topic is, it’s possible) I can’t find in [documentation] this(API reference (gui)) this. How to get actual size of gui text after text updating?

[UPDATE]
found the solution, now that’s possible to do via:

local metrics = resource.get_text_metrics(gui.get_font_resource(gui.get_font(node)), tostring(text))
print(metrics.width)
3 Likes