Assigning "Wood OSB" to face with API
-
I've tried using the name "Wood OSB" to assign this material to a specific face(s) in my plugin. I must be missing something though since I can't get it to work. My code is:
new_face1.material = "Wood OSB"
I am trying to achieve this effect:
My other issue is how to select the correct face to apply the material to. The plugin first creates the profile of the I-Joist as a face and then pushpull to create the solid group. Somehow I've got to figure out how to select the two web faces as shown above and then apply the material only to those two faces (exterior).
-
You can do it in the way you showed, but only if the name is a standard color - like 'Red' - when SketchUp will add a new 'Red' material for you.
However, to make a new named material is not too difficult...
mats = Sketchup.active_model.materials my_mat_name = 'My Material Name' my_mat = mats.add(my_mat_name) unless my_mat = mats[my_mat_name]
either way you now have '
my_mat
' referencing that material.Next you need to add a texture.
my_mat.texture='full_path_to_texture_image_file'
Perhaps referencing and image kept in your extension's subfolder.
Then the texture can be resized etc
my_mat.texture.size = [h, w]
With height and width in inches.
You could also add analpha
transparency value...Another perhaps less involved way is to make a color-swatch component [SKP], with a series of squares each with a different textured material, you also keep a list of their names.
Purge that SKP so it only contains the materials you want [e.g. NO layers, unless you also want to import those].
Now in code add that component SKP [from its path in your extension's subfolder - let's assume it's named 'Medeeks_Swatch.skp'].
defn = Sketchup.active_model.definitions.load('full_path_to_the_SKP') unless Sketchup.active_model.definitions['Medeeks_Swatch']
The unless test only adds it if it's missing - e.g. the user has purged the model.
This also ensures any unused materials it brought are restored.
Now all of its materials have been added to the model.So if you have a material in the swatch named "Wood OSB" use it thus:
new_face1.material = mats["Wood OSB"]
Where mats is the reference to the model's materials set up as shown earlier in this post...This way you only have to import the SKP swatch once and its numerous materials are then readily available for use...
PS: Another tip, because a textured material is aligned axially on a face you might want to make two variants of any 'grained' materials - like lumber - i.e. for horizontally and vertically aligned members.
With OSB one material should suffice... -
Thank-you for the very detailed "howto", this will help me significantly with custom textures and materials. However, I thought it might be easier since "Wood OSB" is already a built in material under the "Wood" category, hence no need to define a new material, just use the existing one.
-
You are confusing materials listed as available in various material-collections, and what's currently loaded into the model.
You have no certainty that a user will not have messed on with their material collections, anyway.
In pure [version-independent] API code at least, you cannot load a material from its external SKM into the model - whether it's in a collection or perhaps your extension's subfolder etc.
That is why I offered the two ways of doing it - one to make a new material with a texture etc, or the other [probably better way] to load a component SKP which you've put in your extension's subfolder, containing a swatch of faces which are each assigned custom-materials, which then has the affect of loading all of those materials into the current model as well, so you can then specify those by name. -
So it sounds like the best bet is to create my own custom materials with unique names which avoids conflicts with material names that have already been created by the user. I am not sure why you cannot just load materials directly from the built in materials library but I will definitely take your word for it.
-
This is what I do
# load_material('c;\...\images', 'Glass', '.png', 36, 0.4) def load_material(images, image_name, extension, ht, alpha = 1.0) file_name = File.join(images, "#{image_name}#{extension}" ) if (File.exist?(file_name)) model = Sketchup.active_model() materials = model.materials # check to see if material is already loaded in the model materials.each do |material| return if (material.texture && material.texture.filename == file_name) end m = materials.add(image_name) m.texture = file_name m.texture.size = ht m.alpha = alpha end end
-
Of course you can write your own method to create a new material [perhaps named from its image file] and then add its texture to it etc.
GaryK's example is clear on how you could do that.
You could even write your own SKM loader [I have done that - several years ago].To explain more fully...
Up until v2017 arrived [and we are still in 2016!], there was no API method like
model.materials.load('full_path_to_material.SKM')
, but it has at last been added to the API.
But also remember that you will greatly limit your user-base to just v2017 users for the next year or so, if you use that limited approach.
See this for >=v2017 specific use: http://ruby.sketchup.com/Sketchup/Materials.html#load-instance_method
Also you will still need to specify the load-path to each material's SKM, and since you can't be sure the user hasn't messed on with the 'shipped' ones, then you really need to ship your own SKM materials files inside your extension's subfolder [probably in their own sub-subfolder 'SKMs' ?], to be sure they are always available to get them loaded.
BUT the approach of using one 'swatch' SKP [saved in a SketchUp version that will suit your intended user-base - I'd say v8 since that's the last unsupported version so it'll load in all upcoming versions, anything later will balk if the model's SketchUp is older that the component's version !] and then loading that, which ensures that all of its materials get loaded with that component - and this will work in every SketchUp version - allowing a broad user-base... -
The load_material function works in all versions of Sketchup from SU 7 through to SU 2017.
Users can add jpg and or png files to the images folder. I do it this way because I wanted to supply a number of wood grain textures write out of the box (since Sketchup has so very few).
-
@GarryK
I wasn't disagreeing.
Your custom load_material() method is well suited to loading a textured material from an image file.
But the very recentmaterials.load(path)
in v2015 loads SKM files directly
My own SKMtools has done this for the preceding six years.
IMHO, loading a component containing a swatch of various textured materials is a quick way of getting dozens of SKMs loaded into a model in one step. Also it allows you to predefine the texture image, sizes etc beforehand... -
I can see I have a couple of good options here. Thank-you for providing so much detail on how to get it done. As always both of you are purveyors of vast amounts of SketchUp knowledge. Thank-you for allowing me to lean on you guys a little.
-
One last question:
If the user moves the deletes the texture image I'm assuming that it will break the material in the SketchUp model?
-
If any file is missing at the moment that there is an attempt to 'use' it - e.g. a texture image, a SKM material, or a SKP component - then the process will fail.
However, once a texture image is used for a material for a model's material, or a SKM material is loaded into a model [v2017], or a SKP component is loaded into a model, then that data is bound into the model and its connectivity to the external reference is no longer needed - so if the file is subsequently deleted nothing bad happens.
Unless a user goes into your extension's subfolder and removes [or renames] images, or SKMs or components, before the load attempt, then it will always [re]load.
If you rely on 'shipped Materials', then if they are there they could load [v2017], but of course if they are removed by the user beforehand, it will fail...
Advertisement