How Can I Copy a Projected Texture With Ruby Script

Hi all,

In Sketchup I can manually make a texture one face1 “projected” and use the eyedropper tool to to copy that texture onto another face2. The texture is then already “projected” on face2. I want to do this same thing, but with ruby script.

With ruby script I know how to apply a texture to face1 and use face1.set_texture_projection(face1.normal, true) to make the texture “projected”. But, I cannot find a way to copy that texture onto face2 and have it already be “projected.” Is there any way to do this with ruby script?

The context is that I want to take a face that is normal to a curve, apply a texture to it, make the texture projected, and then “eyedrop” that texture onto the curved face so that it does not get distorted.

Any feedback would be great, thanks.

Hmmm, noting that the docs say this method never worked correctly, and is deprecated.

Have you tried …

frontside = true
face2.material= face1.material
face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )

:question:


ADD: A method (needs testing) …

See @sdmitch's correction below.
def copy_projected_face_material(face1,face2)
  unless face1.material.nil?
    frontside = true
    face2.material= face1.material
    face2.set_texture_projection( face1.get_texture_projection, frontside )
  end
  unless face1.back_material.nil?
    frontside = false
    face2.back_material= face1.back_material
    face2.set_texture_projection( face1.get_texture_projection, frontside )
  end
  nil
end

Just need to add (frontside) to the .get_texture_projection I think

def copy_projected_face_material(face1,face2)
  unless face1.material.nil?
    frontside = true
    face2.material= face1.material
    face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )
  end
  unless face1.back_material.nil?
    frontside = false
    face2.back_material= face1.back_material
    face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )
  end
  nil
end
2 Likes

Thanks for the suggestions guys. Here is the code I’m using to test this. I tried the copy texture suggestion, but it seems like it isn’t applying any texture to face1. Any reason for this?

# Create 2 parallel faces
pts = []
pts[0] = 0,0,0
pts[1] = 0,0,50
pts[2] = 50,0,50
pts[3] = 50,0,0
face2 = Sketchup.active_model.active_entities.add_face pts

pts[0] = 0,50,0
pts[1] = 0,50,50
pts[2] = 50,50,50
pts[3] = 50,50,0
face1 = Sketchup.active_model.active_entities.add_face pts

#find the file path to the texture/material
path = Sketchup.find_support_file "Cinder Block.skm", "Materials/Brick, Cladding and Siding/"

#Load the material
materials = Sketchup.active_model.materials
material = materials.load(path)

#Apply the material to face1
face1.material = material

#Make the texture projected on face1
face1.set_texture_projection(face1.normal, true)

#Copy projected texture from face1 to face2
def copy_projected_face_material(face1,face2)
    unless face1.material.nil?
        frontside = true
        face2.material= face1.material
        face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )
    end
    unless face1.back_material.nil?
        frontside = false
        face2.back_material= face1.back_material
        face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )
    end
    nil
end

That’s because you def’d copy_projected_face_material, but you never invoked it!

2 Likes

Yes, you’d need to call it thus …

copy_projected_face_material(face1,face2)

P.S. - Ruby should use 2 space indents.

1 Like

Sorry for the formatting issues and stupid mistakes, I am new to Sketchup and the ruby API. So that code works for my flat faces, but would it be possible to apply the projected texture to the created face on a curved object created with a followme command? See the code below and the pictures of my current result.

  model = Sketchup.active_model
  entities = model.active_entities
 
  texture_path = Sketchup.find_support_file "Cinder Block.skm", "Materials/Brick, Cladding and Siding/"
  materials = Sketchup.active_model.materials
 
  wallmat = materials.load(texture_path)
 
  #Draw the face for the texture - face
  pts = []
  pts[0] = [412.788708358203, -439.271997369409, 0]
  pts[1] = [437.268708358203, -462.311997369409, 0]
  pts[2] = [437.268708358203, -462.311997369409, 7.75]
  pts[3] = [412.788708358203, -439.271997369409, 7.75]
 
  #Add the face To the entities In the model
  face1 = entities.add_face(pts)
  face1.material = wallmat
 
  edges = face1.edges
 
  #Project texture 
  face1.set_texture_projection(face1.normal, true)
 
  #Draw the block -  side face
  pts19 = []
  pts19[0] = [659.519881381513, -177.119993425486, 0]
  pts19[1] = [659.425889486804, -165.12036153431, 0]
  pts19[2] = [659.419509333829, -164.30582867111, 7.75]
  pts19[3] = [659.513501228538, -176.305460562286, 7.75]
 
  entities19 = model.active_entities
  face2 = entities19.add_face pts19
 
  #create test curve to follow
  ptsSpine19 = []
  ptsSpine19[0] = Geom::Point3d.new(659.519881381513, -177.119993425486, 0)
  ptsSpine19[1] = Geom::Point3d.new(663.114, -177.3192, 0)
  ptsSpine19[2] = Geom::Point3d.new(664.4076, -177.9048, 0)
  ptsSpine19[3] = Geom::Point3d.new(665.7396, -178.278, 0)
  ptsSpine19[4] = Geom::Point3d.new(667.0488, -178.7208, 0)
  ptsSpine19[5] = Geom::Point3d.new(668.3328, -179.2344, 0)
  ptsSpine19[6] = Geom::Point3d.new(669.5868, -179.814, 0)
  ptsSpine19[7] = Geom::Point3d.new(670.8096, -180.4608, 0)
  ptsSpine19[8] = Geom::Point3d.new(671.9952, -181.1724, 0)
  ptsSpine19[9] = Geom::Point3d.new(673.2816, -181.7388, 0)
  ptsSpine19[10] = Geom::Point3d.new(678.5112, -186.6876, 0)
  ptsSpine19[11] = Geom::Point3d.new(679.1472, -187.9404, 0)
  ptsSpine19[12] = Geom::Point3d.new(679.9224, -189.0852, 0)
  ptsSpine19[13] = Geom::Point3d.new(680.6364, -190.2696, 0)
  ptsSpine19[14] = Geom::Point3d.new(681.2844, -191.4912, 0)
  ptsSpine19[15] = Geom::Point3d.new(681.8676, -192.744, 0)
  ptsSpine19[16] = Geom::Point3d.new(682.3824, -194.0268, 0)
  ptsSpine19[17] = Geom::Point3d.new(682.8288, -195.336, 0)
  ptsSpine19[18] = Geom::Point3d.new(683.6028, -196.5816, 0)
  ptsSpine19[19] = Geom::Point3d.new(683.969052265305, -199.881189894678, 0)
 
  edge = entities.add_curve(ptsSpine19)
 
  #Copy projected texture from face1 to face2
  def copy_projected_face_material(face1,face2)
    unless face1.material.nil?
      frontside = true
      face2.material= face1.material
      face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )
    end
    unless face1.material.nil?
      frontside = false
      face2.back_material= face1.material
      face2.set_texture_projection( face1.get_texture_projection(frontside), frontside )
    end
    nil
  end
  copy_projected_face_material(face1,face2)
 
   #Create a solid from from the block face
   face2.followme(edge)


What happens if you soften or smooth the inner edges on the curved surface ?

Is there any specific code that can smooth the inner edges?

edge.smooth= edge.soft= true

N/M, sdmitch solved it. (I thought your had treated all faces, but I missed that you hadn’t.)

1 Like

Even though you project the texture onto face2, that doesn’t transfer to the faces created by the followme obviously. I have modified the code so that the texture is projected on to all the faces.

copy_projected_face_material.rb (3.1 KB)

2 Likes

This is exactly what I’m looking for. Thanks for all the help guys, I learned a lot!

1 Like

There is currently no way to properly set texture projection in the Ruby API (Or C API).

.set_texture_projection isn’t working correctly and will produce a model that will trigger “Fix Model” dialog. It’s deprecated and might be removed completely when new features that correctly handle projected textures are added. (Normally API features are not removed, but this created invalid data and should not be used.)

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.