Issue with texture assignment

Hi, I am creating a series of materials, each assign to a specific texture, but can’t understand why the texture is not assigned to the material. This is an extract of the code. ts is a list of Time objects from which I generate the file names for the tectures;

timeseries.keys.each do |time|
  maps[time] = File.join('irradiation_' + time.strftime("%Y%m%d%H") + '.png')
  if materials[maps[time]] == nil
    puts 'Adding material' + maps[time]
    materials.add(maps[time])
  end
end

At this point I have all my materials. Now I want to assign the textures to the materials

maps.each do |time, texture_filename|
  mat = materials[texture_filename]
  puts mat.to_s
  puts 'Full path: ' + File.join(path, texture_filename)
  mat.texture = File.join(path, texture_filename)
  mat.texture.size = [width, height]
end

If I run the script I get the error:

Error: #<NoMethodError: undefined method `size=' for nil:NilClass>

So the texture has not been assigned. If I do the same manually, it works.

Any idea? Thanks

My guess would be: it fails at

mat.texture = File.join(path, texture)

because your variable texture is a name (like ‘brick’) and it still needs an extension (like ‘.jpg’)

Thanks Max. I don’t think that’s the issue. See how maps[t] is defined.

your code is a vary hard to follow…
can you provide an overview of your intent…
are you time stamping existing files to the use as textures?
use unique names for your vars to make it a little clearer, i,e, my_tex instead of texture [which is assigned to the method name]
john

You are actually right. Is it better now?

what does p mat[0] return, if you comment out the rest of that block?

It returns

Error: #<NoMethodError: undefined method `[]' for #<Sketchup::Material:0x007fd94aa58ba8>>

You are making a hash based on the time code as key and the matching PNG file as a string value.
You then create a new material [if needed] named after the hash string value.

I assume if you stop your code there are of the expected materials are in the model’s collection ?
If you try this does it work any better ?

maps.each{|a|
  time, texture_filename = a
  mat = materials[texture_filename]
  puts mat.to_s
  puts 'Full path: ' + File.join(path, texture_filename)
  mat.texture = File.join(path, texture_filename)
  puts mat.texture
  p 999
  mat.texture.size = [width, height]
}

I assume ‘width’ and ‘height’ are defined earlier ?
I assume the material ‘mat’ is listed properly.
What about the ‘texture’ reference before ‘999’

Yes. That’s correct. Unfortunately it gives the same error.

The materials are indeed assigned correctly. This is, as I expect, the output of materials.each{|m| p m.name}; nil

"sketchup_default_material"
"Material1"
"Material2"
"Material3"
"irradiation_2010062108.png"
"irradiation_2010062109.png"
"irradiation_2010062110.png"
"irradiation_2010062111.png"
"irradiation_2010062112.png"
"irradiation_2010062113.png"
"irradiation_2010062114.png"
"irradiation_2010062115.png"
"irradiation_2010062116.png"
"irradiation_2010062117.png"
"irradiation_2010062118.png"
"irradiation_2010062119.png"
"irradiation_2010062120.png"
"irradiation_2010062121.png"

Width and height are defined earlier and I have double checked their value.

puts mat.texture returns nil.

Could the problem be related to File.join?

Actually it seems to be related to File.join. From the console:

path = "/Users/ruggiero/RadCalc/rad/base2/Scenario#00-Baseline/radiance/outputs/HourlyPNG"
texture_file = "irradiation_2010062109.png"
materials["irradiation_2010062109.png"]
#<Sketchup::Material:0x007fde246e9060>

materials["irradiation_2010062109.png"].texture = File.join(path, texture_file)
materials["irradiation_2010062109.png"].texture
# nil

If I do instead

materials["irradiation_2010062109.png"].texture = "/Users/ruggiero/RadCalc/rad/base2/Scenario#00-Baseline/radiance/outputs/HourlyPNG/irradiation-map_2010062109.png"

I have what I would expect:

materials["irradiation_2010062109.png"].texture
#<Sketchup::Texture:0x007fde0d261a18>

In this case the texture is assigned.

enclose the File.join method and it should work…

materials["irradiation_2010062109.png"].texture = (File.join(path, texture_file))

it seems very odd to have the .png extension name in the Material name…

Unfortunately it doesn’t. Still empty texture.

The reason I keep the .png is that they are not actually materials, but results of a simulation generated by another program.

Try this:

maps.each{|a|
      time, texture_filename = a
      p mat = materials[texture_filename]
      p ipath = File.join(path, texture_filename)
      p File.exist?(ipath)
      p 666
      mat.texture= ipath
      puts mat.texture
      p 999
      mat.texture.size = [width, height]
}

This will tell you the image’s file path AND if it exists…

Since we don’t know the path there might be an issue with encoding ?
What is ‘path’ ?
Can you try this earlier on [inserted just after you have set up ‘path’]:

if defined?(Encoding)
  begin
    opath = path
    path  = path.force_encoding("UTF-8") ### >= v2014 lashup
  rescue
    path = opath
  end
end

This should resolve accented characters in the path, wherever possible, but it needs the newer Ruby available with >= v2014…

you are using two different paths, when you see File.join fail…

path = "/Users/ruggiero/RadCalc/rad/base2/Scenario#00-Baseline/radiance/outputs/HourlyPNG"
texture_file = "irradiation_2010062109.png"

test_path = File.join(path, texture_file)
test_path == "/Users/ruggiero/RadCalc/rad/base2/Scenario#00-Baseline/radiance/outputs/HourlyPNG/irradiation-map_2010062109.png"

returns false because the second has -map in the name…
@TIG, the filepaths are mac, so I doubt encodings an issue…
john

1 Like

Well, this is embarrassing…

It was just invisible at my eyes! Thanks guys and sorry for wasting your time.