Apply .jpg image as a texture to a face

I am trying to apply a texture from an image to square but the resulting texture is not a texture, but simply a black colour. My code is as follows:

square = entities.add_face [[0,0,0],[50,0,0],[50,50,0],[0,50,0]]
texture_path = Sketchup.find_support_file 'Corrogated_Iron.jpg', 'C:\path_to_material\Corrogated_Iron.jpg'
materials = model.materials
corro = materials.add "Corro"
corro.texture = texture_path
square.material = corro

This is Corrogated_Iron.jpg:
Corrogated_Iron

And this is the result:


but it should look like:

What is wrong with my code?

FOR ANSWER: See below second last quote in answer for…the answer.

Seems I have to apply a colour first?

square = entities.add_face [[0,0,0],[50,0,0],[50,50,0],[0,50,0]]
square.material = Sketchup::Color.new 'Gray'
square.material.texture = 'C:\path_to_material\Corrogated_Iron.jpg'

This works fine, and with a lot less code?

However what is wrong with my last code? Because here: Adding Named Textures to Face; it seems like bartmandude had no troubles?

I’m guessing texture_path = Sketchup.find_support_file 'Corrogated_Iron.jpg', 'C:\path_to_material\Corrogated_Iron.jpg' didn’t find the file and returned nil.

In your second example you used an absolute path.

Btw, Sketchup.find_support_file is meant only to find files that ship with SketchUp.

It works for both.

matl_path = Sketchup.find_support_file 'Siding Rusty Metal.skm', 'Materials/Brick, Cladding and Siding'
#=> "C:/ProgramData/SketchUp/SketchUp 2018/SketchUp/Materials/Brick, Cladding and Siding/Siding Rusty Metal.skm"
matl_path = Sketchup.find_support_file 'Plywood.skm', 'Materials/Custom Wood'
#=> "C:/Users/Dan/AppData/Roaming/SketchUp/SketchUp 2018/SketchUp/Materials/Custom Wood/Plywood.skm"

Although I’m not sure which it checks first, the ProgramData or the User’s AppData paths.

@Poyda Faces drawn on the ground plane are facing down.
So face.material= in your examples will paint the underside which is the face’s front.

the examples have ALWAYS said it is for finding any file in a SU resolvable path…

it will be very bad if this has changed, recently or is even if it’s planned to be change…

help_file = Sketchup.find_support_file("help.html", "Plugins/")

john

Aah…does this mean they need to be *.skm files? cause I’d extracted the *.jpg file, and was using that

A texture object uses an image (file.)
A material object has a texture property.

When you build a material (.skm) file it has within it (being a zip archive) a few XML files containing color, aspect ratio and scaling information, etc, and a resources subfolder that contains the texture image(s).

Then you do not need to recreate the material each time via code. Just load the SKM file into your model, and paint faces (or components.)

It’s not that they “need” to be. But there is are standard places for .skm files (as I’ve shown above,) but not standard disk locations for texture images files.
So, material (.skm) files are better because they were invented to be used by SketchUp as a neat wrapped up package containing the texture and information on how to apply it surfaces. (An image file alone doesn’t have the usage information.)

If you can avoid using jpg, use png instead. Jpg are lossy and do not scale well.

1 Like

Observe the following:

class TestCube
  def the_test(a, toolbar_photo)
    roof = [[0,0,0],[a,0,0],[a,a,0],[0,a,0]]
    model = Sketchup.active_model
    entities = model.active_entities
    draw_face = entities.add_face roof
    draw_face.reverse!

    draw_face.material = Sketchup::Color.new 'Gray'
    draw_face.back_material = Sketchup::Color.new 'Gray'
    draw_face.material.texture = toolbar_photo
    draw_face.back_material.texture = toolbar_photo

    draw_face.pushpull a
  end
end
 
class ToolbarCreator
  def toolbar_maker(toolbar_name)
    toolbar = UI::Toolbar.new toolbar_name
    toolbar_photo = "Script_Resources\\Corrogated_Sheet.jpg"
  
    cmd = UI::Command.new(toolbar_name) {
      TestCube.new.the_test(50, toolbar_photo)
    }
    cmd.small_icon = toolbar_photo
    cmd.large_icon = toolbar_photo
    cmd.tooltip = toolbar_name + " Toolbars"
    cmd.status_bar_text = toolbar_name
    cmd.menu_text = toolbar_name
    toolbar = toolbar.add_item cmd
    toolbar.show
  end
end

toolbar_name = "Test"

ToolbarCreator.new.toolbar_maker(toolbar_name)

In this code, the toolbar creator has no problems with adding the *.jpg to the toolbar, but will not add it as a material.texture. The only way I can get that to work is if it is an absolute path.

Any suggestions as to why?

(The reason I need to use the *.jpg and a relative path, is because this will be shipped over to others computers, to be used by them)

It hasn’t changed, but that’s the purpose of it, find resources that ship with SketchUp.

There is no need to use it otherwise.

I’ve seen quite often that people use it to resolve a path to SU’s Plugins folder with the assumption that their extension is installed there. Which isn’t always the case if a user installs the extension at the different location either manually or using managers like SketchUcation’s Plugin Manager.

If you have the path where a file is located there is no need to use Sketchup.find_support_file since you already know where the file is.

If you want to resolve a path to a file within your extension installation path, build paths using __FILE__ or __dir__.

I beg to differ, agreeing with John. I believe you are reading too much into old, outdated and incorrect API documentation. Ie, the phrases that say “… of a file within the SketchUp installation directory.”
The way the 2 SketchUpfind_support_…” module methods worked was overhauled with the SketchUp 2014 release, but the documentation wasn’t. Even some of SketchUp’s own “distro’d” files were moved out of the installation directory.

Which is false as I showed above a valid reason.

This is not what I was really discussing above with respect to finding skm files. We were discussing getting the location of resource files because the code does not know exactly where they are, because resource file locations have changed o’r the versions, and making an incorrect assumption is poor programming practice.

So we properly ask the API to find the files. If it does great, if not nil is returned.

I do agree that using File.dirname(__FILE__) or __dir__ (for ruby 2+) is safer for an extension’s own files.

The icon setter methods (assuming a relative path from the extension’s folder path) have always been a deviation from the norm, and always cause me confusion. The documentation does not properly explain what kind of filepath argument is allowed.

The norm for most all file I/O operations is that filepaths are first checked if they resolve to a valid absolute path, and if not, then are checked to see if they can find a valid filepath relative from the current working directory. (You can get this from Dir::getwd or Dir::pwd class methods.)

Since your code cannot trust other extensions to reset the working directory, you have 2 options.

1. Temporarily change the working directory before making file I/O method calls using chdir

texture_file = 'Corrogated_Sheet.jpg'
resources = 'Script_Resources'
texture_path = File.join( resources, texture_file )
Dir::chdir(__dir__) do
  # Now in the folder path of the current running Ruby file ...
  draw_face.material.texture = texture_path
  draw_face.back_material.texture = texture_path
end
# Now back in the previous working directory path.

2. Use absolute paths …

texture_file = 'Corrogated_Sheet.jpg'
resources = 'Script_Resources'
texture_path = File.join( __dir__, resources, texture_file )
# It doesn't matter what the current working directory is,
# ... because absolute paths to the texture files are given:
draw_face.material.texture = texture_path
draw_face.back_material.texture = texture_path

Other people’s computers can use PNG images better than JPG images.

Looking in the *.skm files shipped with sketchup I noticed the material icons are *.png but the actual image themselves are *.jpg?