Hi all. I’m new to the Sketchup API. I’m using IFC output from sketchup so I’ve been making everything into components. I need to output component material. I’m making a simple plugin that contains some custom Materials (in .skm format distributed with the plugin) and just lets the user quickly assign the custom material to their IFC component from a drop-down list. I’ve been using the attribute visualizer to learn about and see the component details. I can get the material to be assigned to the component (I assume that will also set it to the instance?) but can’t get the material to show up visually. The material seems to be loaded correctly via api but shows up as “Material not in model” in _material_error (as seen in attribute visualizer plugin). After I’ve made the materials.load call in the code, I can manually type the “My Special Material” in the component dynamic attributes and it will be correctly applied. I’m sure it’s something basic I missed. I did look at this long discussion https://forums.sketchup.com/t/components-attributes-for-ifc/201079/19 but it seemed to do mostly with custom attributes and not a standard one like material. I found a sample that assigns a simple color as component material but it’s not quite working with a new material. Thanks for any help.
setComponentsMaterial(selectedEntities, 'My Special Material')
def setComponentsMaterial(selectedEntities, materialName)
#pull the material if not already in the model
if materialName != 'red'
newMaterial = load_material(materialName)
#save the values to the components
puts "saving material to components"
if selectedEntities.length > 0
selectedEntities.each do |selectedEntity|
selectedEntity_def = selectedEntity.definition
selectedEntity_def.set_attribute('dynamic_attributes','_material_formula','"' + materialName + '"')
#selectedEntity.material = newMaterial
selectedEntity_def.set_attribute 'dynamic_attributes','_description_formula','Component now has material-->' + materialName
puts "finished setting material to component"
dcs = $dc_observers.get_latest_class
mat = Sketchup.active_model.materials[materialName]
full_path_to_skm = File.join( $ifc_plugin_data_path, 'SketchupMaterials', materialName + '.skm')
puts "full_path_to_skm=" + full_path_to_skm
mat = Sketchup.active_model.materials.load(full_path_to_skm)
puts "error loading material from skm"
puts "material loaded successfully:" + full_path_to_skm
What IFC scheme are you using Ifc 2x3 or Ifc 4?
I’m not sure but I think that 2x3 doesn’t export materials.
Have you tried to export with Ifc Manager?
I always use that plugin and Insee my model in an Ifc viewer with all of materials. But I apply them with paint bucket directly to components
Do not use global variables, even if you see old examples that do.
Each of your extensions must be within a submodule, which must be within your unique top level namespace module. Therefore either use a local constant or @variable within your extension submodule.
If your plugin’s materials folder is a subfolder of your extension subfolder, where the file is loaded from, then you only need use the global Ruby method __dir__() to get that path, so
SKM_PATH ||= File.join(__dir__, 'SketchupMaterials')
Only the API color names as described in the Sketchup::Color class can be used by name for #material=.
But if you create a material with a custom name, then you can get it with materials[matl_name] but to assign it to an instance you will need to use a reference you get back from materials[matl_name] or materials.load(matl_name).
Assigning a material to a ComponentDefinition does not currently have a good reason. (This only shows the instance in that material whilst it is attached to the cursor when placing it. Once placed the instance would have no material.)
So, the answer is, you must usually always meticulously “take every step” and “jump through every hoop.” Yes, you must explicitly assign a material to an ComponentInstance or a Group.
Sadly, I need to use 2x3 as the app I’m transferring to only uses that. I looked at ifc manager but it seemed like a lot of overkill for what I thought was a small easy task. Sketchup seems to export the material (or at least the name of the material) at least when defined in the component definition.
Thanks for the very quick responses. Understood about the globals. I changed the code to apply the material to the component instance(s) (ie. selectedEntity.material = newMaterial )and it looks fine in sketchup but even if I leave the material dynamic attribute in the component def, it now doesn’t show up in the IFC output or in the attribute viewer. That confuses me. My main goal was to have the material name in the IFC output (to communicate it to other app) and the secondary need was to have it look correct in sketchup during modeling. Is getting it in the IFC output what you pointed out with the two links? How do I do what is described in the links programmatically?
Try to view the model in another viewer like Bim Collab Zoom or Bim Vision, they read both schemas. Also try to export the same model with Ifc 2x3 and Ifc 4, view them in those viewers and find the differences.
I spoke with the developers of Bim5D software that I’m using and they say that Sketchup exports materials in a different way that Revit does (As an example… I don’t know which one is doing right…)