Hi there, I’m making an extension that observes the model’s changes. I’ve noticed that for certain actions, onChangeEntity (from EntityObserver) and onElementModified (from EntitiesObserver) are not fired when the action is done with a REDO. Recreate the issue with the following:
Create a rectangle.
Select the face only of the rectangle.
Run the following code in the Ruby console.
class MyEntityObserver < Sketchup::EntityObserver
def onChangeEntity(entity)
puts "onChangeEntity: #{entity}"
end
end
class MyModelObserver < Sketchup::ModelObserver
def onTransactionCommit(model)
puts "Transaction committed.";
end
def onTransactionUndo(model)
puts "Transaction undone.";
end
def onTransactionRedo(model)
puts "Transaction redone.";
end
end
model = Sketchup.active_model
entity = model.selection[0]
entity.add_observer(MyEntityObserver.new)
Sketchup.active_model.add_observer(MyModelObserver.new);
Move the rectangle face around several times. Note in the console the onChanged event is fired.
Undo your movements. The event is still fired.
Redo the movements. The event is no longer fired.
Is there a reason for this behaviour, or is it a bug? I’m trying to think of a workaround, but this seems like a pretty tough problem to resolve. Is there any other way to observe when an entity is modified, no matter what? Or pull the undo stack from Sketchup itself?
Not correct. (There are separate callback methods being called of the same model observer. But, during an undo, the Entity observer’s #onChangeEntity callback method is called first, before the model observer undo transaction callback.)
This (the lack of signalling a reverting change for the entity) cannot really be intended as it is poor design. This would require coders to keep separate state variables in order to sync observer events. This would not be good API design.
I’ll log it as an issue so Thomas can look into it …
Expectation / Suggestion:
Either an intervening EntityObserver#onChangeEntity callback should fire for Redo, (This would be consistent with Undo behavior,) …
(But then this latter #onRevertEntity implementation would possibly break existing plugins unless it also still fired the #onChangeEntity event in the absence of a #onRevertEntity callback.)