I’m trying to make a fully functional readable book, which means I will have to work with very long texts, but I’m stuck as to how I’m going to fit all of that text on a frame, so my plan is to somehow cut the texts into multiple pieces via script and store them in a table.
I know how to detect that the text doesn’t fit thanks to the TextFits property, but then how do I split up the string from the last letter that did fit in? I’ve tried looping through the letters and adding them to a temporary TextLabel instance until TextFits becomes false, but that turned out to be a disaster and I can see why that wouldn’t be optimal
Basically, there’s more text to be displayed after that, it’s just limited to one side of the book because I use TextWrapped, I want to get the rest of the text that didn’t fit in and display it on the other page
From what I’ve tried TextLabel.ContentText just gives me what TextLabel.Text already does, it doesn’t seem to be very useful, I heard it’s only useful if you use rich text
Does your text scaled or fixed size?
If it’s fixed size, then you can get text bounds, with TextService, giving inf height and limited width, and then approximatelly split text by returned height.
Like if your page height is 250, and TextService returns height 600, then it means that text should cover 2 full pages and one by 40%
I must say that if player changes screen size, then you will need recalculate everything.
You now need to get rough symbol count per page for text.
local Height = viewportFrame.Page1.PageLeft.AbsoluteSize.Y
local SymbolsPerPage = math.floor(string.len(bookContent.Value)*bounds.Y/Height)
local Pages = math.ceil(string.len(bookContent.Value)/SymbolsPerPage)
for i = 1, Pages, 1 do
local PageText = string.sub(bookContent.Value, (i-1)*SymbolsPerPage+1, i*SymbolsPerPage)
--Apply your text to page here.
end
Although, this won’t be ideal, because you are using not monowidth font, and such method may cut off 1-2 words.
local params = Instance.new("GetTextBoundsParams")
local width = viewportFrame.Page1.PageLeft.AbsoluteSize.X
local height = viewportFrame.Page1.PageLeft.AbsoluteSize.Y
params.Text = bookContent.Value
params.Font = Font.new("rbxasset://fonts/families/AccanthisADFStd.json", Enum.FontWeight.Regular)
params.Size = 14
params.Width = width
local bounds = textService:GetTextBoundsAsync(params)
local SymbolsPerPage = math.floor(string.len(bookContent.Value)*bounds.Y/height)
local Pages = math.ceil(string.len(bookContent.Value)/SymbolsPerPage)
for i = 1, Pages, 1 do
local PageText = string.sub(bookContent.Value, (i-1)*SymbolsPerPage+1, i*SymbolsPerPage)
viewportFrame.Page1.PageRight.Text = PageText
end
When I tried printing PageText it just gave a copy of the original text
Alright I tweaked your code a little bit and it worked
local SymbolsPerPage = math.floor(string.len(bookContent.Value)*height/bounds.Y)
local Pages = math.ceil(string.len(bookContent.Value)/SymbolsPerPage)
print(Pages)
for i = 1, Pages, 1 do
local PageText = string.sub(bookContent.Value, (i-1)*SymbolsPerPage+1, i*SymbolsPerPage)
table.insert(page, PageText)
end
But like you said some words are cut off, what other methods are better and how do I find out which fonts are mono width?
I’m sorry that I not replied before, unnoticed somehow.
About monowidth texts: Roblox has none. =C
About some words being cut off: after you got page text (approximate), which can cut off text, you can get text bounds again. If text bounds exceed page size, remove some symbols (1-5 symbols), otherwise add them. If text begins to comply with page size, or stops compying it (in case of removing/adding letters), you stop and output that page text.
Although, it needs to be somewhat optimized, cause if text will have firstly thin letters like “iiiiiiiiiiiiii” and after wide letters: “wwwwwwwwwwwwwwwww”, such approach may load calculations.