With larger image sets, and to take full advantage of region-offsetting as opposed to bitmap coordinate offsetting, You need to understand the concept of a virtual buffer. The following example is a much earlier version of the grids I build today. But the concept of a virtual buffer is the same. For the final step, when you have more bitmaps then can fit it memory you can introduce the texturemanager into the grid. This adds a whole new level of complexity but it is doable.
' 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 )