Closed cvetan5 closed 11 years ago
@cadaver could you give @cvetan5 a shout when you will be cheking this out so he can merge rex/tundra2 to it.
Should be next week, after checking the noboost pull request.
Looks good. After merging, I'll file an enhancement ticket for also recording transform gizmo actions as undo commands.
An Undo / Redo stack manager for EC / Scene editor. It utilizes the Undo framework classes by Qt that implement the command pattern. All actions i.e. commands from EC / Scene editor (excluding pasting content, importing scene(s) and converting local entity to replicated and vice-versa) are represented by a QUndoCommand-derived class. The undo manager manipulates the QUndoStack and the UI elements i.e. undo and redo tool buttons with two QMenus which contain 5 recent commands that had been done (Undo menu) or undone (Redo menu). A QUndoView is provided to view the contents of QUndoStack, and to walk through them if needed. A helper class called EntityIdChangeTracker is used to track IDs of entities that had been deleted / re-added in an EC / Scene editor lifetime, and also to track acknowledging of new created entities so it can keep their valid replicated ID. The reason I did this is that I don't think it is smart to use old entity IDs to redo a "delete entity" action (and for some reason it does not work for replicated entities).
Workflow:
QUndoStack calls
QUndoCommand::redo()
of the QUndoCommand that had been pushed, except whenEditAttributeCommand<T>
is pushed, where the old attribute value must be stored before setting it to the new value (there is a workaround there to avoid callingredo()
upon pushing). The UI is updated;2.1. If for example, a command that will cause a change in the target entity's ID has been pushed, its ID is tracked with EntityIdChangeTracker;
UndoManager::Undo()
is called, QUndoStack callsQUndoCommand::undo()
of the topmost command from the stack. The index is changed to point to the next command that will be undone on the nextundo()
call. The UI is updated;If, for example. 4 commands are undone i.e. the index is changed back by 4, QUndoStack calls
QUndoCommand::undo()
repeatedly until the desired index is reached. The UI is updated;4.1. In the event that a new command is pushed onto the stack, commands that can be redone are removed from the stack and destroyed; 4.2. Entity IDs are retrieved by recursively walking through EntityIdChangeTracker's maps
Known drawbacks:
Color
attribute results in two commands pushed with same values. This is fixed by merging twoEditAttributeCommand<Color>
instances that have the same values.Possible drawbacks:
Scene::EntityAcked(Entity*, entity_id_t)
signal might come late and the tracker will fail to store the acked ID of an unacked entity, thus resulting in a broken undo stack (the undo command will not be able to retrieve the entity ID and undoing / redoing will not have effect)Most of the code for the commands is reused and moved to the appropriate
QUndoCommand::redo()
method. I would greatly appreciate if you guys test this and give me any notes on this.