# Adding materials from SketchUp's material collections to the current model

**URL:** <https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753>\
**Category:** Ruby API\
**Created:** [November 8, 2017, 8:22pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753 "2017-11-08T20:22:46Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![barry\_milliken\_droid](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/barry_milliken_droid/32/4612_2.png) [@barry\_milliken\_droid](https://forums.sketchup.com/u/barry_milliken_droid)\
**Post date:** [November 8, 2017, 8:22pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/1 "2017-11-08T20:22:46Z")

</div>

SU comes installed with 17 material collections from Wood to Water.  
How do I reference them to add one or more of their materials to the current model?

---

<div class="post-metadata">

**Author:** ![barry\_milliken\_droid](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/barry_milliken_droid/32/4612_2.png) [@barry\_milliken\_droid](https://forums.sketchup.com/u/barry_milliken_droid)\
**Post date:** [November 8, 2017, 8:45pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/2 "2017-11-08T20:45:29Z")

</div>

I just found the work around from a previous post by Dan Rathbun in 2015:

"A workaround is to create a component that has the needed material(s) in it. And load this component definition into the model using DefinitionList#load()3.  
Then immediately afterward DefinitionList#purge\_unused().

This approach requires you to distribute this material component with your plugin."

Seems 25% of my effort is implementing workarounds.

---

<div class="post-metadata">

**Author:** ![eneroth3](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/eneroth3/32/1222_2.png) [@eneroth3](https://forums.sketchup.com/u/eneroth3)\
**Post date:** [November 8, 2017, 9:05pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/3 "2017-11-08T21:05:29Z")

</div>

> [@barry\_milliken\_droid](#):
>
> Seems 25% of my effort is implementing workarounds

Haha, know that feel. But now a quite large amount of the time is spent with users who gets their cards rejected by EW instead 😛 .

Anyhow, the user might not want to purge components. It’s a very unexpected side affect of a plugin. I’m not sure but I think more recent SketchUp versions can delete a single Definition by clearing its Entities.

---

<div class="post-metadata">

**Author:** ![TIG](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/tig/32/198_2.png) [@TIG](https://forums.sketchup.com/u/TIG)\
**Post date:** [November 8, 2017, 9:51pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/4 "2017-11-08T21:51:47Z")

</div>

```
filename = 'Materials/Brick, Cladding and Siding/Cinder Block.skm'
path = Sketchup.find_support_file(filename)
materials = Sketchup.active_model.materials
material = materials.load(path) if filename

```

With v2017 will load the SKM from the shipped folders - IF it exists - i.e. provided that the user has not changed the contents of the shipped Materials subfolder… e.g.

`C:\ProgramData\SketchUp\SketchUp 2017\SketchUp\Materials\Brick, Cladding and Siding`

---

<div class="post-metadata">

**Author:** ![barry\_milliken\_droid](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/barry_milliken_droid/32/4612_2.png) [@barry\_milliken\_droid](https://forums.sketchup.com/u/barry_milliken_droid)\
**Post date:** [November 8, 2017, 10:48pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/5 "2017-11-08T22:48:08Z")

</div>

Are you suggesting that v2017 introduced this new functionality? Or merely that v2017 renamed the folder/file names for the shipped materials?

I need to support v16 and later.

---

<div class="post-metadata">

**Author:** ![eneroth3](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/eneroth3/32/1222_2.png) [@eneroth3](https://forums.sketchup.com/u/eneroth3)\
**Post date:** [November 8, 2017, 10:48pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/6 "2017-11-08T22:48:36Z")

</div>

Isn’t finding the SketchUp install dir pretty much what Sketchup#find\_support\_file was for? Now I can’t get it to return any useful value though 😕 .

---

<div class="post-metadata">

**Author:** ![TIG](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/tig/32/198_2.png) [@TIG](https://forums.sketchup.com/u/TIG)\
**Post date:** [November 8, 2017, 10:54pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/7 "2017-11-08T22:54:46Z")

</div>

Finding the file is one thing.  
Loading it into the model is available with \>=v2017…  
With my example code a material is added to the model using the specified SKM…

If you only specify ‘Materials’ it looks in the user’s defined folder of that name, BUT giving the full path to a potential SKM file succeeds…

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 9, 2017, 7:58pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/8 "2017-11-09T19:58:50Z")

</div>

> [@barry\_milliken\_droid](#):
>
> Are you suggesting that v2017 introduced this new functionality?

The API docs (and TIG) are clear as to the first version availability for each method.

[Class: Sketchup::Materials — SketchUp Ruby API Documentation](http://ruby.sketchup.com/Sketchup/Materials.html#load-instance_method)

indicates the first version availability is:

> Version:
> 
> - SketchUp 2017

…

> [@barry\_milliken\_droid](#):
>
> Or merely that v2017 renamed the folder/file names for the shipped materials?

SketchUp 2017 (for the first time) put the shipped file folders in the correct place.  
So they are now in the **`%ProgramData%`** folder path, rather than the **`%ProgramFiles%`** (or **`%ProgramFiles(x86)%`** ) folder path.

> [@barry\_milliken\_droid](#):
>
> I need to support v16 …

You’ll need to deal with both folder locations, however TIG’s example code **ALSO** works for v2016:

```auto
filename = 'Materials/Brick, Cladding and Siding/Cinder Block.skm'
path = Sketchup.find_support_file(filename)

#=> "C:/Program Files/SketchUp/SketchUp 2016/Materials/Brick, Cladding and Siding/Cinder Block.skm"

```

**If** a user has a 32-bit edition of SketchUp 2016 installed on a 64-bit Windows machine (which some users do as they have 64-bit graphics driver issues,) then this above code would also return the correct path, ie:

```ruby
#=> "C:/Program Files (x86)/SketchUp/SketchUp 2016/Materials/Brick, Cladding and Siding/Cinder Block.skm"

```

For SketchUp versions before 2017 but with Ruby 2.x and the standard library, you can use the RubyZip library to read the SKM zip archives and re-create a new material using the information in the internal XML files and the texture image file in the archive’s subfolder.

---

<div class="post-metadata">

**Author:** ![barry\_milliken\_droid](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/barry_milliken_droid/32/4612_2.png) [@barry\_milliken\_droid](https://forums.sketchup.com/u/barry_milliken_droid)\
**Post date:** [November 12, 2017, 5:30pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/9 "2017-11-12T17:30:34Z")

</div>

It seems that another way to add a material from SketchUp’s collections to the “In Model” collection is to rely on  
Sketchup.active\_model.materials.current  
which (strangely?) returns the currently selected material even if that material is not in the active model.  
But the only way to add it to the model for future use by a ruby script is to apply it, at least temporarily to an entity.

This avoids the version problems mentioned above.

Background FYI: My extension adds 6 custom materials with different standard colors to the model. This is easy to do without using any form of “load” method. During model building, the user can execute a command that analyses the entire model and applies the materials to faces and groups depending on orientation and geometric relationships.  
No problem so far. Then I decided that I wanted the user to be able to substitute any material from the SketchUp collections for any of the custom materials used for analysis. That led to this thread.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 13, 2017, 10:15am UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/10 "2017-11-13T10:15:42Z")

</div>

> [@barry\_milliken\_droid](#):
>
> `Sketchup.active_model.materials.current`
> 
> which (strangely?) returns the currently selected material even if that material is not in the active model.

When SketchUp is first loaded with an empty model this method returns **`nil`** (which can actually be set `nil` at anytime by the user if they choose the “default material” swatch.)

To have this return the reference to previously loaded models would be a bug IMO.  
I just tested this on SU2016 and it returns **`nil`** after loading an new model (having been set to a concrete material and painted a group in the previous model. Matters not whether the previous model was saved or unsaved.)

**What SketchUp version do you see this behavior in ?**

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 13, 2017, 11:09am UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/11 "2017-11-13T11:09:24Z")

</div>

> [@barry\_milliken\_droid](#):
>
> Background FYI: My extension adds 6 custom materials with different standard colors to the model.

One of the old workarounds was to provide a template that already had a set of materials loaded.

Another was to provide or load a component that had the materials loaded within it. These materials need to be assigned to something like layers (must have at least a cpoint on them) or temporary geometry inside a group, that can be deleted after the load is complete. This leaves the materials behind in the “In Model” materials collection for later use. _Hoping that the user or another plugin does not purge the collection(s)_.

> [@barry\_milliken\_droid](#):
>
> Then I decided that I wanted the user to be able to substitute any material from the SketchUp collections for any of the custom materials used for analysis. That led to this thread.

As evidenced by the workarounds, the community was requesting the “ **load from file** ” feature for years until it was finally implemented for version 2017. This took _many_ years for this to happen, I suppose because there were workarounds.

* * *

_… as an aside_: The user themselves were always able to drag and drop multiple materials (one by one) from a secondary Materials browser pane into the “In Model” pane (at least on PC.)

---

<div class="post-metadata">

**Author:** ![barry\_milliken\_droid](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/barry_milliken_droid/32/4612_2.png) [@barry\_milliken\_droid](https://forums.sketchup.com/u/barry_milliken_droid)\
**Post date:** [November 13, 2017, 4:17pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/12 "2017-11-13T16:17:20Z")

</div>

I’m using SU 2017 on PC. My understanding of materials, colors and textures in the API is thin so I’m feeling my way. I’m aware of the possibility that users might “Purge unused” and therefore test and add again my 6 specially named custom materials if necessary. They are all defined with simple color names from the list of colors in the API documentation for the color object. The custom names are referenced by my analysis methods.

Consider this situation: User wants to change the material properties of my “custom material 1” by selecting a “material\_A” in one of SU’s material collections outside the model. I code a method to accomplish this that requires him to first make “material\_A” the current selected material.

There seem to be 2 ways to code this:

1. Retrieve the properties of the current material and assign them to “custom color 1”. This fails because the method texture.filename does NOT return the full path as the documentation says it does. Also its seems material.materialType and material.colorize\_deltas can be retrieved but not assigned. (Perhaps these are merely derivative of other properties?)
2. Apply the current material to a face. Reapply the face’s original material to the face. This adds “material\_A” to the model. Delete “custom color 1”. Change the name of “material\_A” to “custom material 1”. This works. No version dependent load required.

The disadvantage of method 2, is that it does not automatically update all existant references to “custom color 1” already in the model. So the entire model have to be reanalyzed to apply the new material.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 14, 2017, 7:41pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/13 "2017-11-14T19:41:27Z")

</div>

> [@barry\_milliken\_droid](#):
>
> I code a method to accomplish this that requires him to first make “material\_A” the current selected material.
> 
> There seem to be 2 ways to code this:

There are material replacer plugins out there that you could get ideas from.

You would likely need to implement this observer callback:

[Class: Sketchup::MaterialsObserver — SketchUp Ruby API Documentation](http://ruby.sketchup.com/Sketchup/MaterialsObserver.html#onMaterialSetCurrent-instance_method)

… or use a **`ToolsObserver`** to detect a change to the PaintTool.

> [@barry\_milliken\_droid](#):
>
> Also its seems material.materialType and material.colorize\_deltas can be retrieved but not assigned. (Perhaps these are merely derivative of other properties?)

A main reason why I abandon my own SKM importer.

@TIG has a very old SKM tools library over at SketchUcation.

> [@barry\_milliken\_droid](#):
>
> 1. Retrieve the properties of the current material and assign them to “custom color 1”. This fails because the method texture.filename does NOT return the full path as the documentation says it does.

I would **not** rely upon a bug where references are “_left over_” from a previous model. This does not occur in SU2016, so it must be a regression for SU2017.

---

<div class="post-metadata">

**Author:** ![barry\_milliken\_droid](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/barry_milliken_droid/32/4612_2.png) [@barry\_milliken\_droid](https://forums.sketchup.com/u/barry_milliken_droid)\
**Post date:** [November 14, 2017, 9:05pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/14 "2017-11-14T21:05:40Z")

</div>

I think you misunderstood me.  
When I said “which (strangely?) returns the currently selected material even if that material is not in the active model.”, I was not implying that the material existed in some previous model.

I was merely referring to the fact that all the materials in the standard material collections that appear whenever you use SketchUp are:

1. Not “In Model” until the user applies them to some entity.
2. and are therefore not referencable by the ruby API via Sketchup.model.materials

The API give us no access to them. ( there is no Sketchup.materials object in the API)

So it is a logical inconsistency that Sketchup.model.materials.current can give us access to a material not yet in the model.

The problem with texture.filename not returning the full path is unrelated to the above. The path is not returned for any material, even those in the model. Perhaps this method is a holdover from before the invention of the skm file.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 14, 2017, 10:01pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/15 "2017-11-14T22:01:29Z")

</div>

> [@barry\_milliken\_droid](#):
>
> I think you misunderstood me.
> 
> When I said “which (strangely?) returns the currently selected material even if that material is not in the active model.”, I was not implying that the material existed in some previous model.

**Sorry, yes I misunderstood.**

> [@barry\_milliken\_droid](#):
>
> So it is a logical inconsistency that **`Sketchup.active_model.materials.current`** can give us access to a material not yet in the model.

I now understand what your are getting at. This (what you described as being “strange”,) is normal because a user can select a material to paint with, then decide to do something else instead and cancel the tool by pressing ESC or selecting another tool. So yes, it can return a valid **`Sketchup::Material`** object that is not yet a member of the “In Model” collection until some entity is “painted” with it.

But it also is “strange” in that to get it’s reference you have to query the model’s materials collection object. On the one hand, you’d think this would be an application level property, but they decided to have it’s access via the model’s materials collection as that is where people would go looking for it. The possibility also exists that on the Mac’s multi-model interface, that each model may keep it’s own reference to the PaintTool’s current material. (You’d need to test this theory.)

On PC, opening a new model will reset the current material to **`nil`**.

> [@barry\_milliken\_droid](#):
>
> The API give us no access to them. ( there is no Sketchup.materials object in the API)

When they reside on disk, they are mere directories with SKM file objects.

**EDIT: I am NOT against having the API implement a nice interface for it’s application level collections.**

The API gives you access to find the folder paths as @TIG said above.

With that YOU can use the **core Ruby** [**`Dir`**](http://ruby-doc.org/core-2.0.0/Dir.html) class to build a list of material collections and lists.  
I recall @TIG posting an informational thread on how to write a Material Browser WebDialog, perhaps over at SketchUcation.

Basic prompting of user for a material:

```ruby
WIN =( Sketchup.platform == :platform_win rescue RUBY_PLATFORM !~ /darwin/ )
ext = WIN ? 'SketchUp Material|*.skm||;' : '*.skm'
chosen_matl = UI.openpanel("Choose Material",Sketchup.find_support_file('Materials'),ext)
if chosen_matl # nil if user cancels
  # use the material pathname to load a material
end

```

But again, you need SU2017 to leverage the [materials.load()](http://ruby.sketchup.com/Sketchup/Materials.html#load-instance_method) method.

Otherwise you’d be doing a component workaround from a special library that would need a temporary component for every darn material in the distribution library.

> [@barry\_milliken\_droid](#):
>
> The problem with texture.filename not returning the full path is unrelated to the above. The path is not returned for any material, even those in the model. Perhaps this method is a holdover from before the invention of the skm file.

No, this method only returns local paths for texture images that the user themselves have set using the edit tab of a material.

Think about it, what good would it do (for distributed components) to have a pathname to textures on one of Trimble’s development workstations ? … or to a 3DW component author’s local texture files on their computer ?

If YOU want local textures for the materials you can create them manually, or paint a bunch of faces and write a utility the uses that [**`Sketchup::TextureWriter`**](http://ruby.sketchup.com/Sketchup/TextureWriter.html) class to export them locally. I don’t think you want to publish a bunch of image files like this with your plugin.

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 14, 2017, 10:25pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/16 "2017-11-14T22:25:14Z")

</div>

> [@DanRathbun](#):
>
> or to a 3DW component author’s local texture files on their computer

for models they do on a mac…

and for manually created .skm files unless the author `cd` into the image directory first…

I think that’s how the SU ones now avoid the full path, which some older SU ones have…

the `File.basename` can still come in handy for getting the original name…

for v18 ImageRep looks like a better way to make a lot of textures available to extensions…

@barry_milliken_droid,

if your user opens your material for editing, then selects a replacement texture, it retains your material name…

is that what your trying to replicate?

or is that just a mac thing?

if not, would it be easier to advise the user that this how to change a texture…

john

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/sketchup/original/3X/f/2/f2a121500b085ed60806607a82720b092d800bb3.png) [@system](https://forums.sketchup.com/u/system)\
**Post date:** [February 14, 2018, 2:25pm UTC](https://forums.sketchup.com/t/adding-materials-from-sketchups-material-collections-to-the-current-model/54753/17 "2018-02-14T14:25:44Z")

</div>

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.
