Undo Logic – Implementing Undo for Painting on a Canvas

canvaslogic

I'm working on a module that allows users a basic paint function. I want to support undoing any modifications done to the painting surface. Assuming that we have one layer (for the sake of simplicity), what is a reasonable way to store painting done so they can be undone?

An idea I had was to encapsulate draw events as a kind of Undoable object. If someone presses, draws, and releases, the new data added would be contained in an object of what actions were carried out. This event might contain something like "color ARBG of size X at [array of points the user dragged over]".

I'm unsure of this being the optimal way to do it. If there's a lot edit commands done, my logic here would be to rewind back to the beginning and then re-apply every 'edit' done to the scene, render and display, without the UI becoming laggy (excluding fringe cases).

Is this feasible? Is there a better/more optimal way? This is the first time I've attempted such a thing and I'd like to make sure I'm going to learn the best way I can do it.

Note: My goal is not to use any libraries and handle this through my own coding.

Best Answer

Simplest method? Just limit the undo buffer size. Like you only allow the last 20 actions to be undone and keep a copy of the state 20 actions ago.

If you undo then there will be 19 actions in the undo buffer and redoing those is simpler than all since the beginning.

However extending from that you can keep copies of the state every X actions. This is the same idea of diff backups in databases, every month a full backup is done then a daily diff is taken. Then when needing to restore you just need to grab the latest full backup and reapply the diffs stored from that last backup on.

Related Topic