You could have a table to store the strings and a variable for the max characters per line. EX:
local maxchars = 60 — I’m going with 60 here, adjust according to situation
local mtable = {}
local message = — the chatted string here
local lines = string.len(message) / maxchars
for i = 0, (lines-1) do
table.insert(mtable, string.sub(message, (i * maxchars) + 1, maxchars * (i+1))
end
Basically, we’re getting the number of lines in the message typed. Then we’re adding the strech of string from the start of the line to the next to the table proportionate to the number of lines in the string. Please take note that I made this without testing as I can’t open studio yet, so expect bugs. Nevertheless, this is the framework for your query
Ah, then it gets complicated. What I did is manually count the number of characters the box can hold without jumping to the next line. I’m currently not aware of how to do this dynamically. I’ll experiment around and get back to you soon
Maybe you can split the string by spaces and then use TextService to get the text size and then check if it’s more than the AbsoluteSize of the textbox
I would code all this myself but it’s night time and I should probably go to bed soon
local lines, fontProperties = {}, {
textbox.TextSize,
textbox.Font,
textbox.AbsoluteSize
}
local getTextSize = function(s)
return TextService:GetTextSize(s, unpack(fontProperties))
end
local nth, size, currentText = 0, textbox.TextBounds, ""
for i = 1, size.Y / textbox.TextSize do
print(i, nth)
nth += 1
for i = 1, #textbox.Text:sub(nth) do
local textSize = getTextSize(textbox.Text:sub(nth, nth + i))
if textSize.Y > textbox.TextSize then
local text = textbox.Text:sub(nth, nth + i - 1)
table.insert(lines, {text, textSize})
nth += i - 1
break
end
end
end
table.insert(lines, {textbox.Text:sub(nth), getTextSize(textbox.Text:sub(nth))})
Ok this kind of works but when you add a space to a long piece of text that has not been wrapped yet and then add more after that it will result in this
and Idk how to detect that I tried but it didn’t work
-- parses newlines created by the Enter/Return key into "\n"
local function parse_newlines(str: string): string
return string.gsub(str, "\n", "\\n")
end
-- splits string by "\n"
local function split_newlines(str: string): {string}
return string.split(parse_newlines(str), "\\n")
end
print(split_newlines("Hello, World!\nMy name is:\nMy. Robot"))
print(split_newlines([[Hello, World!
My name is:
Mr. Robot]]))
local lines, fontProperties = {}, {
textbox.TextSize,
textbox.Font,
textbox.AbsoluteSize
}
local getTextSize = function(s)
return TextService:GetTextSize(s, unpack(fontProperties))
end
local nth, size, currentText = 0, textbox.TextBounds, ""
local lineCount = size.Y / textbox.TextSize
local oneLine = (textbox.TextBounds.Y <= textbox.TextSize or lineCount == 1)
for i = 1, lineCount do
nth += 1
for x = #textbox.Text - nth, 1, -1 do
local text = textbox.Text:sub(nth, nth + x)
local textSize = getTextSize(textbox.Text:sub(nth, nth + x))
if textSize.Y <= textbox.TextSize then
print(nth, x, textbox.Text:sub(nth, nth + x))
text = text:gsub("%s+[^%s]*$", function(s)
if not oneLine then
print(s)
lines[i + 1] = {s, getTextSize(s)}
return "" --text:match(`(.*){s}`)
end
end)
print(text)
print(lines[i], i)
if lines[i] then
text = lines[i][1] .. text
textSize = getTextSize(text)
if textSize.Y > textbox.TextSize then
for i = 1, #text do
textSize = getTextSize(text:sub(1, i))
if textSize.Y > textbox.TextSize then
table.insert(lines, {text:sub(i), getTextSize(text:sub(i))})
text = text:sub(1, i)
break
end
end
end
--[[
lines[i] = {text, textSize}
else
lines[i] = {text, textSize}
]]
end
lines[i] = {text, textSize}
nth += x
break
end
end
end
if #lines ~= lineCount then
warn("Number of lines do not match with the actual line count! (something must have gone wrong)")
end
Ok I am almost done
Only bug is that if you put too much spaces in a line it will bug a lot
local TextService = game:GetService("TextService")
return function(textbox : TextBox)
local getPos = function(size, nth)
local yAxis = Vector2.yAxis
local End = Vector2.new(size.X, nth * textbox.TextSize) - yAxis * textbox.TextSize
return {
Start = End * yAxis,
End = End
}
end
local size = textbox.TextBounds
local fullText = textbox.Text
local lineCount = size.Y / textbox.TextSize
local lines, fontProperties = {}, {
textbox.TextSize,
textbox.Font,
textbox.AbsoluteSize
}
local getTextSize = function(s)
return TextService:GetTextSize(s, unpack(fontProperties))
end
local nth, currentText = 1, ""
for i = 1, lineCount do
local text, textSize = fullText, size
--nth += 1
for y = 1, #fullText do
text = fullText:sub(nth, nth + y)
textSize = getTextSize(text)
if textSize.Y > textbox.TextSize then
text = text:sub(1, #text - 1)
textSize = getTextSize(text)
local matched = text:match(".*%s")
if matched then
text = matched
textSize = getTextSize(text)
end
break
end
end
if textSize.Y <= textbox.TextSize then
table.insert(lines, {
Text = text,
Position = getPos(textSize, i)
})
nth += #text -- - 1
end
end
if #lines ~= lineCount then
warn("Number of lines do not match with the actual line count! (something must have gone wrong)")
end
return lines
end
local TextService = game:GetService("TextService")
local getPos = function(textbox : TextBox, X : number, line : number)
local Y = line * textbox.TextSize -- size.Y
local Alignments = {
[Enum.TextXAlignment.Left] = X,
[Enum.TextXAlignment.Right] = -X,
[Enum.TextXAlignment.Center] = (textbox.AbsoluteSize.X / 2) + X / 2,
[Enum.TextYAlignment.Top] = Y - textbox.TextSize,
[Enum.TextYAlignment.Bottom] = textbox.AbsoluteSize.Y - Y, -- -Y
[Enum.TextYAlignment.Center] = (textbox.AbsoluteSize.Y / 2) - Y / 2,
}
local End = Vector2.new(
Alignments[textbox.TextXAlignment],
Alignments[textbox.TextYAlignment]
)
return {
Start = End - (X * Vector2.xAxis),
End = End
}
end
return function(textbox : TextBox)
local size = textbox.TextBounds
local fullText = textbox.Text
local lineCount = size.Y / textbox.TextSize
local fontProperties, lines =
{
textbox.TextSize,
textbox.Font,
textbox.AbsoluteSize
},
{
{
Text = textbox.Text,
Position = getPos(textbox, size.X, 1)
}
}
local getTextSize = function(s)
return TextService:GetTextSize(s, unpack(fontProperties))
end
local nth, currentText = 1, ""
for i = 1, lineCount do
local text, textSize = fullText, size
--nth += 1
for y = 1, #fullText do
text = fullText:sub(nth, nth + y)
textSize = getTextSize(text)
if textSize.Y > textbox.TextSize then
text = text:sub(1, #text - 1)
text = text:match(".*%s") or text
textSize = getTextSize(text)
break
end
end
if textSize.Y <= textbox.TextSize then
lines[i] = {
Text = text,
Position = getPos(textbox, textSize.X, i)
}
nth += #text -- - 1
end
end
if #lines ~= lineCount then
warn("Number of lines do not match with the actual line count! (something must have gone wrong)")
end
return lines
end