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: 
squirreltown
Roku Guru

roscreen grid

I need to build a roscreen based grid screen which will operate like the built-in component one. I have little experience with regions and know they will be necessary here. I would appreciate if someone who has done this could give me a basic strategy for building one row. I don't need code, just a description of how it might go. I know i can make a graphic into a bitmap region and scroll it , but I can't see how to take a bunch of thumbs and space them properly and more importantly how to deal with the off screen part ( I need way more than 2048 pix for a row). I would have a max of 120 thumbs on any one row.
Thank you.
Kinetics Screensavers
0 Kudos
47 REPLIES 47
NewManLiving
Visitor

Re: roscreen grid

One way of Building a virtual grid is not much different
Than building a virtual list which I demonstrated
In the recent API wisdom post You just change the direction
Of the region. Instead
Of moving in the y direction you are moving
In the x. You also create a grid container
That contains a description of your cells. More on
That later. But the real issue is how are you
Supplying data to the grid. Do you preload all your
Thumbs or do you expect to fetch them as you
Go along that would add some complexity
To it ???
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
RokuJoel
Binge Watcher

Re: roscreen grid

Lets see, essentially, you would have an array of content items. One property of those content items could be a boolean onscreen:false
you would want to mark items as false as the move off screen and on as the move on screen.

Keeping distance is easy:

width=imagewidth+10
for i=0 to itemcount() -1
if images[i].onscreen then
screen.drawobject(images[i].bmp,hPos,i*width)
end if
end for


Of course, you need to be able to load and unload images in a way that won't interrupt the users flow, generally use roTextureManager to do that or for legacy, roURLTransfer, they are more or less interchangeable. Having a default "loading" bitmap makes this much easier as you can setup and display your GUI right away while images are downloading in the background.

Use the same content item style that we use for all Roku items, and add a few relevant fields like

item.bitmap
item.region
item.sprite
Item.onscreen

If you plan to wrap around each end of the grid, you'll need a mechanism to do that. This might help:

http://stackoverflow.com/questions/1519 ... s-a-circle

- Joel
0 Kudos
squirreltown
Roku Guru

Re: roscreen grid

Hey Thanks NewManLiving, I copied your example but haven't run it yet, so I will have a good look at it.
The files I will use are currently in the MRSS grid format - that is, the grid loads an .opml file which references an RSS feed which pulls the list of the images/titles/info that get downloaded. The files will not be changing dynamically, once the user selects the grid, the list of files is static, so I can download them all to temp (which is what it appears the stock grid is doing) if thats the easiest way. They are small files and there are not a lot of them (around 120 max).
Kinetics Screensavers
0 Kudos
squirreltown
Roku Guru

Re: roscreen grid

Joel - Thank you. I'd be less then honest if I said that all made sense right now but I know it will soon. Every new thing on this box is like pulling teeth for me but then after I wonder why it was so hard. I try to remember watching people use a mouse for the first time and then I don't feel so bad.
Kinetics Screensavers
0 Kudos
NewManLiving
Visitor

Re: roscreen grid

You enjoy what you do so you will learn
And you will be very good
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
RokuMarkn
Visitor

Re: roscreen grid

This is a pretty substantial task you've taken on. You should also be aware that you may not achieve the same performance as a real grid. I recently wrote a side-scrolling game which faced similar issues. This is how I'd approach it.

In the active row at least, you should maintain some wide offscreen bitmaps (probably as wide as possible, 2048) containing the image of a horizontal section of the row, starting at a certain position. It's probably simplest to maintain these images as an LRU cache. Whenever the user switches the horizontal scrolling direction, you'd make sure you have the next image in that direction cached; if not, then start a job to build it. Because there are no threads in brightscript, the building job has to be written in a way that lets it be done in small increments. In your main event loop, you'd draw the current frame by copying the appropriate offscreen images to the screen and calling SwapBuffers. You would then call a function (I called it Crank) which does a little work to build the current incomplete image and returns. You need to tune this to make sure you do enough work in each frame to have the image ready when you need it (based on scrolling speed), but not so much work that you delay the production of the current frame.

--Mark
0 Kudos
squirreltown
Roku Guru

Re: roscreen grid

Thank you Mark, thats sobering, but I knew this one would be the bear. The audio springboard was easy and the slideshow was mostly head-scratching about the procedure, so I'm probably due some trouble and I'm starting to get how much is involved here with the grid. I will add your description to my pile and you can be sure this won't be the last you hear from me on this. Thanks again.
Kinetics Screensavers
0 Kudos
NewManLiving
Visitor

Re: roscreen grid

Hello squirreltown:

I put this together real quick, so it is a rush job. But I believe it is in the right direction. Copy and run it .. If you like it I'll help you flesh it out
If you have any problems let me know. I rushed it but I believe it performs as commented




' Ok Buddy Here is a very simple virtual grid. And it took great pains for me to do this
' because 1 - I did not use a compositor aarrrrgghhh. 2 -I did not use an object arrrggghhh
' But it is top down and straightforward so you can understand how it works. Once you do then
' if you like it and want to continue I will help you, I will also show you how to encapsulate it
' into an obejct if you want to

' Limitations:
' 1 - for now you can only scroll to the right. Once you understand that then I'll show you how
' to page flip the indexes to go in the opposite direction. Then we will add paging if you want

' 2 - Most of the parameters are hard coded so I cannot predict what will happen if you change them
' Error checking will come later. Again, the idea is for you to understand what is going on
' You can experiment with the page and margin sizes at this time, but again I am not concerned
' right now with that so you may get some interesting results. Perfecting it can only come after
' understanding it

' 3 - The program generates 120 bitmaps of size 175 x 200 ( I dont know what your thumb size is)
' but it really does not matter as far as the grid is concerned; however, memory is quickly
' absorbed even by these 120 bitmaps. use r2d2_bitmaps to observe. So if you change the
' dummy bitmap generator at the bottom to increase the number of bitmaps, very shortly it will fail.

' 4 - If you decide you like this method. Then we will change the bitmap cache for the temp folder cache
' and build some cache management using both the temp folder and memory
' I have not tried this yet as I use a different caching method, but since you are at any one time
' only loading and drawing one small bitmap, my guess is that it will be very acceptable. Thus my
' interest as well. Well, when paging you will be writing a page full, but your page full does not
' need to exceed the size of the screen. So at most you will have possibly ten. Learn to use and
' understand a region. if you understand this well, the concept of writing something off-screan will fade
' and be replaced by "write something outside the region"

Function Main() As Void

' standard stuff
Screen = CreateObject("roScreen", True)
Screen.Clear(&hE0DFDFFF)
Screen.SwapBuffers()

SimpleVGrid(Screen)

End Function


Function SimpleVGrid(Screen As Object)

' Generate 120 test bitmaps
bitmaps = GetBitmaps()

' Total number of bitmaps
bitmapCount = bitmaps.Count()
' Bitmap index
bitmapIndex = 0
' virtual column index
bufferIndex = 0

' width and height of our bitmaps. You can play with this if you want (change it to your size)
' but again this is an introduction so all that good stuff comes later
width = 175
height = 200
' If you don't want to use a margin set it to 0
margin = 20

' This is how many cells in the grid are displayed you can set it from 1 to
' the number that will fit comfortably in the dimensions of your display. It is
' not necessary to go beyond the screen. The user cannot see any more than that
' If you want that effect, then offset in drawobject.
' And you risk making the grid bitmap too large and throwing an exception
' Screen.DrawObject( 75, 200, gridRegion ) increase the 75 to where you like it
pageSize = 6
' The actual column width is the width of the bitmap plus any margin
columnWidth = (width + margin)

' Ok now we are going to create the grid buffer. You notice that its width will be
' pagesize * columnwidth + columwidth the additional columnwidth is the virtuall column
bmBuffer = pageSize * columnWidth + columnWidth
' What the user sees is the same size - the extra column. that column is updated
' and then scrolled into view.
bmRegion = pageSize * columnWidth

' Create your bitmap and region based on the above calculations. The region will start at
' position 0,0 in the bitmap, extend the width of the bitmap minus one columnwidht
' and be the same heigh as the bitmap
gridBitmap = CreateObject("roBitmap", {width: bmBuffer, height: height, AlphaEnable: false})
gridRegion = CreateObject("roRegion", gridBitmap, 0, 0, bmRegion - margin, height)
' You must set the wrap to true for this to work, otherwise you have to do it another way
gridRegion.SetWrap(true)

' Now its time for the fun. Bitmap index is set to 0 . It is an index into the
' array of bitmaps . x is set to 0 then incremented by columnwidth to draw each
' page full of bitmaps
x = 0
bitmapIndex = 0

' Clear the bitmap
gridBitmap.Clear(&hE0DFDFFF)

' I prefer to do it this way (2 to pagesize) then after the loop exits
' draw the final column
for i = 2 to pageSize

' Now you want to draw a page full of bitmpas right into
' the bitmap buffer
gridBitmap.DrawObject(x, 0, bitmaps[bitmapIndex])

' Increment the x pos by columnwidth to draw the next cell
x = x + columnWidth

' Increment the bitmapindex by one to draw the next bitmap in the array
' If you have to wrap around then do so
bitmapIndex = bitmapIndex + 1
if bitmapIndex >= bitmapCount then bitmapIndex = 0

end for

' After we exit the loop you notice that x was incremented and bitmapindex was
' incremented in the loop but the loop itself failed because the limit was reached
' so all you need to do is write the last cell and set the virtual index at x
' NOTE: if you change this then you have to change the code below that increments
' these as well .
gridBitmap.DrawObject(x, 0, bitmaps[bitmapIndex])
bufferIndex = x

' Ok now put this bitmaps newly drawn region onto the screen
' Like is said you can change the x = 75 to whatever to make it
' appear like it is coming in from outside the screen
Screen.Clear(&hE0DFDFFF)
Screen.DrawObject( 75, 200, gridRegion )
Screen.SwapBuffers()

port = CreateObject("roMessagePort")
Screen.SetPort(port)

running = true
scrollSpeed = 100
lastKey = -1
kp_LT = 4
kp_RT = 5
kp_BK = 0
kp_FWD = 9

while(running)

msg = wait(scrollSpeed, port)

if type(msg) = "roUniversalControlEvent"

index = msg.GetInt()
lastKey = index

'if index = kp_LT or index = kp_RT
if index = kp_RT
' Ok everything was setup in the above paging code so now
' you just increment both indexes, check bounds and wrap if
' needid
bitmapIndex = bitmapIndex + 1
if bitmapIndex >= bitmapCount then bitmapIndex = 0

' When the draw page (soon to come with the code above)
' is called the bufferindex is always positioned at its start
' position. right at the last visible column so you want to
' increment it into the virtual column, but keep in mind
' that the next column becomes virtual because the region will now
' be moved. Picture this as a magnifying glass that is going
' over a piece of paper. The paper stays still but what you
' see in the glass is constantly moving

' Ok increment by columnwidth . You have to wrap around because
' the regions setwrap is on . You must play by the rules for this to work
bufferIndex = bufferIndex + columnWidth
if bufferIndex > bmRegion then bufferIndex = 0

' Ok everything is in order to draw the new bitmap into the virtual
' column. (Soon to be if you like - load from temp and draw)
gridBitmap.DrawObject(bufferIndex, 0, bitmaps[bitmapIndex])

' now scroll that column right into view
ScrollRegion(gridRegion, Screen, columnWidth)

else if index > 100 ' All key ups are value + 100

scrollSpeed = 100

else if index = kp_BK

running = False

end if

else
' The user is holding down the key. So you have to repeat all this
' nonsense again (THUS THE OBJECT). I mean you can put all this
' in a function but once you get used to the object you will never
' go back to the old way. You can play with the speeds here
' to get it to your liking. Once again just right for now
'if lastKey = kp_LT or lastKey = kp_RT

' I threw in a goodie here. If you use the page forward key you can
' see how fast this really is. I really don't expect much of a hit
' from loading one bitmap from temp each time
if lastKey = kp_RT or lastKey = kp_FWD

bitmapIndex = bitmapIndex + 1
if bitmapIndex >= bitmapCount then bitmapIndex = 0

bufferIndex = bufferIndex + columnWidth
if bufferIndex > bmRegion then bufferIndex = 0

gridBitmap.DrawObject(bufferIndex, 0, bitmaps[bitmapIndex])

scrollSpeed = 5
if lastKey = kp_RT
ScrollRegion(gridRegion, Screen, columnWidth, 😎
else
ScrollRegion(gridRegion, Screen, columnWidth, 2)
end if

end if

end if


end while

End Function

' This is the where the nice effect occurs
' You can use many of the Robert Penner's easing functions (THANK YOU ROBERT)
' Bounce them off a tree if you want. This one is the simplest and most frequently used
' Play with the values and adjust them to your liking
Function ScrollRegion(Region As Object, Screen As Object, width As Integer, frames = 16 As Integer) As Void

offset = 0
offdiff = 0
prevset = 0

if frames < 2 then frames = 2

for i = 1 to frames

offset = int(width * i / frames)
offdiff = offset - prevset

if offdiff > 0

Region.Offset(offdiff, 0, 0, 0)

Screen.DrawObject( 75, 200, Region)
Screen.SwapBuffers()

prevset = offset

end if

end for

End Function


' Get some dummy bitmaps for the examle. Of course you would use your own
' Fix the thumb at 100 * 150 just so you can understand how it works
Function GetBitmaps() As Object

number = 120

width = 175
height = 200

clrs = [
&h222835FF,
&h203864FF,
&hAD4F0FFF,
&h324D1FFF,
&h7A0000FF,
]


fontRegistry = CreateObject("roFontRegistry")
font18 = fontRegistry.GetDefaultFont(18, True, False)
bitmaps = CreateObject("roArray", number, False)

j = 0
count = clrs.Count()
textHeight = font18.GetOneLineHeight()
y = int(height / 2 - textHeight / 2)

for i = 0 to number - 1

bitmap = CreateObject("roBitmap", {width: width, height: height, AlphaEnable: false})

bitmap.Clear( clrs[j] )

i_str = i.ToStr()
str_w = font18.GetOneLineWidth(i_str, width)
x = int(width / 2 - str_w / 2)
bitmap.DrawText(i_str, x, y, &hFFFFFFFF, font18)

bitmaps.Push(bitmap)

j = j + 1
if j >= count then j = 0

end for

return bitmaps

End Function



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
squirreltown
Roku Guru

Re: roscreen grid

NewManLiving -Awesome!
Man that is really great, theres nothing like english descriptions of whats going on to help those of us with code-blindness. I will run this and let you know how it goes, thats really generous of you. I shall be back.
Kinetics Screensavers
0 Kudos