Hi all,
I have an issue with using UI.start_timer on Windows 10 OS (I tested the same function on Mac OS, it works well)
I have the code below:
$added_instance = nil
class TestDefinitionObserver < Sketchup::DefinitionObserver
def onComponentInstanceAdded(definition, instance)
$added_instance = instance
UI.start_timer(0.1, false) {
$added_instance.explode!
}
end
end
$added_instance is undefined in the runtime. If anyone experienced with the issue and have any solution to fix it, please let me know. Thanks in advanced.
Not yet experienced, but with observers you should be careful. As you should never assume things just from common experience, you should never assume things in SketchUp observers.
- Add a check that the given instance is not nil, and valid (not a deleted entity):
if instance && instance.valid?
This is necessary because observers can be triggered when entities are already deleted. Try copy-pasting a component instance and instead of placing it, you press Esc.
- Also add a
begin
/rescue
clause so that you will know about if an exception happens (exceptions in event handlers like observers or dialog callbacks do not print to the console).
Also you should not use the global variable and there is never a need for passing data with global variables (I think you added it for debugging). If you need it, you could give the observer a reference to the class that needs the collected instances, and notify it:
class TestDefinitionObserver < Sketchup::DefinitionObserver
def initialize(my_extension)
# Initialize with a reference to a class to notify
@my_extension = my_extension
end
def onComponentInstanceAdded(definition, instance)
begin
if instance && instance.valid?
# Notify the related class and pass the instance over to it.
@my_extension.instance_added(instance)
end
rescue Exception => e
puts(e.message)
puts(e.backtrace.join($/))
end
end
end
# Example code using messaging between observer and extension classes.
class MyExtension
def initialize
@instances = []
end
def run
model = Sketchup.active_model
definition = model.definitions.add("My Definition")
definition.entities.add_edges(ORIGIN, ORIGIN+X_AXIS)
# Pass a reference to the class that should be notified (this class, self)
instance_added_observer = TestDefinitionObserver.new(self)
definition.add_observer(instance_added_observer)
# Simulate the user doing this:
instance = model.entities.add_instance(definition, IDENTITY)
end
def instance_added(instance)
@instances << instance
puts(@instances)
end
end
MyExtension.new.run
2 Likes
I second what Aerulius said. And in addition I see this exercise as problematic.
The OP is interrupting the instance creation process with an observer that destroys that very instance.
- There may be other observers in the queue that have not yet been called and expect a valid instance.
- The exploding can cause new component instances (that were previously nested) to trigger another observer calling loop before the current one is done.
Hence the OP’s attempt at using a timer to delay the explode.
This does not seem to me to be a very good coding pattern.