Is this possible with a Ruby Script?


#1

I’m currently at the bottom of the learning curve with Ruby in the hope to solves some functionality I wish was included as a standard with Sketchup.

Basically I want to make a script to control the placement and scale of certain textures. While there are workarounds (using individual dynamic nested sub components which copy rather than using a component with a textured face which scales), I feel there must be a way to write a script that can do the following - and effectively create a texture which always locks to a particular ‘real world’ scale.

This is what I’d like the script to do

  1. Find entities (components) with a particular texture.
  2. Find how these component instances have been scaled & in which direction (x,y,z)
  3. Adjust the scale of the textures within each of the instances so the scale of that particular texture is increased or decreased by that amount.
  4. Find the reference point for the texture within the component in relation to the reference point of the same texture outside the component & adjust the position accordingly so they match.

With a long road ahead to learn Ruby, can anyone tell me if this would be achievable or am I setting my goals a little too high. Any feedback would be welcomed…

  • I’d also be happy to add an attribute option for texture scale in the dynamic component if this helps…

#2

There may be a basic flaw in your thinking. All component instances reflect the definition of their parent. In order for the materials to be scaled differently, each must have it’s own unique material applied (even if they share the same texture originally from the same image file.) In this scenario then each instance could not be a sibling from the same definition.
If the material was applied in the definition, that would mean making each instance unique, which creates a new unique definition, and duplicating the material for each new instance.

OR the definition does not have materials applied, and instead the instances each have their own scaled material copy applied.

So either way, since API-wise, it is the Texture instance (inside the Material instance,) that has size properties, each unique scaled instance will need a unique material instance with a uniquely scaled texture specified for it.


But if the geometry is simple, exploding and re-grouping (after the scale operation) and re-applying the original material might work. (But you run the risk of edges and faces intersecting the model. Doing all this within a temporary group might help.)


Anyway, for 1…3 I think it’s is possible.

(4) I am not sure what the “reference point” is supposed to be. All groups and component instances have an 3D origin point accessible via their transformation accessor. I think textures are applied beginning at the origin.


#3

BTW… there are a couple of extensions that may help you:

http://extensions.sketchup.com/en/search/site/texture


#4

Thanks Dan. I really appreciate your feedback…

I’m am currently trying to resize within the Dynamic Components so would prefer not to explode and re-group - which is what I am currently doing in my normal workflow, but I’m trying to use more DC’s with the ability to resize as needed and then report on the nested components & attributes for Bill Of Materials.

The only reason I mentioned the reference point in (4) was my belief that textures are positioned in relation to a point. Although this point (3D origin point) within a scaled or unscaled DC would differ to that of the original texture instance, I was hoping I could calculate the difference in position & scale of the DC and move this reference point to line up with others - even if it meant adding a few hidden points in the DC so the 3D origin was always in the same position.

Again… I’m just putting it out there so I really appreciate any feedback or ideas - I’ll definitely check out the link you’ve put in your response.

I’ve also added a link to one of my first DC files if anyone is interested…

You’ll see in 2 of the DC’s I’ve nested the Basic Wall within the DC as a nested component (weatherboards don’t line up)
and 2 more where I’ve exploded the Basic Walls within the DC so they do line up - This might be an option…

Select the DC options to change wall height - as the wall is stretched it adds studs and nogs, you can aslo increase top plate width (nog spaces) and so on…


#5

They would have to be ConstructionPoints on a hidden layer. (SketchUp does not have orphan point objects in the model; only cpoints and the vertices of edges and faces.)

Basically you need to play with a simplified scenario. Just one face in the model, with a textured material applied.
Scale it, then duplicate the material, apply the duplicate, and reverse scale the new material’s texture. … all using code.


#6

Thanks Dan. Sure, Construction points would work - thanks for the tip. I’m working on a few other scripts at the moment but will let you know how I get on with this one once I get on to it. And I’ll follow your simplified scenario so I can hit any brick walls early in development before spending too much time on the idea.

It would be so good if Sketchup ever brought a feature like this in - a ‘world’ scaling and positioning option for either components, groups or the texture itself… Maybe one day…


#7

On a similar vein, and as a newb to both scripting and the forums while trying to keep this in the right topic…

Is it possible to script “send to layout” as a final operation. I might also need to know how to script a “save as copy” with incremental file name.


#8

Actually the topic is about controlling textures.

Windows ONLY: Sketchup::send_action( 23051 )
If there is a cross-platform string for it, I couldn’t figure it out.

The save task requires it’s own topic.


#9

Thanks Dan, I’ll keep researching, and when I find a solution I’ll be sure to post it to the correct topic page.


#10
Sketchup.send_action("sendToLayOut:")

works on mac, does it on Win…

john


#11

No it returns false on Windows.
But that gives us a cross-platform method

def send_to_layout()
  return nil unless Sketchup.is_pro?
  if (Sketchup.respond_to?(:platform) &&
  Sketchup::platform == :platform_win ) ||
  RUBY_PLATFORM !~ /(darwin)/i
    Sketchup::send_action( 23051 )
  else
    Sketchup::send_action("sendToLayOut:")
  end
end

EDIT: inserted Pro only bailout statement to return nil if not SketchUp Pro.