This was previously hidden in the SDK category as a response to a mixed code extension.
I have moved it here into the Ruby category.
This also serves as the example for what was discussed in topic:
Attach_Model_Observers.rb (3.8 KB)
# encoding: UTF-8
module SomeAuthor # <<---<<< Change to your toplevel namespace module
module SomeNiftyExtension # <<---<<< Change to your extension submodule
extend self
def attach(model)
model.add_observer(ModelSpy.new(model))
end
def expectsStartupModelNotifications
true
end
def onNewModel(model)
attach(model)
end
def onOpenModel(model)
attach(model)
end
def onQuit()
# execute onQuit tasks
end
class ModelSpy < Sketchup::ModelObserver
attr_reader :model
def initialize(model)
puts "#{self.class.name}\n in '#{__method__}'"
@model = model
# Hash to hold observer references:
@spy = {}
# Add all of the implemented observers to model collections:
model.definitions.add_observer(
@spy[:definitions]= DefinitionsSpy.new(model.definitions)
)
# ... etc, ... same for Entities, Materials, Layers (if defined) ...
end
#
### ... ModelObserver callback method definitions ...
#
end # class
class DefinitionSpy < Sketchup::DefinitionObserver
def initialize(definition)
puts "#{self.class.name}\n in '#{__method__}'"
# On model load, attach observers to each existing instance:
definition.instances.each { |instance|
instance.add_observer(InstanceSpy.new)
instance.add_observer(EntitySpy.new)
}
end
def onComponentInstanceAdded(definition, instance)
puts "#{self.class.name}\n in '#{__method__}':"
puts " #{definition.name}: #{instance}"
# Attach appropriate observers to the new instance:
instance.add_observer(InstanceSpy.new)
instance.add_observer(EntitySpy.new)
# Do something with the new instance ...
end
end # class
class DefinitionsSpy < Sketchup::DefinitionsObserver
def initialize(definitions)
puts "#{self.class.name}\n in '#{__method__}'"
# On model load, attach an observer to each existing definition:
definitions.each { |definition|
definition.add_observer(DefinitionSpy.new(definition))
}
end
def onComponentAdded(definitions, definition)
puts "#{self.class.name}\n in '#{__method__}': #{definition}"
# Attach an observer to the new definition:
definition.add_observer(DefinitionSpy.new(definition))
# Do something else with the new definition ...
end
end # class
class EntitySpy < Sketchup::EntityObserver
def initialize
puts "#{self.class.name}\n in '#{__method__}'"
end
def onChangeEntity(entity)
puts "#{self.class.name}\n in '#{__method__}': #{entity}"
# Do something with the changed entity ...
end
end # class
class InstanceSpy < Sketchup::InstanceObserver
def initialize
puts "#{self.class.name}\n in '#{__method__}'"
end
def onClose(instance)
puts "#{self.class.name}\n in '#{__method__}': #{instance}"
# Do something with the closed instance ...
# The instance's internal coordinates are in local values.
end
def onOpen(instance)
puts "#{self.class.name}\n in '#{__method__}': #{instance}"
# Do something with the opened instance ...
# All API methods will use and return WORLD coordinates !
end
end # class
# .. other observer class definitions ...
# RUN ONCE AT STARTUP:
if !defined?(@loaded)
# Define UI objects here ...
# Attach this module as an AppObserver object:
Sketchup.add_observer(self)
# Mark this extension as loaded:
@loaded = true
end
end # extension submodule
end # namespace module
Then when a component or group instance is moved, the onChangeEntity
callback method in the EntitySpy
will get called.
NOTE: The puts
statements like puts "#{self.class.name}\n in '#{__method__}'"
sending output to the Console are just for testing. They can be deleted, commented out OR a conditional if @debug
added at the end. (In the latter case you’ll need to define a @debug
boolean variable at the top of the extension submodule.)