• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM "undo" function for "paint" app

A

Adam Martinez

Guest
Hello. I'm currently making a paint app (like Mario Paint) and am trying to create an "undo" button for the user to remove the last thing that they drew (draw_line, draw_circle, etc.)

I'm using surfaces with a white background.

My first idea was to use a temporary surface that the player draws onto, and then copy it on top of a more permanent surface (part of the overall drawing/painting the player is making) at the right time, then "clearing" the temporary surface with a huge white sprite.

//when the player starts drawing a new line, the old line is copied from the temporary surface to the permanent surface, and the temporary surface is cleared blank with a huge white sprite, ready for the player to draw a new line
if mouse_check_button_pressed(mb_left) {
surface_set_target(surface)
surface_copy(surface,0,0,preliminary_surface)
surface_reset_target()
surface_set_target(preliminary_surface)
draw_sprite_ext(spr_white_surface,0,0,0,1,1,0,0,0)
surface_reset_target()
}

I think this isn't possible because there's no way to "draw" a surface on top of another surface... the temporary surface will just replace the permanent surface. And... I think for some reason, this code isn't working because my "eraser" tool which draws white circles onto the permanent surface now has no effect. Something is wrong.

My second idea was to use the file handling, but I don't know how to use file handling to save a series of lines and circles drawn between a mouse_check_button_pressed() and mouse_check_button_released().

Any ideas how to make this "undo" function work?

Thank you!
 
I

Insanebrio

Guest
Try saving the old surface into a sprite, than add the new drawing. When you undo, remove all from the surface and than draw the sprite on it.
 
R

renex

Guest
In my editor, I save the main drawing surface to a buffer after every edit action. To make undo work, All I have to do is keep old copies of the buffer on a queue and phase out the older ones to file when it gets too big. Then I can throw those buffers back to the main surface as needed.

It's also convenient for when the the OS decides to chew on your surfaces. You'd lose the drawing otherwise...
 
A

Adam Martinez

Guest
Try saving the old surface into a sprite, than add the new drawing. When you undo, remove all from the surface and than draw the sprite on it.
I'm going to try this right now, thank you!
 
A

Adam Martinez

Guest
In my editor, I save the main drawing surface to a buffer after every edit action. To make undo work, All I have to do is keep old copies of the buffer on a queue and phase out the older ones to file when it gets too big. Then I can throw those buffers back to the main surface as needed.

It's also convenient for when the the OS decides to chew on your surfaces. You'd lose the drawing otherwise...
I haven't use buffers yet, but need to learn. I only know that surfaces are volatile but have nothing in place to prevent my game from crashing. I will look at this next, thank you!
 
D

daprato

Guest
I'm interrested also renex to know more about playing with buffers, I thought about the same of Insanebrio, creating sprites backups.
 
R

renex

Guest
I'm interrested also renex to know more about playing with buffers
Creating a sprite from a surface is slower than getting the surface into a buffer. You can also make more copies of the buffer without spending video memory.

upload_2017-2-18_15-15-20.png

The buffer size required for a surface backup is width * height * 4. That's because the BGRA colorspace is 32 bits so it uses 4 bytes per pixel.

Then you can just get and set as required. The extra arguments on those functions control simple truncation.
upload_2017-2-18_15-12-2.png

upload_2017-2-18_15-12-14.png

I save a backup after every draw command is processed in my editor. Currently, it's only saving one copy, but I'll be implementing a cache later for file-backed infinite undo. Buffers are fast to save to file.
 
R

RealityShifter

Guest
Creating a sprite from a surface is slower than getting the surface into a buffer. You can also make more copies of the buffer without spending video memory.

View attachment 7069

The buffer size required for a surface backup is width * height * 4. That's because the BGRA colorspace is 32 bits so it uses 4 bytes per pixel.

Then you can just get and set as required. The extra arguments on those functions control simple truncation.
View attachment 7067

View attachment 7068

I save a backup after every draw command is processed in my editor. Currently, it's only saving one copy, but I'll be implementing a cache later for file-backed infinite undo. Buffers are fast to save to file.
This helps a lot. Thanks.
 
Top