Unused materials and Tags with Ruby

I’m making a statistics plugin, and I’m trying to get the amount of unused materials in a model
I can get a number, but in large projects there is an account error, a number appears that is higher than it should be.

def self.get_unused_materials_count
  model = Sketchup.active_model
  used_materials = model.entities.grep(Sketchup::Face).map(&:material).compact.uniq +
                   model.definitions.grep(Sketchup::ComponentDefinition).flat_map { |d| d.entities.grep(Sketchup::Face).map(&:material) }.compact.uniq +
                   model.entities.grep(Sketchup::Group).flat_map { |g| g.entities.grep(Sketchup::Face).map(&:material) }.compact.uniq
  all_materials = model.materials.to_a
  unused_materials = all_materials - used_materials

for tags it’s the same thing

def self.get_unused_layers_count
  model = Sketchup.active_model
  all_layers = model.layers.to_a
  used_layers = []

  model.entities.each do |entity|
    used_layers << entity.layer unless entity.layer.nil?
    if entity.respond_to?(:definition)
      entity.definition.entities.each do |sub_entity|
        used_layers << sub_entity.layer unless sub_entity.layer.nil?

  unused_layers = all_layers - used_layers

help? I just need to show the total materials in the file and how many are not being used, the same thing for the tags.

(1) Realize that there are three kinds (owner types) of material objects:

Only the materials manager “owned” material objects are allowed to be assigned to geometric Drawingelements.

See this API tracker issue:

(2) Your counting code is only checking for materials assigned to Face objects. However, both group and component instances as well as Edge objects can have material assignments. There are also other Drawingelements subclass objects that can have material assignments, such as dimensions and text callouts (which will display their material.)

Then there are others that accept a manual material setting which shows in the Model Info swatch, but does not display nor get returned from Ruby, such as a SectionPlane object. (The latter may be a bug as Guidelines are similar but do not allow the Paint Bucket tool to paint them.)

Also, see this API tracker thread which I posted some useful Ruby refinements as ideas for future API methods:

1 Like