You could use a hybrid observer class, that watches the tool stack (for each model as it is opened,) then when the PaintTool is activated, attaches itself to watch the active entities and the materials collection.
It will not attach to the open model if loaded into the console, so load a new model.
Also, it may need to some tweaking to work on a Mac with multiple models open.
paint_spy.rb (3.2 KB)
which looks like this for those not wishing to d/l the file:
module SomeAuthor
module SomePlugin
@@loaded ||= false
@@spy ||= false
def self.spy
@@spy
end
# This is an example of a hybrid observer that watches the tools collection
# for PaintTool activation, then attaches itself as an obsever to watch the
# materials collection and the active entities context.
# It will set instance references to the modified entity and it's material.
# When the active tool is changed and is no longer the PianTool, then this
# hybrid observer will stop watching the materials collection and entities.
class HybridSpy < Sketchup::EntitiesObserver
# Construction:
attr_reader( :material_used, :back_material_used, :painted_entity )
def initialize(*args)
reset()
@previous_tool = nil
end
def reset
@back_material_used = nil
@material_used = nil
@painted_entity = nil
end
def watch_tools(model)
model.tools.add_observer(self)
puts "Spy now watching Tools collection of active model:\n #{model.inspect}\n"
end
# AppObserver callbacks:
def expectsStartupModelNotifications
return true
end
def onNewModel(model)
watch_tools(model)
end
def onOpenModel(model)
watch_tools(model)
end
# ToolsObserver callbacks:
def onActiveToolChanged(tools, tool_name, tool_id)
model = tools.model
if tool_id == 21074 # PaintTool
@previous_tool = 21074
puts "\nPaintTool activated"
# Begin watching the materials & active entities collections:
model.materials.add_observer(self)
model.active_entities.add_observer(self)
elsif @previous_tool == 21074
puts "\nPaintTool deactivated"
# Stop watching the materials & active entities collections:
model.materials.remove_observer(self)
model.active_entities.remove_observer(self)
@previous_tool = tool_id
reset() # reset the instance vars to nil
end
end
# EntitiesObserver callbacks:
def onElementModified(entities, entity)
return unless entity.is_a?(Sketchup::Drawingelement)
puts "\nonElementModified: #{entity}"
@painted_entity = entity
if entity.respond_to?(:material)
puts " front material: #{entity.material.inspect}"
puts " material name : #{entity.material.name}" unless entity.material.nil?
@material_used = entity.material
else
@material_used = nil
end
if entity.respond_to?(:back_material)
puts " back material : #{entity.back_material.inspect}"
puts " material name : #{entity.back_material.name}" unless entity.back_material.nil?
@back_material_used = entity.material
else
@back_material_used = nil
end
#
### Notify some other code object of paint action ?
#
end
end # class HybridSpy
if !@@loaded
# Attach as an AppObserver:
@@spy = HybridSpy.new
Sketchup.add_observer(@@spy)
@@loaded = true
end
end
end