Is there a method or extension to show a "swatch palette" of all materials in a model?

Here are a tuned version.
You can install with the Extension Manager, however it is not fully fulfil the extension requirements, but still will work…
You need to restart SU if previous version have been installed before.
Still, does not tested extensively… so no warranties! Use at your own risk!

Dezmo_Material_Lister2.rbz (1.1 KB)

Changes:

  • If you have a selection, the created component listing only the materials in a selection ( nested instances / drawing elements will taken into consideration.)

  • If no selection the full material list of model will be drawn. In this case even the unused materials will be there. (Similar as in a previous version of plugin)

  • You can enter the approx. height of material text, therefore the texture could fit better into the sample rectangle. (You can scale it afterwards you placed.)
    The initial height is 10 inch and displayed in an input box according the current Unit Settings. You can use the normal measurement entering rules to write in. (Type integer/float number as a current unit or 254mm or 10" or 1,66667’ etc ). The last entered value will be remembered during the session.

Dezmo_Material_Lister2

Ruby Code:
module Dezmo:MaterialLister
  extend self
  @@loaded = false unless defined?(@@loaded)
  
  def instance?(obj)
    obj.is_a?(Sketchup::ComponentInstance) || obj.is_a?(Sketchup::Group)
  end
  
  def no_mat(scope)
    UI.messagebox("There is no materials in a #{scope}")
    nil
  end
  
  def get_mats(ents, mat_h = {})
    ents.each do |obj|
      next unless obj.respond_to?(:material)
      mat_h[obj.material] = true if obj.material && !mat_h.key?( obj.material )
      if obj.is_a?( Sketchup::Face )
        mat_h[obj.back_material] = true if obj.back_material && !mat_h.key?( obj.back_material )
      elsif instance?(obj)
        get_mats( obj.definition.entities , mat_h )
      end
    end
    mat_h.keys
  end
  
  def list_materials
    mod = Sketchup.active_model
    mat = mod.materials 
    return no_mat("model") if mat.to_a.empty?
    sel = mod.selection
    if sel.empty?
      mod_name = mod.name == "" ? "Untitled" : mod.name
    else
      mat = get_mats( sel.to_a )
      return no_mat("selection") unless mat.first
      mod_name = "selection"
    end
    mats = mat.sort_by(&:display_name).reverse
    prompt = ["3D Text height:   "]
    @defaults ||=  [ 10.inch.to_l ]
    begin
      input = UI.inputbox(prompt, @defaults, "Material name text height")
      if input
        t_size = input[0].to_l 
        @defaults = [ t_size ]
      else
        return
      end
    rescue
      UI.messagebox( "Invalid length!\nType integer as a current unit or 50mm or 1.9\" for example" )
    end
    
    mod.start_operation "Create Material list component", true
    comp = mod.definitions.add "Material List of #{mod_name}"
    
    mats.each_with_index do |m, i|
      g = comp.entities.add_group
      g.entities.add_3d_text("█ #{m.display_name}", 0, "Arial", true, false,
                              t_size, 0.0, 0.0, true, t_size * 0.10 )
      g.name = m.display_name
      g.material = m
      g.move!([0, t_size * 2.0 * i, 0])
    end
    mod.place_component( comp )
    
    mod.commit_operation 
  end
  
  unless @@loaded
    @@loaded = true
    cmd1 = UI::Command.new("Create 'Material List' component"){
      list_materials
    }
    UI.menu("Plugins").add_item( cmd1 )
  end
  
end