Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
RokuMarkn
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

You're only clearing it once at the beginning of the program. You need to clear it every time you draw the text, so that you're not drawing new text on top of old text.

--Mark
0 Kudos
bcoding
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

"RokuMarkn" wrote:
You're only clearing it once at the beginning of the program. You need to clear it every time you draw the text, so that you're not drawing new text on top of old text.

--Mark


Thank you for the input. I am using the code provided by NewManLiving. If I run the code as provided, it runs fine. I am able to scroll up and down smothly.
However, I need to have a background image that will cover the entire screen and on the middle part of the screen I need a transparent area where the scrollable items will be placed. Therefore it should look like scrollable items are on top of the image.

Here is the code provided by NewManLiving:


Sub Main()

' This is strictly for example - You really should NOT create your globals this way
' There is a much better way which I will not go into now, but to demonstrate how a region works
' this will have to do

l_color = &h262626FF

m.Screen = CreateObject( "roScreen", True )
m.Compositor = CreateObject( "roCompositor" )
Port = CreateObject( "roMessagePort" )
m.Screen.SetMessagePort( Port )
m.Screen.Clear( l_color )
m.Compositor.SetDrawTo( m.Screen, l_color )

Registry = CreateObject( "roFontRegistry" )
FontR26 = Registry.GetDefaultFont( 26, False, False )

l_data = [
"1) Get a Macbook pro with 4GB ram and 250gb harddrive",
"2) Get a Macbook pro with 8GB ram and 260gb harddrive",
"3) Get a Macbook pro with 12GB ram and 270gb harddrive",
"4) Get a Macbook pro with 14GB ram and 280gb harddrive",
"5) Get a Macbook pro with 16GB ram and 290gb harddrive",
"6) Get a Macbook pro with 18GB ram and 300gb harddrive",
"7) Get a Macbook pro with 20GB ram and 310gb harddrive",
"8) Get a Macbook pro with 22GB ram and 320gb harddrive",
"9) Get a Macbook pro with 24GB ram and 330gb harddrive",
"10) Get a Macbook pro with 26GB ram and 340gb harddrive",
"11) Get a Macbook pro with 28GB ram and 350gb harddrive",
"12) Get a Macbook pro with 30GB ram and 360gb harddrive"
]

' Keep in mind there are only so many text strings that you can fit into a bitmap buffer, before you exceed its maximum size
' there is a much better way to do all of this, but for now to help you understand regions, i'll keep it simple

' You have 12 items in your data
l_count = l_data.Count()
' You want to show a page size of 5 items
l_pageSize = 5
' The height of one text line for this font is GetOneLineHeight()
l_textHeight = FontR26.GetOneLineHeight()
' The largest width for your data is probably item 12 + some padding, normally you would interate
' the data and save the maximum width for your bitmap buffer. So this is the bitmap buffers width
l_width = FontR26.GetOneLineWidth( l_data[ l_count - 1 ], 1000 ) + 25
' For this examle you have to fit all those strings into a bitmap buffer. If you had 250 + strings you could not
' do this, but there is a better way like i said
' so the total height of your bitmap buffer is l_height, which is the total count * the height of each line
l_height = l_count * l_textHeight
' Now for the region size. It will be the same width as the bitmap but you only want to show pagesize of data
' So the height of the region will bee the textheight * the page size
l_pageHeight = l_textHeight * l_pageSize

' Create the bitmap with l_width and l_height
Bitmap = CreateObject( "roBitmap", { Width: l_width, Height: l_height, AlphaEnable: True } )
'Clear it or leave it transparent
Bitmap.Clear( &h333333FF )
' Starting at y offset 0 ( you could play with this for margins, but then the region would have to change
' write each line of text, offsetting the y coord by text height
l_y = 0
for each l_str in l_data
Bitmap.DrawText( l_str, 0, l_y, &hCCCCCCFF, FontR26 )
l_y = l_y + l_textHeight
end for

' Create your region the same with, but only the page height
Region = CreateObject( "roRegion", Bitmap, 0, 0, l_width, l_pageHeight )
' Set wrap true
Region.SetWrap( True )
' Create the sprite
Sprite = m.Compositor.NewSprite( 200, 300, Region, 1 )
' Draw everything
m.Compositor.DrawAll()
m.Screen.SwapBuffers()

' Set up your event loop
' The frame rate for the up/down arrow
l_slowRate = 8
' The frame rate/number fwd/reverse arrows - ( this is not a true rate but good enough for lists )
l_fastRate = 2
' Delay between the button presses
l_delay = 200

' These are the constants for the buttons you can use the AA if you wish, probably best to
l_bp_BK = 0
l_bp_UP = 2
l_bp_DN = 3
l_bp_REV = 8
l_bp_FWD = 9

' Button pressed
l_index = 0
' Last button pressed
l_lastKey = -1
l_running = True

l_timer = CreateObject( "roTimeSpan" )

while( l_running )

' Get used to GetMessage, Wait is not really very good for anything but simple interface
l_msg = Port.GetMessage()

if type( l_msg ) = "roUniversalControlEvent"

l_index = l_msg.GetInt()
l_lastKey = l_index

' Based upon the key press, call the functions below
if l_index = l_bp_DN or l_index = l_bp_FWD
ScrollDown( Region, l_textHeight, l_slowRate )
else if l_index = l_bp_UP or l_index = l_bp_REV
ScrollUp( Region, l_textHeight, l_slowRate )
else if l_index = l_bp_BK
l_running = False
else if l_index >= 100 ' All key ups are value + 100
l_lastKey = -1
end if

' reset the timer for the delay
l_timer.Mark()
' User is holding down a button and the delay has been exceeded
else if ( l_lastKey >= 0 and l_timer.TotalMilliseconds() >= l_delay )

if l_lastKey = l_bp_DN
ScrollDown( Region, l_textHeight, l_slowRate )
else if l_lastKey = l_bp_FWD
ScrollDown( Region, l_textHeight, l_fastRate )
else if l_lastKey = l_bp_UP
ScrollUp( Region, l_textHeight, l_slowRate )
else if l_lastKey = l_bp_REV
ScrollUp( Region, l_textHeight, l_fastRate )
end if

end if

end while

' Always remove the sprite or you will have a memory leak, even out of scope it is not released
' must be explicity released at all times
if ( Sprite <> Invalid ) then Sprite.Remove()

End Sub

' This employs region offsetting and a very simple ease. You want to move the regions y pos by textheight each time the function is called
Function ScrollDown( roRegion As Object, height As Integer, frames As Integer ) As Void

' Not sure how optimized the byte code is so I simplify references when in loops
l_compositor = m.Compositor
l_screen = m.Screen
l_prevset = 0

for l_i = 1 to frames
' Offset means to move from the current position by the value
l_offset = int( height * l_i / frames )
l_offdiff = l_offset - l_prevset
l_prevset = l_offset

' Moving forward in Y direction so everything else is 0
roRegion.Offset( 0, l_offdiff, 0, 0 )
l_compositor.DrawAll()
l_screen.SwapBuffers()
end for

End Function

Function ScrollUp( roRegion As Object, height As Integer, frames As Integer ) As Void
l_compositor = m.Compositor
l_screen = m.Screen
l_prevset = 0

for l_i = 1 to frames
l_offset = int( height * l_i / frames )
l_offdiff = l_offset - l_prevset
l_prevset = l_offset
' same as aobve only moving back so the offset is negative
roRegion.Offset( 0, -l_offdiff, 0, 0 )
l_compositor.DrawAll()
l_screen.SwapBuffers()
end for
End Function

0 Kudos
Komag
Roku Guru

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

I think you may have to clear the bitmap and redraw the text every frame (within you're WHILE loop) to get that transparent effect you're looking for. Although it sort of kills the point of NML's code which was to avoid having to redraw the text every frame.
0 Kudos
NewManLiving
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

Yes That's correct. Clear would get rid of all the text defeating the whole purpose. If a design incorporates the compositor then the menu sprite should be created at a Z order higher than the background, so the background needs to be a Sprite as well generally placed at z order 0. Then compositor.drawall would first redraw the background and then the menu on top of it. In this case where there are a limited number of text all previously drawn into a bitmap then to scroll is simple. Create a region, set wrap to true and +/-offset the y position by the text height + any additional spacing as it was originally layed out in the bitmap. In the case of a virtual list where the number of items can vary or become very large then the bitmap is created with a virtual buffer zone hidden by the region. In this case there must be an explicit clear to get rid of the text that was previously there. However, this presents a problem when the clearing must be transparent. Drawing a transparent rectangle in that zone (which is always changing like a dog chasing its tail ) will not do the trick. The other option of using the bitmap or region to clear transparently will cause all text to be cleared resulting in a complete redraw of all text. To get around this caveat a seperate region is created the size of one row of text. When the user scrolls the data indexes are calculated to return the next text in the list, then the new y position of the buffer zone is determined by an offset from the previous rows position. This area is always hidden because the region is created one row size smaller than the bitmap. Since scrolling involves offsetting the region as opposed to redrawing all the text, then naturally the region moves exposing a new area of the bitmap while hiding another until it wraps around, thus the dog chasing its tail analogy. It is the new area that needs to be cleared before the new text is written and before the easing function offsets the region to expose that updated portion of the bitmap to the user. To clear this area then involves moving the seperate row region into that same area and clearing it transparently before the new text is written and before the main region is offset into that area.

I'm having some dialog with the poster. I like to help people interested in the 2D. Not sure where Scene Graph is going and what effect it will have upon the use of the 2D. One must first overcome their distaste for XML which I think is pretty ubiquitous and then grapple with the node-tree concept, and then finally get around all the things that just don't come out the way you expected them to by rummaging through the disconnected documentation to which you have 10 pages open in 10 browser Instances. But I am spending time with it. So we will see
My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
bcoding
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

"Komag" wrote:
I think you may have to clear the bitmap and redraw the text every frame (within you're WHILE loop) to get that transparent effect you're looking for. Although it sort of kills the point of NML's code which was to avoid having to redraw the text every frame.


yup it will defeat the purpose of drawing all the list items earlier. thank you for the response.
0 Kudos
bcoding
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

"NewManLiving" wrote:
Yes That's correct. Clear would get rid of all the text defeating the whole purpose. If a design incorporates the compositor then the menu sprite should be created at a Z order higher than the background, so the background needs to be a Sprite as well generally placed at z order 0. Then compositor.drawall would first redraw the background and then the menu on top of it. In this case where there are a limited number of text all previously drawn into a bitmap then to scroll is simple. Create a region, set wrap to true and +/-offset the y position by the text height + any additional spacing as it was originally layed out in the bitmap. In the case of a virtual list where the number of items can vary or become very large then the bitmap is created with a virtual buffer zone hidden by the region. In this case there must be an explicit clear to get rid of the text that was previously there. However, this presents a problem when the clearing must be transparent. Drawing a transparent rectangle in that zone (which is always changing like a dog chasing its tail ) will not do the trick. The other option of using the bitmap or region to clear transparently will cause all text to be cleared resulting in a complete redraw of all text. To get around this caveat a seperate region is created the size of one row of text. When the user scrolls the data indexes are calculated to return the next text in the list, then the new y position of the buffer zone is determined by an offset from the previous rows position. This area is always hidden because the region is created one row size smaller than the bitmap. Since scrolling involves offsetting the region as opposed to redrawing all the text, then naturally the region moves exposing a new area of the bitmap while hiding another until it wraps around, thus the dog chasing its tail analogy. It is the new area that needs to be cleared before the new text is written and before the easing function offsets the region to expose that updated portion of the bitmap to the user. To clear this area then involves moving the seperate row region into that same area and clearing it transparently before the new text is written and before the main region is offset into that area.

I'm having some dialog with the poster. I like to help people interested in the 2D. Not sure where Scene Graph is going and what effect it will have upon the use of the 2D. One must first overcome their distaste for XML which I think is pretty ubiquitous and then grapple with the node-tree concept, and then finally get around all the things that just don't come out the way you expected them to by rummaging through the disconnected documentation to which you have 10 pages open in 10 browser Instances. But I am spending time with it. So we will see



Thanks a lot NewManLiving for such insightful explanation. I have been gaining a lot of knowledge from this forum.
0 Kudos
RokuMarkn
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

Here's a version of NML's code that doesn't use the compositor but draws the text in each frame. You'll see the changes are actually very small. In this version it should be simpler to add a DrawObject to draw the background in each frame too.


Sub Main()

' This is strictly for example - You really should NOT create your globals this way
' There is a much better way which I will not go into now, but to demonstrate how a region works
' this will have to do

m.l_color = &h262626FF

m.Screen = CreateObject( "roScreen", True )
Port = CreateObject( "roMessagePort" )
m.Screen.SetMessagePort( Port )

Registry = CreateObject( "roFontRegistry" )
FontR26 = Registry.GetDefaultFont( 26, False, False )

l_data = [
"1) Get a Macbook pro with 4GB ram and 250gb harddrive",
"2) Get a Macbook pro with 8GB ram and 260gb harddrive",
"3) Get a Macbook pro with 12GB ram and 270gb harddrive",
"4) Get a Macbook pro with 14GB ram and 280gb harddrive",
"5) Get a Macbook pro with 16GB ram and 290gb harddrive",
"6) Get a Macbook pro with 18GB ram and 300gb harddrive",
"7) Get a Macbook pro with 20GB ram and 310gb harddrive",
"8) Get a Macbook pro with 22GB ram and 320gb harddrive",
"9) Get a Macbook pro with 24GB ram and 330gb harddrive",
"10) Get a Macbook pro with 26GB ram and 340gb harddrive",
"11) Get a Macbook pro with 28GB ram and 350gb harddrive",
"12) Get a Macbook pro with 30GB ram and 360gb harddrive"
]

' Keep in mind there are only so many text strings that you can fit into a bitmap buffer, before you exceed its maximum size
' there is a much better way to do all of this, but for now to help you understand regions, i'll keep it simple

' You have 12 items in your data
l_count = l_data.Count()
' You want to show a page size of 5 items
l_pageSize = 5
' The height of one text line for this font is GetOneLineHeight()
l_textHeight = FontR26.GetOneLineHeight()
' The largest width for your data is probably item 12 + some padding, normally you would interate
' the data and save the maximum width for your bitmap buffer. So this is the bitmap buffers width
l_width = FontR26.GetOneLineWidth( l_data[ l_count - 1 ], 1000 ) + 25
' For this examle you have to fit all those strings into a bitmap buffer. If you had 250 + strings you could not
' do this, but there is a better way like i said
' so the total height of your bitmap buffer is l_height, which is the total count * the height of each line
l_height = l_count * l_textHeight
' Now for the region size. It will be the same width as the bitmap but you only want to show pagesize of data
' So the height of the region will bee the textheight * the page size
l_pageHeight = l_textHeight * l_pageSize

' Create the bitmap with l_width and l_height
Bitmap = CreateObject( "roBitmap", { Width: l_width, Height: l_height, AlphaEnable: True } )
'Clear it or leave it transparent
Bitmap.Clear( &h333333FF )
' Starting at y offset 0 ( you could play with this for margins, but then the region would have to change
' write each line of text, offsetting the y coord by text height
l_y = 0
for each l_str in l_data
Bitmap.DrawText( l_str, 0, l_y, &hCCCCCCFF, FontR26 )
l_y = l_y + l_textHeight
end for

' Create your region the same with, but only the page height
Region = CreateObject( "roRegion", Bitmap, 0, 0, l_width, l_pageHeight )
' Set wrap true
Region.SetWrap( True )

' Set up your event loop
' The frame rate for the up/down arrow
l_slowRate = 8
' The frame rate/number fwd/reverse arrows - ( this is not a true rate but good enough for lists )
l_fastRate = 2
' Delay between the button presses
l_delay = 200

' These are the constants for the buttons you can use the AA if you wish, probably best to
l_bp_BK = 0
l_bp_UP = 2
l_bp_DN = 3
l_bp_REV = 8
l_bp_FWD = 9

' Button pressed
l_index = 0
' Last button pressed
l_lastKey = -1
l_running = True

l_timer = CreateObject( "roTimeSpan" )

while( l_running )

DrawScreen( Region )

' Get used to GetMessage, Wait is not really very good for anything but simple interface
l_msg = Port.GetMessage()

if type( l_msg ) = "roUniversalControlEvent"

l_index = l_msg.GetInt()
l_lastKey = l_index

' Based upon the key press, call the functions below
if l_index = l_bp_DN or l_index = l_bp_FWD
ScrollDown( Region, l_textHeight, l_slowRate )
else if l_index = l_bp_UP or l_index = l_bp_REV
ScrollUp( Region, l_textHeight, l_slowRate )
else if l_index = l_bp_BK
l_running = False
else if l_index >= 100 ' All key ups are value + 100
l_lastKey = -1
end if

' reset the timer for the delay
l_timer.Mark()
' User is holding down a button and the delay has been exceeded
else if ( l_lastKey >= 0 and l_timer.TotalMilliseconds() >= l_delay )

if l_lastKey = l_bp_DN
ScrollDown( Region, l_textHeight, l_slowRate )
else if l_lastKey = l_bp_FWD
ScrollDown( Region, l_textHeight, l_fastRate )
else if l_lastKey = l_bp_UP
ScrollUp( Region, l_textHeight, l_slowRate )
else if l_lastKey = l_bp_REV
ScrollUp( Region, l_textHeight, l_fastRate )
end if

end if

end while

End Sub

' This employs region offsetting and a very simple ease. You want to move the regions y pos by textheight each time the function is called
Function ScrollDown( roRegion As Object, height As Integer, frames As Integer ) As Void

' Not sure how optimized the byte code is so I simplify references when in loops
l_screen = m.Screen
l_prevset = 0

for l_i = 1 to frames
' Offset means to move from the current position by the value
l_offset = int( height * l_i / frames )
l_offdiff = l_offset - l_prevset
l_prevset = l_offset

' Moving forward in Y direction so everything else is 0
roRegion.Offset( 0, l_offdiff, 0, 0 )
DrawScreen(roRegion)
end for

End Function

Function ScrollUp( roRegion As Object, height As Integer, frames As Integer ) As Void
l_screen = m.Screen
l_prevset = 0

for l_i = 1 to frames
l_offset = int( height * l_i / frames )
l_offdiff = l_offset - l_prevset
l_prevset = l_offset
' same as aobve only moving back so the offset is negative
roRegion.Offset( 0, -l_offdiff, 0, 0 )
DrawScreen(roRegion)
end for
End Function

Function DrawScreen( region as Object )
m.Screen.Clear( m.l_color )
m.Screen.DrawObject( 200, 300, region )
m.Screen.SwapBuffers()
End Function
0 Kudos
NewManLiving
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

Yes, That would be the way it is done without the compositor; However, I believe that he is using the compositor, at least that is what I had gathered from previous posts. Which is why I stated initially: "'If one is to incorporate' the compositor into their design, then just setting the z order properly and creating a background sprite would work"

Your method is extremely useful for optimizing complex animation when not using the compositor and reduces the need to create temporary bitmaps and sprites when using the compositor. I make use of it extensively, and this technique is demonstrated the keyboard.zip that I put out recently. Most of the selector animation is a direct drawing of regions to the screen sandwiched in-between Compositor.DrawAll and screen.swapbuffers.

The combination of both permits even a higher level of complexity, especially in asynchronous drawing. This is demonstrated in the Matrix Grid in my demo channel. With this type of complexity you do not know when anything is coming in from the texturemanager, until it arrives, coupled with the user scrolling/selecting/ cursor animation, the possibility that the texture had not arrived prior to the user selecting the grid cell, and/or other multi-layered animation all going on at the same time. So one way or the other you have to introduce this logic into your channel using a bunch of flags and if statements ( have done it ) or you can just depend upon the compositor to draw whatever sprite happens to be in its sprite list at the time the event occurs, and concentrate on optimizing any drawing that is concrete and known during the execution of a particular event. I personally have found this beneficial, and have been able over the years to produce interface that is unique
My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
bcoding
Visitor

Re: scrolling in roScreen, roBitmap, roRegion, roCompositor

"RokuMarkn" wrote:
Here's a version of NML's code that doesn't use the compositor but draws the text in each frame. You'll see the changes are actually very small. In this version it should be simpler to add a DrawObject to draw the background in each frame too.


Sub Main()

' This is strictly for example - You really should NOT create your globals this way
' There is a much better way which I will not go into now, but to demonstrate how a region works
' this will have to do

m.l_color = &h262626FF

m.Screen = CreateObject( "roScreen", True )
Port = CreateObject( "roMessagePort" )
m.Screen.SetMessagePort( Port )

Registry = CreateObject( "roFontRegistry" )
FontR26 = Registry.GetDefaultFont( 26, False, False )

l_data = [
"1) Get a Macbook pro with 4GB ram and 250gb harddrive",
"2) Get a Macbook pro with 8GB ram and 260gb harddrive",
"3) Get a Macbook pro with 12GB ram and 270gb harddrive",
"4) Get a Macbook pro with 14GB ram and 280gb harddrive",
"5) Get a Macbook pro with 16GB ram and 290gb harddrive",
"6) Get a Macbook pro with 18GB ram and 300gb harddrive",
"7) Get a Macbook pro with 20GB ram and 310gb harddrive",
"8) Get a Macbook pro with 22GB ram and 320gb harddrive",
"9) Get a Macbook pro with 24GB ram and 330gb harddrive",
"10) Get a Macbook pro with 26GB ram and 340gb harddrive",
"11) Get a Macbook pro with 28GB ram and 350gb harddrive",
"12) Get a Macbook pro with 30GB ram and 360gb harddrive"
]

' Keep in mind there are only so many text strings that you can fit into a bitmap buffer, before you exceed its maximum size
' there is a much better way to do all of this, but for now to help you understand regions, i'll keep it simple

' You have 12 items in your data
l_count = l_data.Count()
' You want to show a page size of 5 items
l_pageSize = 5
' The height of one text line for this font is GetOneLineHeight()
l_textHeight = FontR26.GetOneLineHeight()
' The largest width for your data is probably item 12 + some padding, normally you would interate
' the data and save the maximum width for your bitmap buffer. So this is the bitmap buffers width
l_width = FontR26.GetOneLineWidth( l_data[ l_count - 1 ], 1000 ) + 25
' For this examle you have to fit all those strings into a bitmap buffer. If you had 250 + strings you could not
' do this, but there is a better way like i said
' so the total height of your bitmap buffer is l_height, which is the total count * the height of each line
l_height = l_count * l_textHeight
' Now for the region size. It will be the same width as the bitmap but you only want to show pagesize of data
' So the height of the region will bee the textheight * the page size
l_pageHeight = l_textHeight * l_pageSize

' Create the bitmap with l_width and l_height
Bitmap = CreateObject( "roBitmap", { Width: l_width, Height: l_height, AlphaEnable: True } )
'Clear it or leave it transparent
Bitmap.Clear( &h333333FF )
' Starting at y offset 0 ( you could play with this for margins, but then the region would have to change
' write each line of text, offsetting the y coord by text height
l_y = 0
for each l_str in l_data
Bitmap.DrawText( l_str, 0, l_y, &hCCCCCCFF, FontR26 )
l_y = l_y + l_textHeight
end for

' Create your region the same with, but only the page height
Region = CreateObject( "roRegion", Bitmap, 0, 0, l_width, l_pageHeight )
' Set wrap true
Region.SetWrap( True )

' Set up your event loop
' The frame rate for the up/down arrow
l_slowRate = 8
' The frame rate/number fwd/reverse arrows - ( this is not a true rate but good enough for lists )
l_fastRate = 2
' Delay between the button presses
l_delay = 200

' These are the constants for the buttons you can use the AA if you wish, probably best to
l_bp_BK = 0
l_bp_UP = 2
l_bp_DN = 3
l_bp_REV = 8
l_bp_FWD = 9

' Button pressed
l_index = 0
' Last button pressed
l_lastKey = -1
l_running = True

l_timer = CreateObject( "roTimeSpan" )

while( l_running )

DrawScreen( Region )

' Get used to GetMessage, Wait is not really very good for anything but simple interface
l_msg = Port.GetMessage()

if type( l_msg ) = "roUniversalControlEvent"

l_index = l_msg.GetInt()
l_lastKey = l_index

' Based upon the key press, call the functions below
if l_index = l_bp_DN or l_index = l_bp_FWD
ScrollDown( Region, l_textHeight, l_slowRate )
else if l_index = l_bp_UP or l_index = l_bp_REV
ScrollUp( Region, l_textHeight, l_slowRate )
else if l_index = l_bp_BK
l_running = False
else if l_index >= 100 ' All key ups are value + 100
l_lastKey = -1
end if

' reset the timer for the delay
l_timer.Mark()
' User is holding down a button and the delay has been exceeded
else if ( l_lastKey >= 0 and l_timer.TotalMilliseconds() >= l_delay )

if l_lastKey = l_bp_DN
ScrollDown( Region, l_textHeight, l_slowRate )
else if l_lastKey = l_bp_FWD
ScrollDown( Region, l_textHeight, l_fastRate )
else if l_lastKey = l_bp_UP
ScrollUp( Region, l_textHeight, l_slowRate )
else if l_lastKey = l_bp_REV
ScrollUp( Region, l_textHeight, l_fastRate )
end if

end if

end while

End Sub

' This employs region offsetting and a very simple ease. You want to move the regions y pos by textheight each time the function is called
Function ScrollDown( roRegion As Object, height As Integer, frames As Integer ) As Void

' Not sure how optimized the byte code is so I simplify references when in loops
l_screen = m.Screen
l_prevset = 0

for l_i = 1 to frames
' Offset means to move from the current position by the value
l_offset = int( height * l_i / frames )
l_offdiff = l_offset - l_prevset
l_prevset = l_offset

' Moving forward in Y direction so everything else is 0
roRegion.Offset( 0, l_offdiff, 0, 0 )
DrawScreen(roRegion)
end for

End Function

Function ScrollUp( roRegion As Object, height As Integer, frames As Integer ) As Void
l_screen = m.Screen
l_prevset = 0

for l_i = 1 to frames
l_offset = int( height * l_i / frames )
l_offdiff = l_offset - l_prevset
l_prevset = l_offset
' same as aobve only moving back so the offset is negative
roRegion.Offset( 0, -l_offdiff, 0, 0 )
DrawScreen(roRegion)
end for
End Function

Function DrawScreen( region as Object )
m.Screen.Clear( m.l_color )
m.Screen.DrawObject( 200, 300, region )
m.Screen.SwapBuffers()
End Function


As NML mentioned I am using compositor. However, this approach is interesting too. Thank you for your help.
0 Kudos
Need Assistance?
Welcome to the Roku Community! Feel free to search our Community for answers or post your question to get help.

Become a Roku Streaming Expert!

Share your expertise, help fellow streamers, and unlock exclusive rewards as part of the Roku Community. Learn more.