SU2018 Renamed material not found

bug

#1

I have discovered a strange bug - a renamed material cannot be found with the new name, but it can with old name!
Can someone replicate it? I have deleted all the plugins, but it still is there.

Open default template with Stacy. Rename Stacy_Skin to Stacy_SkinRenamed and run following:

Sketchup.active_model.materials.each {|mat| puts mat.name}
Stacy_SkinRenamed
Stacy_Shirt
Stacy_Shoe
Stacy_Shoe_Laces_Sole
Stacy_Hair
Stacy_Pants

Sketchup.active_model.materials.each {|mat| puts Sketchup.active_model.materials[mat.name].class}
NilClass
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material

Sketchup.active_model.materials.each {|mat| puts Sketchup.active_model.materials[mat.display_name].class}
NilClass
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material

puts Sketchup.active_model.materials[“Stacy_Skin”].class
Sketchup::Material


#2

Tested on SketchUp Pro 16.1.1449 (Win7+SP1 x64)
bug is not present (I used Lisanne and material "Lisanne_Bandana" for the test.)

Tested on SketchUp Pro 2018 - bug is confirmed.


#3

On Mac (10.13.6), SketchUp Version 18.0.16976:

> Sketchup.active_model.materials.each {|mat| puts mat.name}
Stacy_SkinRenamed
Stacy_Shirt
Stacy_Shoe
Stacy_Shoe_Laces_Sole
Stacy_Hair
Stacy_Pants
#<Sketchup::Materials:0x007fa3f1782160>
> Sketchup.active_model.materials.each {|mat| puts Sketchup.active_model.materials[mat.name].class}
NilClass
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material
#<Sketchup::Materials:0x007fa3f1782160>
> Sketchup.active_model.materials.each {|mat| puts Sketchup.active_model.materials[mat.display_name].class}
NilClass
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material
Sketchup::Material
#<Sketchup::Materials:0x007fa3f1782160>
> puts Sketchup.active_model.materials[“Stacy_Skin”].class
Error: #<NameError: undefined local variable or method `“Stacy_Skin”' for main:Object>
<main>:in `<main>'
SketchUp:1:in `eval'

> puts Sketchup.active_model.materials['Stacy_Skin'].class
Sketchup::Material

> puts Sketchup.active_model.materials['Stacy_SkinRenamed'].class
NilClass

Note: Changed the double quote in the last two expressions


#4

Great. Thanks for confirming.
The issue is present in SketchUp 2018 (2018.0.16975/6). I have made the test in SU2017 Pro and it was fine.

It means materials["MaterialName"] is not reliable in SketchUp 2018. I recommend writing a custom search function iterating through materials[index] and comparing names.

Btw. The new material name is recognized when the same model is saved and reopened.


#5

Yes, that is correct. SU2018 have a regression where obtaining materials by name might fail. The techincal reason for this is that a performance improvement was added to looking up names (dramatically improving performance in some cases with models with large amount of materials).

Yes, the cache is rebuild upon restarting. So this only affect the current session - not the model.

However, there are cases where this cache can get out of sync in SU2018. This is a known issue and on our radar.

The workaround is to look up the material yourself:

model.materials.find { |material| material.name == material }

I’m about to release a patch for some of my own extensions to address this. This is how I implemented a helper method:

module Example
  # Workaround for bug in SketchUp 2018 where obtaining materials by name might
  # fail even if the material exists.
  #
  # @param [Sketchup::Materials] materials
  # @param [String] name
  # @return [Sketchup::Material]
  if Sketchup.version.to_i == 18
    def self.get_material(materials, name)
      materials.find { |material| material.name == name }
    end
  else
    def self.get_material(materials, name)
      materials[name]
    end
  end
end

That way there is only a conditional evaluation when the file is loaded, but not when it’s invoked.