Details of components within components

I’m trying to get attribute values of components within components. I’ve searched for a while, and getting close, but stuck. My application is drawing bookshelves for a room. I’ve made various component definitions to do this: room, base cabinet, base top, and bookshelves. For example, for one of multiple base cabinets, I create a “Base” definition and give it a name (e.g., “BaseOuterLeft”) and then add an instance of it. This “Base” definition’s body creates a component definition (called “Solid”, so I end up with components called Solid, Solid#1, Solid#2, etc.) for each base part (left side, right side, back, etc.) with unique dimensions. I want to list my final part sizes. I currently can get dimensions, but I need to associate them with the actual part (e.g., BaseOuterLeft, back).

How can I attach a name to each part?

Code/results:

Current dimensions gotten with:

> Sketchup.active_model.entities.each {|entity| puts entity.class.name; puts entity.definition.name; entity.definition.entities.each{|ent| puts ent.typename; puts ent.bounds.width; puts ent.bounds.height; puts ent.bounds.depth}}
. . .
Sketchup::ComponentInstance
BaseOuterLeft
ConstructionPoint
0"
0"
0"
ComponentInstance
1' 11 1/4"
3/4"
2' 1/2"
ComponentInstance
1' 11 1/4"
3/4"
2' 1/2"
ComponentInstance
3/4"
2' 7"
2' 1/2"
. . .
. . .

Without seeing the rest of your code, I can’t say for sure where you needed to do so, but as you create a new ComponentDefinition you can assign it a meaningful name via its .name= method, and when you place a ComponentInstance you can assign a meaningful name to the instance via its .name= method. All your snippet is doing for the nested instances is printing their typename, which is (doh!) ComponentInstance, so it doesn’t even show the ComponentDefinition names that SketchUp auto-generated. And if you are reusing a Component to nest instances in a different parent, you can do so without creating a new ComponentDefinition each time, as the names Solid, Solid#1, etc. suggest you are doing.

BTW: It isn’t a good practice to cram so many code statements onto a single line like that. It makes it very hard to read and does nothing to improve performance.

1 Like

Thanks for the info. Yeah, "isn’t a good practice to cram ", I agree. This was just me manually poking around in the Ruby console. In my interrogating line, in the entity for loop, I was trying ent.name, but it doesn’t exist. So, assuming I assign names to nested definitions and instances, could you show me a general form of accessing the appropriate name? Thanks again.

You can test whether an object responds to a given method like …

if ent.respond_to?(:definition) # it's a group or component instance
  unless ent.name.empty?
    puts ent.name
  else
    puts ent.definition.name
  end
else # it's a primitive or complex (dimension, section plane, etc.)
  if ent.respond_to?(:typename)
    puts ent.typename
  else
    puts ent.class.name
  end
end

The ComponentDefinition #name method retrieves the name of the component definition.
The ComponentDefinition #name= method is used to set the name of the component definition.

The ComponentInstance #name method is used to get the name of this instance.
The ComponentInstance #name= method is used to set the name of this instance.

1 Like

Thanks to all. I folded in some "respond_to"s and"empty"s and my entity.definition.entities handling is much more robust, although still slightly tuned to my specific style of components built from lower level components, so still need to beef it up. But does all I need right now. Thanks again.

  7 model.entities.each {|entity|
  8   if entity.respond_to?(:definition) # it's a group or component instance
  9     unless entity.name.empty?
 10       puts ("entity name:"+entity.name)
 11     else
 12       puts ("entity definition name:"+entity.definition.name)
 13       entity.definition.entities.each{|ent|
 14         if ent.respond_to?(:definition)     # skip Cpoints (can still be more robust below)
 15           puts ("  "+ent.definition.name)
 16           puts ("    width ="+ent.bounds.width.to_s);
 17           puts ("    height="+ent.bounds.height.to_s);
 18           puts ("    depth ="+ent.bounds.depth.to_s);

entity definition name:BaseOuterLeft
  left side
    width =1' 11 1/4"
    height=3/4"
    depth =2' 1/2"
  right side
    width =1' 11 1/4"
    height=3/4"
    depth =2' 1/2"
  back
    width =3/4"
    height=2' 7"
    depth =2' 1/2"
  bottom
    width =1' 10 1/2"
    height=2' 7"
    depth =3/4"
  left stile
    width =3/4"
    height=1 1/2"
    depth =2' 1/2"
1 Like