Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
Komag
Level 9

Need help with custom text "line break" system

A while back RokuMarkn was awesome and gave me a nice line-splitting function that will break up long text strings if they are longer than a specified width. I've used it a ton, and now I'd like to add the ability for it to automatically start a new line if it encounters the characters "/n".
Example Text:
I went to the store and bought:/nMilk, Eggs, and Bread."

I've been working on my game since last summer and learned a ton of BrightScript (and programming in general, since I've never really done it before), but I still can't get my head around this function or how to tweak it. I'm hoping it's just a matter of adding a few lines, and that's what I'm asking help for now.

Here is RokuMarkn's function (with some of my notes)
FUNCTION SplitBlockText(text AS STRING, width AS INTEGER, font AS OBJECT) AS OBJECT ' trig by prepText(1) ' From RokuMarkn on the dev forums
'timer = createObject("roTimespan") ' For measuring performance
splitTextLines = []
linePos = 0
WHILE TRUE
WHILE text.Mid(linePos,1) = " "
linePos = linePos + 1 ' If it ever finds a Space, move the linePos ahead 1
END WHILE
end_line = linePos
WHILE TRUE
IF end_line >= text.Len() THEN
IF end_line > linePos THEN splitTextLines.Push(text.Mid(linePos, end_line - linePos))
'? "SplitBlockText() took " timer.totalMilliseconds() ' On 2XS one example takes 18-23ms, sometimes up to 44ms, very time consuming. ALWAYS do this ahead of time, not every frame
RETURN splitTextLines
END IF
e = EndWord(text, end_line)
IF font.GetOneLineWidth(text.Mid(linePos, e - linePos), width) >= width THEN
splitTextLines.Push(text.Mid(linePos, end_line - linePos))
linePos = end_line
EXIT WHILE
END IF
end_line = e
END WHILE
END WHILE
END FUNCTION

FUNCTION EndWord(text AS STRING, index AS INTEGER) AS INTEGER 'trig by SplitBlockText(1), from RokuMarkn on the dev forums
FOR p = index TO text.Len()
IF text.Mid(p,1) <> " " THEN EXIT FOR
END FOR
FOR p = p TO text.Len()
IF text.Mid(p,1) = " " THEN EXIT FOR
END FOR
RETURN p
END FUNCTION
0 Kudos
8 Replies
renojim
Level 8

Re: Need help with custom text "line break" system

The easy way is probably to split on \n first and then process each line: (untested)
lines = text.tokenize(chr(10))
splittext = []
for each line in lines
splittext.Append(SplitBlockText(line,width,font))
end for

-JT
0 Kudos
RokuMarkn
Level 7

Re: Need help with custom text "line break" system

Actually I added newline handling to my version some time ago. Try this.


function SplitBlockText(text as String, width as Integer, font as Object) as Object
lines = []
line = 0
while true
' Skip spaces.
while text.Mid(line,1) = " "
line = line + 1
end while
end_line = line
' Output line starts here; step thru words.
while true
if end_line >= text.Len() then
if end_line > line then lines.Push(text.Mid(line, end_line-line))
return lines
end if
newline = (text.Mid(end_line,1) = Chr(10))
if not newline then e = EndWord(text, end_line)
if newline or font.GetOneLineWidth(text.Mid(line, e-line), width) >= width then
lines.Push(text.Mid(line, end_line-line))
line = end_line
if newline then line = line + 1
exit while
end if
end_line = e
end while
end while
end function

function EndWord(text as String, index as Integer) as Integer
for p = index to text.Len()
if text.Mid(p,1) <> " " then exit for
end for
for p = p to text.Len()
if text.Mid(p,1) = " " or text.Mid(p,1) = Chr(10) then exit for
end for
return p
end function
0 Kudos
Komag
Level 9

Re: Need help with custom text "line break" system

Thanks for that. I've tested with other characters and it splits it up as expected, but how do I enter a Chr(10) into my strings? Like this?
"I went to the store and bought:"+Chr(10)+"Milk, Eggs, and Bread."

...Yes, it works great, thanks!

Here is my new code, fully working as desired:
FUNCTION SplitBlockText(text AS STRING, width AS INTEGER, font AS OBJECT) ' trig by prepText(1) ' From renojim on the dev forums
lines = text.tokenize(Chr(10)) ' Ascii 10 is New Line or Line Feed. Enter in strings like: "Hello."+Chr(10)+"Goodbye." ' Don't use "/n" because both / and n are delims, so all n's cause split!
splitText = []
FOR EACH line IN lines ' Original text was one big string, got broken down by delimiter Chr(10) into multiple lines
splitText.Append(SplitBlockTextWork(line, width, font)) ' Break up each line that is still too wide into an array of multiple lines, and add (Append) each new array into splitText
END FOR
RETURN splitText
END FUNCTION

FUNCTION SplitBlockTextWork(text AS STRING, width AS INTEGER, font AS OBJECT) AS OBJECT ' trig by SplitBlockText(1) ' From RokuMarkn on the dev forums
'timer = createObject("roTimespan") ' For measuring performance
splitTextLines = []
linePos = 0
WHILE TRUE
WHILE text.Mid(linePos,1) = " " ' Mid(start_index as Integer, num_chars as Integer) as String. Ex: s.Mid(0, 1) returns the first letter of s, while s.Mid(2, 2) returns the 3rd and 4th letters
linePos = linePos + 1 ' If it ever finds a Space, move the linePos ahead 1
END WHILE
end_line = linePos
WHILE TRUE
IF end_line >= text.Len() THEN
IF end_line > linePos THEN splitTextLines.Push(text.Mid(linePos, end_line - linePos))
'? "SplitBlockText() took " timer.totalMilliseconds() ' On 2XS takes 18-23ms, sometimes up to 44ms, very time consuming. ALWAYS do this ahead of time, not every frame
RETURN splitTextLines
END IF
e = EndWord(text, end_line)
IF font.GetOneLineWidth(text.Mid(linePos, e - linePos), width) >= width THEN
splitTextLines.Push(text.Mid(linePos, end_line - linePos))
linePos = end_line
EXIT WHILE
END IF
end_line = e
END WHILE
END WHILE
END FUNCTION

FUNCTION EndWord(text AS STRING, index AS INTEGER) AS INTEGER 'trig by SplitBlockText(1), from RokuMarkn on the dev forums
FOR p = index TO text.Len()
IF text.Mid(p,1) <> " " THEN EXIT FOR
END FOR
FOR p = p TO text.Len()
IF text.Mid(p,1) = " " THEN EXIT FOR
END FOR
RETURN p
END FUNCTION
0 Kudos
Komag
Level 9

Re: Need help with custom text "line break" system

Ah, missed that post while preparing mine - I'll probably use that new integrated version RokuMarkn, thanks!
0 Kudos
Komag
Level 9

Re: Need help with custom text "line break" system

It works great, and I'm starting to follow that code the more I dig into it.

Thanks to both of you renojim and RokuMarkn, I appreciate it. Smiley Happy

Is there a more natural way of including line breaks in my strings than inserting +Chr(10)+ ?
0 Kudos
Roku Employee
Roku Employee

Re: Need help with custom text "line break" system

"Komag" wrote:
Is there a more natural way of including line breaks in my strings than inserting +Chr(10)+ ?


If you are targeting firmware 6.1 or later, I would use roString Replace method to replace a placeholder string with the newline char.

E.g.
s = "this\nthat\nthose"
s = s.replace("\n", chr(10))
0 Kudos
belltown
Level 7

Re: Need help with custom text "line break" system

Or if you want to target all Roku firmware versions:


s = "this\nthat\nthose"
s = CreateObject ("roRegex", "\\n", "").ReplaceAll (s, Chr (10))
https://github.com/belltown/
0 Kudos
Komag
Level 9

Re: Need help with custom text "line break" system

I am targeting all Rokus, so I may look at that regular expression stuff
0 Kudos