No, incorrect ! This lists only the material objects that have already been loaded into the model’s materials collection. Not what is on disk in the various “Materials” directories.
It is already in the model’s memory at that point.
Only if the user has clicked the house icon, and is looking at the “In Model” materials collection.
Computer platforms differ. MS Windows and MacOS are different in their filesystems and where they organize user and program data files.
It is a situation that programmers must deal with.
And the location of material files is only 1 of many differences you will need to deal with as a SketchUp extension programmer.
No, it is not that simple. It depends upon whether the user wants to use a material that is already in the model, or is still on disk in one of the material repositories.
Listen, it is not the same for Ruby. You’ll just need to realize this. You did do the correct thing in having the API find the file …
filename = 'Materials/Asphalt and Concrete/Blacktop Old 01.skm'
path = Sketchup.find_support_file(filename)
This was shown you in the API documentation.
Yes, …
# Within some method...
filename = 'Materials/Asphalt and Concrete/Blacktop Old 01.skm'
materials = Sketchup.active_model.materials
matl_name = File.basename(filename,".skm")
matl = materials["[#{matl_name}]"]
if matl.nil? # not in model materials collection, load it:
begin
matl = materials.load(Sketchup.find_support_file(filename))
rescue => err
put err.inspect
end
end
return unless matl
No … let the API give your code the file path as shown above. It is cross-platform.
I really love Sketchup. A big reason is a logical similarity between programing and normal usage.
About this topic.
When I say User Material List I mean the following picture.
This menu is all available materials that come from hard disks. SU doesn’t list only materials that users used before. When a user one of the materials just select and use it.
1- Is it possible for SU team to do the same way for programmers?
I believe the answer is “YES”.
2- Is it difficult?
I believe the answer is “NO”.
This is just a suggestion.
The answer is no. Because it would be a waste of time and effort.
As shown above a programmer can load any of the distributed materials.
If you wish to, it is rather easy to use the core Ruby Dir class to search through the material collections on disk and return the file path.
Example …
# Returns the absolute path to a material name query,
# or nil if the named material was not found.
def get_material_path(matl_name)
# Search User Materials first:
user_path = Sketchup.find_support_file("Materials")
found = search_materials(user_path, matl_name)
if !found # Search ProgramData Materials:
matl_path = Sketchup.find_support_file("Materials/Colors")
prog_path = File.dirname(matl_path)
found = search_materials(prog_path, matl_name)
end
return found
end
# Recursively searches the material path given for the named material.
# Do not include the .skm extension, just the name.
def search_materials(matl_path, matl_name)
skm = File.join("**", "*.skm")
skm_files = []
Dir.chdir(matl_path) { skm_files = Dir.glob(skm) }
rel_path = skm_files.find do |file|
File.basename(file,'.*') == matl_name
end
rel_path ? File.join(matl_path,rel_path) : nil
end
Hello Mr. Dan,
This code doesn’t work on MAC. Can you help me with it?
I write following code in MAC
mt_dir = Sketchup.find_support_file("Materials")
p mt_dir
#"/Users/majidmahmoudi/Library/Application Support/SketchUp 2018/SketchUp/Materials"
prog_mt_dir = mt_dir.dup
p prog_mt_dir
#"/Users/majidmahmoudi/Library/Application Support/SketchUp 2018/SketchUp/Materials"
Dir.chdir(prog_mt_dir) do
# Directory change.
Dir.glob("**/*.{skm,SKM}") do |mt|
p mt # This code never executed.
end
#
Also Following code…
mt_dir = Sketchup.find_support_file("Materials")
Dir.chdir(mt_dir.dup)
p Dir.pwd
# "/Users/majidmahmoudi/Library/Application Support/SketchUp 2018/SketchUp/Materials"
files = Dir.glob("**/*.skm")
p files
#[]
First of all, I do not have a Mac, so I cannot help with strange Mac quirks.
Why are you using the Array#<< method and not assignment ?
And if it is because of a dynamic constant assignment error, then this should tell you that using a constant reference is likely the incorrect solution.
Try using a module @var instead.
The most likely reason you did not see the print filename statement get called is the materials directory folder is empty.
You can test the directory thus … if Dir.exist?(prog_mt_dir) && !Dir.empty?(prog_mt_dir)
You can also insert a … puts Dir.getwd
… statement inside the Dir.chdir block to test that the working directory has been changed.
Again shows that the user’s materials directory is empty.
This is normal if the user has not yet saved any custom materials locally to their account.
What is wrong with the example methods I gave you above ?
Hello.
If the directory is empty why following code works in MAC and material add in list? By using this method I can add any material. For sure directory is not empty and materials are there.
mat = Sketchup.active_model.materials
@f_mat = nil
filename = 'Materials/Stone/Carrera Marble.skm'
mat_name = File.basename(filename,".skm")
@f_mat = mat["[#{mat_name}]"]
if @f_mat.nil?
begin
@f_mat = mat.load(Sketchup.find_support_file(filename))
rescue => err
@f_mat = "yellow"
end
end
I don’t have 2018 installed on this Mac, but Dir.glob works for the other versions I have.
In the last example snippet @majid866 gave, it works because Sketchup.find_support_file finds the distribution material within the SketchUp app bundle, for example in SU 2021:
But that’s an entirely different location than the user materials folder in Application Support. Further, if the user has set a location via Preferences->Files, that’s yet a third place a skm could be, and find_support_file doesn’t probe it.
Thanks Steve. This is what I thought. And is why I did this …
… in the example methods above. Ie, I purposefully used a subfolder (“Colors”) that I knew would be in the Program Data path and then stripped that subfolder off in the next statement.
Just an idea, if that matters to you in your present case…
It may not be necessary to load all materials.
If you use UI.openpanel method, the users can browse and select the one they want.
To get these “nice” thumbnails of materials, of course, assumes that the .skm file association is properly done to Sketchup… in an operating system level. At least on Windows. I 'have No idea about Mac.
The code snippet:
mat = Sketchup.active_model.materials
mat_path = Sketchup.find_support_file("Materials/Colors")
prog_path = File.dirname(mat_path)
chosen_material = UI.openpanel("Open Material File", prog_path, "Material Files|*.skm;*.SKM;||")
if chosen_material
last_loaded_material = mat.load chosen_material
puts last_loaded_material.name
# do something with last_loaded_material
else
puts "No material selected."
# do something else
end