Creating a 3d model isn’t a linear experience, you often have to take a step back, or two or ten. However, while extensions adds great power to SketchUp and let the user create better models, they can sometimes put a fork in the process. One of the biggest forks is not keeping the Undo-stack clean. Imagine the horror for the user after experimenting with a new plugin, but realizing that each of the thousands of faces the extension created must be undone manually. What’s worse – the undo-stack doesn’t scale to thousands of items – so it’s impossible to return the model to the state it was at before using the extension.
Extension developers should take great care to test that their extension only adds items to the undo stack when expected – when the user perform an action. Additionally ensuring that any action only adds one operation.
Example
Bad example
1 2 3 4 5 | # Creates 1000 items on the undo stack. model = Sketchup.active_model 1000.times { |i| model.active_entities.add_line([0,0,i], [9,0,i]) } |
# Creates 1000 items on the undo stack. model = Sketchup.active_model 1000.times { |i| model.active_entities.add_line([0,0,i], [9,0,i]) }
Good example
1 2 3 4 5 6 7 | # Creates 1 item on the undo stack. model = Sketchup.active_model model.start_operation("Draw lines") 1000.times { |i| model.active_entities.add_line([0,0,i], [9,0,i]) } model.commit_operation |
# Creates 1 item on the undo stack. model = Sketchup.active_model model.start_operation("Draw lines") 1000.times { |i| model.active_entities.add_line([0,0,i], [9,0,i]) } model.commit_operation
Single Operations
Even if the extension perform only one action it can be worth wrapping it a custom operation – if only to provide a better description for the Undo menu item so the user can have an idea of what the user is undoing.
Tools
Tools that modify the model, such as drawing geometry might need to keep an operation open across Tool events in order to ensure only one operation is created. But beware that any other native function or third party tool might be activated in between so code defensible and try to avoid open operations if possible.
Attributes
It might not be obvious, but writing attributes are operations that adds to the undo stack. One must take as much care in writing attributes as one does adding geometry to the model. For this reason, do not write attributes in observer events or when opening webdialogs – defer it until the user perform an action where it makes sense to write the attributes.
Observers
This could be a topic all of its own. The gist of it is that if you start an operation in the middle of an observer event you are very likely to break the executing operation that triggered the event and break the undo-stack – possibly cause a BugSplat crash.
The current observer system isn’t doing a good job of making life easy for developers. The safest pattern found so far is to defer any model changes with a timer. Use this pattern example as a guide: Safer SketchUp Observer Events. That pattern also ensures that the model changes are appended to the last operation so it all seem as one.
[…] Keep the Undo stack clean (Important!) […]