Structure of an undo command

Started by
6 comments, last by Drastick 20 years, 6 months ago
I am laying down the framework for my level editor and I want to have an undo command...possible keep track of the undos for a few changes back. My problem is that I have never done this and my only idea seems very bute force...I don''t care too much but I would not mind some input from others. My idea was to just save the entire state before each change and if there is an undo command I would just rollback to the previous state. It just sounds like a big load on the program to make after every change. I want to have an idea how this is going to work before anything else is done.
Advertisement
Like you, I've never done an undo-commmand.

However, your solution seems fine for me, if your level-data structure isn't huge i.e. if your working on a highdetail-3d editor.

It would be quite easy to have a std::vector in which you push_back the adress of a copy to the leveldata strucutre before you change it. When the number of elements in the vector is bigger than 10 for instance, you just delete the oldest structure and then pop the adress from the vector.

If the user wants to undo, you just copy the newest structure in the vector to your leveldata structure and pop it.

[edited by - Enselic on October 14, 2003 6:08:07 AM]
[s]--------------------------------------------------------[/s]chromecode.com - software with source code
I would not save the entire state, but only the changes the user made. since you allways have the current state, you could easily undo the last change and restore the previous in this way.
this solution is by far less memory consuming, since you are only saving little events (the user changes) in your undo-list, rather than the entire state.
Yeah I definiatly would not store the whole level state, especially if you want to go back a few undos.

Instead, work out a system of logging user input, and how to reverse these changes.

ie:
Vertex #145 gets moved (19,20,0)
so to undo that, move Vertex #145 (-19,-20,0)

or
Face #9 changes color from (255,255,0)
so to undo, change its face back to that color.


Never done an undo myself, but I imagine that would be the way to do it.
The ultimate would ofcourse be save only what the user does and then reverse this on an Undo-event.

There's a problem though, and that is implementation... Could you develop your posts to HOW you would implement this? Cause in a level editor you probably want to be able to do more than just moving vertices around. And having one 'reverse'-technique for every possible thing that can happend isn't smooth either.

[edited by - Enselic on October 14, 2003 10:06:09 AM]
[s]--------------------------------------------------------[/s]chromecode.com - software with source code
There''s a design pattern that might help you known as the Command pattern.

Basically, it''s a way of wrapping up a user action (delete, new object, change object, etc etc) in an object, and then sending it to a ''reciever'' (an object in the level, the level itself, or whatever). You fill out a Command object, and pass it to an Execute() method on the reciever.

If you track the last 5 or so command objects, and make your receivers supply an UnExecute() method as well, then you have the beginnings of an undo mechanism. The big question is how much data you need to store to be able to both do and undo an action.

Superpig
- saving pigs from untimely fates, and when he''s not doing that, runs The Binary Refinery.
Enginuity1 | Enginuity2 | Enginuity3 | Enginuity4
ry. .ibu cy. .abu ry. dy. "sy. .ubu py. .ebu ry. py. .ibu gy." fy. .ibu ny. .ebu

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

the simplest way to make undo possible for any sort of task is simply storing the state before. not the whole, but only the part that get affected..

means if you delete a sphere, you save it in the undo-command-chain, and a "delete it", behind it. and then you can undo it by just skipping back over the "delete it", placing the sphere into the scene again..



If that''s not the help you''re after then you''re going to have to explain the problem better than what you have. - joanusdmentia

davepermen.net
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

Sorry, only just read Enselic''s post.

You''d probably want a different subclass of CCommand for each action the user can perform - CMoveCommand (which can be sent to objects, vertices, whatever), CColorCommand (for example), CChangeTextureCommand, etc. You can then store the original and desired states in each command object, saving on space (because you''re not copying the entire thing) but still allowing for Undos.

Then you''d need a way of recognising what type of command something is - given that a CVertex could probably receive a number of commands, it''d have to receive a CCommand pointer and then dynamic_cast<> it to the correct type, depending on what it actually is.

For that, you could just use a simple GetCommandType() function in the base CCommand class, which returns a value (CMD_MOVE, CMD_COLOR, CMD_CHGTEX, etc) so that the command''s type can be identified.

Superpig
- saving pigs from untimely fates, and when he''s not doing that, runs The Binary Refinery.
Enginuity1 | Enginuity2 | Enginuity3 | Enginuity4
ry. .ibu cy. .abu ry. dy. "sy. .ubu py. .ebu ry. py. .ibu gy." fy. .ibu ny. .ebu

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

This topic is closed to new replies.

Advertisement