Undo is a system by which users can reverse particular actions which they have already taken. This is related to Redo, where those reversed actions are performed again.
Objects Utilized in Undo
Undo Op
The Undo Op (shorthand for Undo Operation) is the smallest part of Undo. An Undo Op is a single instance of change at the developer level. A particular value changing its state is an example of an Undo Op.
Undo Step
The Undo Step represents the entirety of what is changed from a user's perspective. Undo Steps are broken down further into Undo Step Types:
- Select - References a new selection (either group or singular selection depending on the work mode)
- Move - An automated move done by a non-user action.
- Move2D - A move done by a user in 2D.
- Move3D - A move done by a user in 3D.
- Insert - The insertion of a snapper.
- Remove - The removal of an object (most likely a snapper)
- Modify1 - The modification of a field on an object.
Another type of Undo Step, the Serious Undo Step, will be discussed later on.
Undo Chain
Undo Steps are made of Undo Ops, and similarly, the Undo Chain is comprised of Undo Steps. The Undo Chain records the string of user actions, through a set of Undo Steps. The Undo Chain contains all information used for the Undo System. held within the Undo Stack and Redo Stack.
Undo Stack
The Undo Stack is a sequence of Undo Steps stored on the Undo Chain that (initially) contains all relevant information within the Undo System. As users undo actions, reversed versions of the steps are added to the Redo Stack. We will discuss this in more detail later.
they begin to "go up" the chain. "Going Up the chain puts the current "state" of the world back to a particular instance of time, and adds the Undo Step that was just performed to the Redo Stack. We typically think of the current state undo of the World as being a "position" in the Undo Chain. The user's current "position" in the "Undo Chain" is always at the end of the current Undo Stack, and before the Beginning of the Redo Stack.
Redo Stack
The Redo Stack is another sequence of Undo Steps recorded on the world. The Redo Stack contains reversed versions of the Undo Steps in the Undo Stack. The Redo Stack only appears when a user begins to Undo actions they have taken, but before new Undo Steps are recorded. This is because as new undo steps are recorded, the Redo Stack is flushed.
Functionality of Undo
How Does the “Undo” Button Operate?
When a User Presses "Undo" the last Undo Step in the Undo Stack is reversed. Each Undo Op in the stack is reversed one by one and applied to undo the programmatic parts of the Undo Step. These reversed Operations are stored in another Undo Step and then placed in the "Redo Stack."
When we talk about the Undo Chain we refer to a "position" in the chain. Such a position is truly just the point after the Undo Stack, but before the Redo Stack. For simplification purposes in debugging, we consider these to be the same "stack" with the user's "position" between the two (always after the end of the Undo Stack and before the Redo Stack).
A Simple Example
We Perform the following steps
- Insert a Fika Panel
- Insert a second Fika Panel connected to the First
- In any .cm file, add the following code:
mainSpace.world.undoChain.debug()
- Run the file with the code shown. You will see the Undo Chain's debug print out with the current position at the end of the chain.
Note the "Current position" Marker at the end of the print out from the "debug" method.
- Undo once (by pressing the Undo button or using the hotkey).
- Run the debug code again. Note the New "Current Position" Amongst the Undo Stack.
- Repeat Steps 5 and 6 Until you reach the "Top" of the Undo Stack.
- Redo (Ctrl + Y or press the "redo" button) until you replace the first panel. Press Ctrl + Y once, this should redo the last step taken.
Note how the Redo puts us back in the same "position" as we were in step 6.
Serious Undo Steps Vs Undo Steps
The above applies most recognizably to UndoSteps but not as much to a SeriousUndoStep. A SeriousUndoStep is an UndoStep that takes a snapshot of the relevant part of a space both before and after some event.
SeriousUndoSteps do this by using a pair of Snapper{} to hold all the relevant information. These Snapper{} are copied both before and after the operation in question. SeriousUndoSteps are best used when the number of UndoOps generated by a normal undo step is very large, when the number of snappers affected by an operation is very large, or when both of these things are true.
Recording for Undo
UndoSteps of any kind has to be recorded. If you are new to recording your new undo steps you may be unknowingly taking advantage of the recording types that are already taking place. To record an UndoStep the two following methods on world are used to start UndoRecording:
extend public void beginUndoStep(SrcRef src=#:src)
extend public void beginUndoRecording()
Then the action is taken. Followed by closing the UndoStep with the following methods on world:
extend public void endUndoRecording()
extend public void endUndoStep(str description=null, str key=null)
Keep in mind that the description passed into endUndoStep is visible by users, so it should have an rs entry. You can see the description in the tooltip of the undo button.
More Information
This article represents the basics of the Undo system. There is more information presented in the How to Debug Undo article.
Comments
0 comments
Please sign in to leave a comment.