"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
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
"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.
"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
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
"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