Paint program help - drawing rectangles, restoring

BlitzMax Forums/BlitzMax Beginners Area/Paint program help - drawing rectangles, restoring

Wellmt(Posted 2006) [#1]
I'm trying to write a simple drawing program like MS-Paint, just to learn Blitzmax. I'm a bit stuck though.

Imagine the user has drawn a load of stuff on the screen. Now the user draws a rectangle by clicking and dragging the mouse button. As the user moves the mouse with the button down, the rectangle can grow or shrink until the button is released.

I can draw the rectangle fine but how to I restore the stuff behind the rectangle if the user shrinks the size of the rectangle? I've tried copying the whole screen into a buffer and restoring that before redrawing the rectangle but it doesn't seem to work.

Is this the best approach?

(I'm using regular Max2D functions)

Thanks


tonyg(Posted 2006) [#2]
I'm guessing you're not using cls.
How about...
1) cls
2) Draw background
3) Draw rect
4) loop to 1)
When the mouse is released for drawing the rectangle then make that part of the background.


CS_TBL(Posted 2006) [#3]
I wonder whether restoring a part of the screen (where you're editing) is more clever. I recently made some testprogram which had a 512x512 canvas, drawing an even larger image on it with some selector rect over it @ event x/y. The movement was quite slugish, caused by redrawing the whole image again and again..

(98se, amd 2ghz, geforce4mx)


Wellmt(Posted 2006) [#4]
Thanks for the replies:

tonyg

That's neat and you're right I'm not using CLS. Practically I can't find a way of storing the background before the rect is being drawn, which is kind of my problem. Should I just store the whole canvas into a buffer and then re-store the canvas in the buffer after the mouse is released?


so

1. CLS
2. Draw contents of buffer on canvas (DrawImage)
3. Draw rect
4. Flip
5. Loop to 1

When mouse is released store canvas using GrabImage. on a hires screen that can be a massive canvas to grab and draw each loop.

Thanks


ImaginaryHuman(Posted 2006) [#5]
There is no point considering only restoring the part of the screen which you are `uncovering` by shrinking the rectangle, because with every frame, the entire backbuffer is wiped or relocated and basically does not keep its contents. After every Flip you have to completely redraw the entire screen anyway, so trying to only restore the part that changed won't save you any time. That technique would have been useful if the backbuffer were being kept, or if you were rendering it in main memory with custom drawing routines, but with the way Max is set up using OpenGL there is no point.

As was mentioned, you start off, draw stuff, grab it into an image, then use that same image for the duration of scaling the rectangle - each frame draw the whole screen image, draw the rectangle at the appropriate size, then flip. That's all.

If you do away with the backbuffer, which may be a possibility, and render directly to the `front` buffer, it might possibly be useful to preserve some of the background and restore only the parts being seen. It's questionable whether you really need a double buffered system for a paint program.


Wellmt(Posted 2006) [#6]
OK thanks everyone. I got it working - well under Windows anyway. It seems I had it working already, I just didn't know it as there seems to be a bug in the Blitzmax Linux version. The same code works under one OS and not the other.

Thanks again for your help.

I'll post the code here just incase anyone can spot the problem. It's the drawimage line with the *** comment ** that causes problems under Linux, an exception error occurs.

-------- cut here ----------------------------

Strict

' ------------ vars --------------------
' Screen res
Local screenwidth=800
Local screenheight=600

' Mouse coords
Global ox,oy, mx, my

' shape
Local width, height

' Colour
Global red, green, blue

' types of tools
Const PEN=1, RECTANGLE=2
' current tool
Local currenttool = PEN
' holds current keypress
Local key


'set graphics mode
'Graphics screenwidth,screenheight,16
Graphics screenwidth,screenheight,0

' set a buffer up big enough to hold the whole screen (so we can restore the image during drawing ops such as rectangle
Local screenbuf:timage = CreateImage(screenwidth,screenheight)


' ------------ main loop --------------------

red = 255
green = 100
blue = 100

'set the default colour
SetColor (red,green, blue)

' take an initial snapshot of the canvas
GrabImage screenbuf,0,0

While Not KeyHit(KEY_ESCAPE)


' See if key has been pressed or a tool clicked on
key = GetChar()

Select key
' p or P pressed, PEN mode
Case 80
currenttool = PEN
Case 112
currenttool = PEN
' r or R pressed, RECTANGLE mode
Case 82
currenttool = RECTANGLE
Case 114
currenttool = RECTANGLE
End Select


'update previous mouse coords
ox = MouseX()
oy = MouseY()

' Left mouse button pressed
While MouseDown(1)

' Get mouse coords
mx = MouseX()
my = MouseY()

Select currenttool
Case PEN
'Plot a pixel
Plot mx,my
Case RECTANGLE
' draw a rect
width = mx-ox
If width < 0 Then width = 1
height = my-oy
If height < 0 Then height = 1
Cls
' **** comment/uncomment this next line for a crash under linux *****
DrawImage screenbuf ,0,0,0
DrawRect(ox,oy,width,height)
End Select

' Flip the buffers
Flip

EndWhile

Select currenttool
Case RECTANGLE
' take a snapshot of the screen proir to the next draw operation if drawing rects, ovals etc
GrabImage screenbuf,0,0,0
End Select

' end of main loop
Wend