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

Something like, “make a bunch of 10x10x1 squares, each painted with 1 material, with the name of the material next to it, all organized in a list”.

Not just a list of the statistics, but like a “Legend / Key” as actual objects that I can put into a separate scene & print along with other views.

You’d better to start learning to code with Ruby & SketchUp API. :wink:

I understand what you need but if you think about it, by having your own custom color palette it is a one-time job. (not necessary a plugin)
I have mine and a legend like the one you are asking for inside a LayOut scrapbook. I just have to update it every time I add new materials.

1 Like

Try Eneroth’s Material Extractor: Extension | SketchUp Extension Warehouse

2 Likes

Here are my quickie.
You can install with the Extension Manger, however it is not fully fulfil the extension requirements, but still will work…
As usual, does not tested extensively… so no warranties! Use at your own risk!

EDIT: Please see newer version in a next post!
Dezmo_Material_Lister.rbz (658 Bytes)

You will get a menu in Extension>“Create ‘Material List’ component”

As the menu suggests it will create a component (with a name “Material List of +{model_name}”) and one of it instance will be attached to the mouse cursor so you can place it to the model as you wish.
Inside this component each group and its name representing one material. The materials are assigned to the corresponding groups.
The group itself geometrically created as 3D text of one cuboid and a material name.

You can undo it.
If you create an other component that will be automatically get a new name by numbering it.

Dezmo_Material_Lister

Ruby Code:
module Dezmo:MaterialLister

  @@loaded = false unless defined?(@@loaded)
  
  def self.list_materials
    mod = Sketchup.active_model
    mat = mod.materials 
    return UI.messagebox("There is no materials in a model ") if mat.to_a.empty?
    
    mod_name = mod.name == "" ? "Untitled" : mod.name
    mats = mat.sort_by(&:display_name).reverse
    
    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,
                              1.0, 0.0, 0.0, true, 0.10 )
      g.name = m.display_name
      g.material = m
      g.move!([0, 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"){
      self.list_materials
    }
    UI.menu("Plugins").add_item( cmd1 )
  end
  
end
10 Likes

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
5 Likes

hi @dezmo , I was wondering if it would be possible to do something similar with DC name attribute?
basically select dc (cabinet) ,pres the button and it will place text of the name within the DC .
like this


thanks Miro

It’s theoretically possible. However, the task is completely different.

The length of the text to be placed and where to start a new line in the text are quite difficult to determine.
In the Ruby API, only the height of the 3D text can be specified (approximately), and the length of the text can be estimated approx. from the number of characters (the different widths of the letters complicate the task even more.). So, depending on the size of the cabinet, on which side you want to place the text, you need to iterate the height of the text and the position of the new line to fit on the desired side of the cabinet.

Open a new topic, describe the task in as much detail as possible. Attach an example model. I (or others) will see if I can do something. (This is not a promise, just a possibility. :blush:)

1 Like

You should take a look at one of the @curic4su plugins called Curic Single-Line Text

It takes the name of the Component easily

2 Likes