How to wrap texts with a script

Alright well I haven’t completely finished it but heres a working prototype, I can’t quite fix the issues yet, but I will be able too try and fix them in a few minutes, in the meantime if you want to try here you go

LocalScript inside the TextBox:

local maxLength = 20 -- Max Letters Per Line

local scriptChanged = false

script.Parent:GetPropertyChangedSignal("ContentText"):Connect(function()
	local text = script.Parent.ContentText
	if text:len() > maxLength and not scriptChanged then
		local firstLine = text:sub(1, maxLength)
		local nextLine = text:sub(maxLength, -1)
		scriptChanged = true
		script.Parent.Text = string.format(firstLine.."\n"..nextLine, "%q")
	else
		wait(2)
		scriptChanged = false
	end
end)

is there anyway to do it with the TextFits property? so it adds a new line everytime it reaches the end of the textbox and not with a max length

TextFits would probably work for the first beeline but every line after that it probably wouldn’t work for

Click to view my original purposed workaround. (This workaround is very buggy and only works with typing at the end of textboxes.) Here's a slightly revised version of what I created in your other topic. Just like the other one, it doesn't work with fast typing text or editing anything in the middle of the text. It only really works if the user types at the end.

The problem is you can’t measure text. You can’t determine the size of the text because different characters are different pixel sizes. If it was possible to measure text pixels, it would be easy to come up with a workaround but I’m stumped.

This is the best I could come up with. I don’t think I can be of any help past this point. If someone could improve/adapt this, that would be really cool.

local function UpdateSize(FrameInstance,LayoutInstance)
	if FrameInstance and LayoutInstance then
		local PaddingX = 0
		local PaddingY = 0
		if FrameInstance:FindFirstChildOfClass("UIPadding") then
			local UIPadding = FrameInstance:FindFirstChildOfClass("UIPadding")
			PaddingX += UIPadding.PaddingLeft.Offset
			PaddingX += UIPadding.PaddingRight.Offset
			PaddingY += UIPadding.PaddingBottom.Offset
			PaddingY += UIPadding.PaddingTop.Offset
		end
		if FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.Y then
			FrameInstance.CanvasSize = UDim2.new(0,0,0,LayoutInstance.AbsoluteContentSize.Y + PaddingY)
		elseif FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.X then
			FrameInstance.CanvasSize = UDim2.new(0,LayoutInstance.AbsoluteContentSize.X + PaddingX,0,0)
		elseif FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.XY then
			FrameInstance.CanvasSize = UDim2.new(0,LayoutInstance.AbsoluteContentSize.X + PaddingX,0,LayoutInstance.AbsoluteContentSize.Y + PaddingY)
		end
	end
end


local v = script.Parent
local Layout = v:FindFirstChildOfClass("UIListLayout") or v:FindFirstChildOfClass("UIGridLayout")
local TextBox = script.Parent.TextBox
TextBox:GetPropertyChangedSignal("AbsoluteSize"):connect(function() UpdateSize(v,Layout) end)
local LastCursorPosition = -1

TextBox:GetPropertyChangedSignal("CursorPosition"):Connect(function()
	if TextBox.CursorPosition >= 0 and TextBox.TextEditable == true and TextBox.TextFits == true then
		LastCursorPosition = TextBox.CursorPosition
	end
end)

TextBox:GetPropertyChangedSignal("Text"):connect(function()
	v.CanvasPosition = Vector2.new(0,TextBox.AbsoluteSize.Y + v.AbsoluteWindowSize.Y)
end)

TextBox:GetPropertyChangedSignal("TextFits"):Connect(function()
	local LP = game.Players.LocalPlayer
	if TextBox.TextFits == false then
		local TextAdjustment = 1
		TextBox.TextEditable = false
		TextBox.Selectable = false
		TextBox:ReleaseFocus()
		local OldText = TextBox.Text
		local ReversedText = string.reverse(OldText)
		if string.reverse(OldText):find(" ") == 1 then
			--print("New line was going to be space")
			OldText = string.reverse( ReversedText:sub(2, ReversedText:len() ) )
		end
		local Counter = 0
		local NewCursorPos = LastCursorPosition
		repeat
			if OldText:sub(1, LastCursorPosition-2):find(" ") and Counter < 5 then
				local PrecursorString = OldText:sub(1, LastCursorPosition)
				local StringSplit = PrecursorString:split(" ")
				local AssembledString = ""
				for i = 1, #StringSplit do
					if i == 1 then
						AssembledString = StringSplit[i]
					elseif i ~= #StringSplit then
						AssembledString = AssembledString.. " " ..StringSplit[i]
					else
						AssembledString = AssembledString .. " \n" .. StringSplit[i]
					end
				end
				TextBox.Text = AssembledString ..  OldText:sub(LastCursorPosition, OldText:len())
				NewCursorPos = AssembledString:len() + 1
			else
				local NewFormatString = OldText:sub(1,LastCursorPosition-(1 + TextAdjustment)) .. "\n" 
				NewCursorPos = NewFormatString:len() + 3
				TextBox.Text = NewFormatString.. OldText:sub(LastCursorPosition-(TextAdjustment), OldText:len())
				TextAdjustment+=1
			end
			Counter += 1
			wait()
		until TextBox.TextFits == true or Counter > 100
		TextBox.CursorPosition = NewCursorPos
		TextBox.TextEditable = true
		TextBox.Selectable = true
		TextBox:CaptureFocus()
	end
end)

Click to view solution on other thread. (This one is a much better solution to OP's root issue.)
1 Like

yeah, I tried it with this script and this happened


oh, wow. thank you, this would work since it’s not really the player typing in the text box but my type writing script so no need to worry of not being able to type in the middle (still does kind of work when i type in the middle). also it does work with fast typing and copy pasting. thank you, i really appreciate it!

oh wait, it bugs with the type writing script?
this happens

i used a textbox instead of a textlabel so i can add a placeholder text, it’s easier than making a script to type the “Enter a prompt…”

That’s because the workaround was intended for user input, not script input. I didn’t know you were going to use script input. Typically, TextBoxes are reserved for the user while TextLabels are used by scripts. This is going to need a different approach to workaround these issues.