perhaps it’s initializing something on the very first run ever after a reboot – a .NET assembly or who knows what?
You could easily test this by performing a single pasteBitmap with just a single pixel or so outside of the loop, then run the full test?
As for letters – I think there’s a .NET function that lets you grab a given control as a bitmap. If not, you could get a full screengrab and parse that. There’s a function in the Max9+ help on custom label controls using .NET so you can use any font/etc.
At SF we use bitmapped fonts to write text seeing as we’re supporting way back to prehistoric max versions; it’s not too bad, performance-wise, as typically you’re just writing a few words or a single line, and not a complete novel
For my application it seems like the RLE method is fastest since most boxes are unique.
One annoyance is the rollout.bitmap UI element applies a 2 pixel border crop. So the canvas needs to be width+4, height+4to correctly place a box.
The border can be annoying, but if it’s really an issue – use imgTag instead? It doesn’t have a border…
Found a little problem with the RLE approach. It doesn’t work if it runs off the image on the left or right side.
A quick and dirty fix:
fn drawbox canvas: pos: width: height: border:1 bordercolor:black bgcolor:white=
(
rightcrop = (canvas.width-pos.x-width)
if rightcrop > 0 do (rightcrop = 0)
if pos.x < 0 then (leftoffset = abs(pos.x)+1; pos.x = 0) else (leftoffset = 1)
local theBorderLine = for i = leftoffset to (width+rightcrop) collect bordercolor
local theBodyLine = for i = leftoffset to (width+rightcrop) collect bgcolor
for i = 1 to border do
(
if i >= leftoffset and width > rightcrop do
(
theBodyLine[i] = bordercolor
)
if (i-1) <= rightcrop and leftoffset < width do
(
theBodyLine[width+2-i-leftoffset] = bordercolor
)
)
for y = border to height-border-1 do
setPixels canvas [pos.x,pos.y+y] theBodyLine
for y = 0 to border-1 do
(
setPixels canvas [pos.x,pos.y+y] theBorderLine
setPixels canvas [pos.x,pos.y+height-1-y] theBorderLine
)
)
Hi me again.
How do you composite (using paste I presume) without overwriting the old buffer?
example draw backgroundBitmap ‘plate’
imgtag.bitmap = pastebitmap foregroundBitmap BackgroundBitmap
The BackgroundBitmap always gets manipualted and if I try to dump the background into say… a compositebitmap to be modified the backgroundbitmap remains an instance then of compositebitmap?
It’s almost like if you had:
var01 = 25
var02 = var01
var02 = 15
var01 (returns 15)
create a copy of the background bitmap, call this your ‘working’ bitmap
whenever you need to meddle with the ‘working’ bitmap so that it starts with the blank slate of the background bitmap, copy the background bitmap back into the working bitmap.
backgroundBitmap = bitmap 100 100
workingBitmap = copy backgroundBitmap -- one-time only
-- copy backgroundBitmap workingBitmap -- not needed here as we just made a clean copy
setPixels workingBitmap [50,50] #((color 255 0 0))
display workingBitmap
messagebox "red dot"
copy backgroundBitmap workingBitmap
setPixels workingBitmap [10,10] #((color 0 0 255))
display workingBitmap
messagebox "blue dot"
Hey! Whadya know! If I use imgtag instead of bitmap it’ll just give me two layers to work with if the top layer has an alpha channel. Even better.
Thanks for the ‘copy’ tip though. I’ll store that away in my “future use” directory.
yes-and-no… the imgtag itself only has one bitmap… if that bitmap has a particular color and you set that color to be transparent, it will show whatever control is underneath it. So for your background image, you’d need something else to show that – a second imgtag underneath, or a bitmap control, etc.
If you don’t need to read the results back out, then yes – that’s a pretty decent way to do it
try(destroyDialog BoxDrawing)Catch()
global BoxDrawing
global BoxShapes = #()
(
struct BoxShape (pos,width,height,border,bordercolor,bgcolor,active,fg,nhandle)
local Boxobjects = for o in $box* collect o
for o in BoxObjects do
(
append BoxShapes (BoxShape pos:[(o.min.x + (255/2))as integer,(o.max.y*(-1) + (255/2)) as integer] width:(o.width as integer) height:(o.length as integer) border:1 bordercolor:black bgcolor:white active:0 fg:1 nhandle:o.inode.handle)
append BoxShapes (BoxShape pos:[(o.min.x + (255/2))as integer,(o.max.y*(-1) + (255/2)) as integer] width:(o.width as integer) height:(o.length as integer) border:1 bordercolor:black bgcolor:white active:0 fg:0 nhandle:o.inode.handle)
)
)
(
local bitmapX = bitmapY = 255
local keycolor = (color 0 254 0)
local WhiteBitmap = (bitmap bitmapx Bitmapy color:white)
local BlankBitmap = (bitmap bitmapx bitmapy color:keycolor)
local BackgroundBitmap = (bitmap bitmapX bitmapY color:white)
local ForegroundBitmap = (bitmap bitmapx bitmapy color:keycolor)
rollout BoxDrawing "DrawingBox"
(
imgtag BackgroundCanvas pos:[0,0] width: bitmapX height: bitmapY transparent:keycolor bitmap:BackgroundBitmap
imgtag ForegroundCanvas pos:[0,0] width: bitmapX height: bitmapY transparent:keycolor bitmap:ForegroundBitmap
timer clock "maxscriptdemoclock" interval:1000
fn drawbox canvas: pos: width: height: border:1 bordercolor:black bgcolor:white =
(
rightcrop = (canvas.width-pos.x-width)
if rightcrop > 0 do (rightcrop = 0)
if pos.x < 0 then (leftoffset = abs(pos.x)+1; pos.x = 0) else (leftoffset = 1)
local theBorderLine = for i = leftoffset to (width+rightcrop) collect bordercolor
local theBodyLine = for i = leftoffset to (width+rightcrop) collect bgcolor
for i = 1 to border do
(
if i >= leftoffset and width > rightcrop do
(
theBodyLine[i] = bordercolor
)
if (i-1) <= rightcrop and leftoffset < width do
(
theBodyLine[width+2-i-leftoffset] = bordercolor
)
)
for y = border to height-border-1 do
setPixels canvas [pos.x,pos.y+y] theBodyLine
for y = 0 to border-1 do
(
setPixels canvas [pos.x,pos.y+y] theBorderLine
setPixels canvas [pos.x,pos.y+height-1-y] theBorderLine
)
)
fn CompositeCanvas bgcanvas fgcanvas =
(
pasteBitmap fgcanvas bgcanvas (box2 0 0 fgcanvas.width fgcanvas.height) [0,0] type:#blend
)
fn drawbg shapearray canvas =
(
for b in shapearray do
(
if b.fg == 0 then
(
drawbox canvas:canvas pos:b.pos width:b.width height:b.height bgcolor:blue
)
)
)
fn drawfg shapearray canvas =
(
for b in shapearray do
(
if b.fg == 1 then
(
drawbox canvas:canvas pos:b.pos width:b.width height:b.height bgcolor:green
)
)
)
on clock tick do
(
ForegroundBitmap = copy blankbitmap
drawfg boxshapes foregroundBitmap
ForegroundCanvas.bitmap = ForegroundBitmap
)
on BoxDrawing open do
(
foregroundbitmap = Blankbitmap
backgroundbitmap = Whitebitmap
drawbg boxshapes backgroundBitmap
drawfg boxshapes foregroundBitmap
BackgroundCanvas.bitmap = BackgroundBitmap
ForegroundCanvas.bitmap = ForegroundBitmap
)
)
createDialog BoxDrawing (bitmapX+30) (bitmapY+100)
)
Ok had a little bit of free time again to work on this.
It works. But it still flickers… even set at an interval of 5000. How to I get it not to flicker? It can’t be a processing limitation? Flicker was the whole point of this endeavor.
Do I have a memory leak somewhere that’s causing it to hang no matter how fast the processing is?
Based on previous benchmarking it should be able to draw more than 1000 boxes a second.
only a color, I’m afraid… alpha would have been fun, but alas
Note that if you go back to the pasteBitmap option, you can tell it which bitmap’s alpha channel to use in the composite.
Oops I accidentally hit Edit instead of “reply” to my previous comment. See above. Is there like a V-Sync or equivalent step I’m missing?
Edit: I just benchmarked the tick code and it took ‘0’ so that should be fast enough for 1000ms refreshrate.
Oh and the onload should probably be
Foregroundbitmap = copy Blankbitmap
Backgroundbitmap = copy whitebitmap
Edit2: worse still if I put:
ForegroundCanvas.bitmap = ForegroundCanvas.bitmap
in the ‘on clock tick’ code it still flickers.
So ‘bottleneck’ seems to be in updating the imgtag irregardless of box drawing. Would I get better luck from an alphaless precomposited imgtag?
Edit3: To answer my own question: Yes and no. No if there is no overlay/compositing it does not stop flicker. Yes. It is a problem with Imgtag. IMGTAGs I guess flicker on update. BITMAP UI elements it seems do not.