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

Re: roscreen grid

NewManLiving - That works really really well, I dropped it into the slot it will go in in my channel and Voila! Grid!. Amazing.

The row works every bit as well as the stock grid, I'll be curious to see if Marks warning about performance will come into play once I get the graphics in there, but it sure smokes now. The descriptions are great - Its just so unusual to have something like that - Theres nothing like having a map when you are in the middle of the wilderness.

Now- give me a day to tinker with it. There are a lot of individual concepts to absorb here so I want to get a grip on it so I can ask intelligent questions. It seems you enjoy helping others, and you have been completely successful with that here, and I'm extremely grateful for that.
Kinetics Screensavers
0 Kudos
NewManLiving
Visitor

Re: roscreen grid

ok but you only have part of it, but that is enough to chew on. also the line
gridRegion = CreateObject("roRegion", gridBitmap, 0, 0, bmRegion - margin, height)
I snip off the end margin (bmRegion - margin) for a clean cutoff on the scrolling otherwise the margin scrolls in giving an unbalanced look

Now how do you create a virtual grid? I will give a hint based upon my most recent post in Wisdom: 1 + 1 = 2
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
NewManLiving
Visitor

Re: roscreen grid

Just a note
What Mark is dealing with is a much more difficult problem.
Memory management which plagues all of us. In the grid row
Example all the bitmaps are still loaded into memory
This evaporates very quickly. You will reach your limit
If you do not provide a means to cache. Now for you
If 120 is fine at that bitmap size then good. But as I suggested
I would go further and remove that serious limitation
Thee grid row is an elegant way to display your data quickly
But it manages memory only in part. However because of its
Design it is very reasonable to expect a resolution using a combination
Of memory and disk cache.
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

I've organized the row with my own thumbnails and titles/info below them and changed it to 5 pages across. I'm working with a list of 60 items. I was wrong about the number - its 100 max total, which will be organized into 5 rows, so there are a lot of dupes across the rows, but it looks like I should be able to keep those 100 as bitmaps in memory at the same time ( i think), each cell is 224 x 200.
The next thing I'm going to do is try to make the row scroll left. I'm slowly getting what each part does, and that should be good hurdle to get over.
The row still scrolled really fast and smooth until i added two small graphics - a logo and a menu icon, and a piece of text, the row title. Those really kill the high-speed part of the motion, scrolling one at a time is unaffected though.
Before I get to the multiple row part I will need to work out a downloading strategy. Right now its d/ling everything to temp before it starts, which takes too long. The row will have to be able to add bitmaps as they become available and I'll have to be creating them in a loop of some sort as the thing starts up. Closing the page and re-opening it is acceptable since the files are already in tmp:, and it takes a few seconds to create the bitmaps.
It was pretty cool to see a grid row as I originally wanted it almost a year ago, on a white background with text under the grid items - something thats not possible with the stock grid. Just like being able to have cross-fades in the slide show, there are certainly benefits to all the extra work that the 2D API is.
Kinetics Screensavers
0 Kudos
TheEndless
Channel Surfer

Re: roscreen grid

"squirreltown" wrote:
and a piece of text, the row title. Those really kill the high-speed part of the motion

Make sure you're re-using your font. Initializing the font is a very expensive operation, so you only want to do it once, if possible.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
NewManLiving
Visitor

Re: roscreen grid

The biggest hurdle to cross is thinking about application design. Take a look at the ROKU home screen. They could if they wanted to, put everything in one big grid
and segregate them by title, such as you see in the stock grid screens.
However, they do not. What they do is use a list to the left and grid on the right (after that its whatever, but anyway) This helps them segregate the data into separate
logical menu units which may be attached to a grid and/or other components when needed. If you have data redundancy in your grid then your design needs to be re-evaluated.
Another type of menu/grid/design that I use mimics the home screens. I find that to be a good way to segregate my data and help me to manage downloading and a cache. My grids like the home screen grids are more row based than column

When you say that you added this and that, what exactly do you mean? Your gridrows should have nothing to do but display a completed bitmap. If you are writing something over the bitmaps then you need to do that before you even show the grid. In the case of the virtual cell then everything should be ready to go. I do this myself in my audiobooks. They have different skins but I don't include
the skins with the graphics. However I do prepare the skins, fonts, and even their x,y positions (if the text is centered such as my book titles) among other things before I show the grid. I keep all this info in a data-definition container which is an array of associative arrays, much like the meta-data that many of the stock components
use. The grid does not care what kind of array it is using. It increments all arrays the same way. However in the drawing functions you have to split it up



bitmapDesc = bitmaps[bitmapIndex]

gridBitmap.DrawObject(bufferIndex, 0, bitmapDesc.bitmap)
gridBitmap.DrawText( bitmapDesc.Text, bitmapDesc.x, bitmapDesc.y, bimapDesc.Color, bitmapDesc.Font)



Also if your bitmaps have no transparency in them your better off in most cases to convert them to jpg instead of png if you have not done so already they are much smaller. Be a little more specific or send me a private message with code and I will take a look at it. No sense cluttering up things here
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

Thanks Endless, good tip.

edit- Thats more than a good tip, made a huge difference, the row scrolls fast again.
Kinetics Screensavers
0 Kudos
NewManLiving
Visitor

Re: roscreen grid

Here is the completed code for left/right scrolling. Some things have changed so if you are going to use it replace the entire example.
I tested it with page sizes of 1 to 5 and everything appears ok. But my messy apartment and my dirty laundry are staring at me. Anyway
test it thoroughly before using it - I believe it is solid as commented. All this is taken from my framework but put in a format more easy to read.
and understand . It is a top-down approach using no user-defined objects. ( And you know this is not my style). But it really makes it easier to
understand. You can then create your own object and isolate the redundancies




' Ok this is an updated version that shows how to page swap the indexes. The concept here is
' 1 - When a page is written it is always going forward so both indexes are resting above
' the next index increment. So if you are incrementing forward all you have to do is increase
' by one position. However, if the user decides to move in the opposite direction then you
' have to flip everything by a pagesize (number of bitmaps visually seen in the dataindex)
' (regionsize for the virtual cell index). Picture a dog chasing it's tail. The bitmap is
' stationary but the region is moving frantically back and forth over the bitmap looking to catch and empty
' virtual cell. But the cell is smart and is always running in front or in back one step
' ahead. So when a transition is made from one direction to the other then you have to flip
' I did not comment too much I really have things I must get done. Any questions
' or mistakes let me know and I will fix them. All this stuff is already in my framework in a
' different but (functionally the same) format so it will be easy to see where the mistake is and correct it

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 100 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 = 224
height = 200
' If you don't want to use a margin set it to 0
margin = 15

' 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

' I would not go much beyond this. Also if your data is less than the page size
' you have to make adjustments yourself (see my virtual list view example in 2d api wisdom)
' This examle is fixed to show how to create a virtual cell. Error checking is your business
' I have tested page sizes from 1 to 5
pageSize = 5
' 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
pagingRight = True

' 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( 50, 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
kp_REV = 8

while(running)

msg = wait(scrollSpeed, port)

if type(msg) = "roUniversalControlEvent"

index = msg.GetInt()
lastKey = index

if index = kp_LT or index = kp_REV
'Ok added a flag to indicate what direction the user is going in
'Since an adjustment needs to be made only once you want to keep that
'in the else portion of you statement not on the top (think speed, speed, speed)

' In this case the page adjustment was made (under the else) and the flag was set
' so if we are not pagingRight then we must be pagingLeft
if not pagingRight

bitmapIndex = bitmapIndex - 1
if bitmapIndex < 0 then bitmapIndex = bitmapCount - 1

bufferIndex = bufferIndex - columnWidth
if bufferIndex < 0 then bufferIndex = bmRegion

else
' Otherwise the user was formally paging right so we have to flip and set the flag
bitmapIndex = bitmapIndex - pageSize
if bitmapIndex < 0 then bitmapIndex = bitmapCount + bitmapIndex

bufferIndex = bufferIndex - bmRegion
if bufferIndex < 0 then bufferIndex = bufferIndex + bmRegion + columnWidth

pagingRight = False

end if

gridBitmap.DrawObject(bufferIndex, 0, bitmaps[bitmapIndex])
ScrollRegion(pagingRight, gridRegion, Screen, columnWidth)

else if index = kp_RT or index = kp_FWD

' Just read the top and apply the opposite
if pagingRight

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

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

else

bitmapIndex = bitmapIndex + pageSize
if bitmapIndex >= bitmapCount then bitmapIndex = bitmapIndex - bitmapCount

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

pagingRight = True

end if

gridBitmap.DrawObject(bufferIndex, 0, bitmaps[bitmapIndex])
ScrollRegion(pagingRight, 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 or periodically
if lastKey = kp_LT or lastKey = kp_REV

bitmapIndex = bitmapIndex - 1
if bitmapIndex < 0 then bitmapIndex = bitmapCount - 1

bufferIndex = bufferIndex - columnWidth
if bufferIndex < 0 then bufferIndex = bmRegion

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

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

else 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(pagingRight, gridRegion, Screen, columnWidth, 😎
else
ScrollRegion(pagingRight, 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(goRight As Boolean, 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

if not goRight then offdiff = -offdiff

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

Screen.DrawObject( 50, 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 = 100

width = 224
height = 200

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


fontRegistry = CreateObject("roFontRegistry")
font32 = fontRegistry.GetDefaultFont(32, True, False)
bitmaps = CreateObject("roArray", number, False)

j = 0
count = clrs.Count()
textHeight = font32.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 + 1).ToStr()
str_w = font32.GetOneLineWidth(i_str, width)
x = int(width / 2 - str_w / 2)
bitmap.DrawText(i_str, x, y, &hFFFFFFFF, font32)

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
TheEndless
Channel Surfer

Re: roscreen grid

"NewManLiving" wrote:
Also if your bitmaps have no transparency in them your better off in most cases to convert them to jpg instead of png if you have not done so already they are much smaller.

This is only true with regards to channel size and/or network transfer. JPGs and PNGs of the same dimensions use up the same amount of video/graphics memory (roughly width * height * 4 bytes per pixel) regardless of file size.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
NewManLiving
Visitor

Re: roscreen grid

"TheEndless" wrote:
"NewManLiving" wrote:
Also if your bitmaps have no transparency in them your better off in most cases to convert them to jpg instead of png if you have not done so already they are much smaller.

This is only true with regards to channel size and/or network transfer. JPGs and PNGs of the same dimensions use up the same amount of video/graphics memory (roughly width * height * 4 bytes per pixel) regardless of file size.


Yes, I was thinking about size and it's impact on downloading. But a 200*200 bitmap is exactly that. To prove your point all you have to do is open a telnet with the r2d2_bitmaps command and observe the examples test bitmaps. So obviously there has to be a caching method to compliment the grid row for best results. Loading all
the bitmaps is somewhat defeating to the virtual concept. But as you know caching can be done. And, with the single cell update displaying data is very quick. Since I employ the compositor I can have virtual components under the zorder that accept data as it arrives and just swap themselves out.
But I am a little nervous about using temp since I can never be sure how much space is available. In my opinion, since caching data is unavoidable, there should be at least
a fixed amount guaranteed for the developer. I recall from another post that you said to find out how much just write some files until failure. I have not looked at
roFileSystem yet but you probably have. There must be a better way to determine space in the temp. Have you investigated the file system component for this purpose?
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