How do I add 2 existing components to a new component?

Hey!

So I have a question that seams really easy (probably a brain fart on my end) but I just cant find the answer and its driving me crazy! I’m new to Ruby coding and still haven’t figured out all the details.

So I have created 2 components with ruby from 2 groups using the .to_component method. This works fine. So now I want to create a new component and add the 2 existing components into the new one, the new component should have no entities inside it, only the 2 existing components. I cant seam to figure out how to create a component without using the .to_component method. Any ideas?

This has been discussed several times in this category:

https://forums.sketchup.com/search?q=%23developers%3Aruby-api%20add%20existing%20components%20

Sketchup.active_model.selection[0].definition.entities.add_instance(definition, transform)

You can nest the components in one component using the SketchUp::Entities Class.
#add_instance(definition, transform) ⇒ Sketchup::ComponentInstance

#add_instance(definition, transform) ⇒ Sketchup::ComponentInstance

#add_instance(definition, transform) ⇒ Sketchup::ComponentInstance

#add_instance(definition, transform) ⇒ Sketchup::ComponentInstance

@nnijmeijer We really cannot add an instance of a definition to it’s own entities.
That would be circular reference.

You snippet does not show that the definition arg must be a new empty definition and transformation arg should be the transform of selection[0].

You do not need to do this.

You can create new empty component definitions with Sketchup::DefinitionList#add and then add geometry directly into it’s entities collection. Lastly add an instance of that new definition to whatever entities collection you desire (the model’s or some other definition’s entities collection.)

So if the 2 instances you are creating will always be your code’s creations then you’ve been doing it butt-backward. First create the empty parent definition. Then the child definitions. Add instances of the children to the parent’s entities collection, then add an instance of the parent to the model at some level.

1 Like

That’s right @DanRathbun.
You explained it well and completely.

With my response I tried to offer a possible programming direction.

I am aware that the snippit is not complete. But when I first started using Ruby, I actually liked figuring things out instead of copy-paste.

@DanRathbun thank you for your input! I’ll try it out next week when I’'m back home. Have I understod it correctly that I would have to add a new definition to the model.definitions (new_comp) and then add the other components (comp_A & comp_B) to the new components entities and lastly add a instance off the newly created component (new_comp) to the model? Wouldn’t that create 2 copies of comp_A & comp_B? The original ones and the new ones in the new_comp?

@nnijmeijer appreciate your input as well. Currently enjoying some time in the southern part of your wonderful country!

Yes to question 1, and …

Well I had said that IF you were creating instance A and instance B … then you might as well just create them as component definitions (instead of going through the group paradigm,) in which case no there would not be 2 copies of each.

But IF you are wanting to encapsulate existing instances in a component, then as I said in the 2nd post above, this has been discussed multiple times with multiple code snippets already posted. (See the category search link in that post.)

1 Like

Hey again @DanRathbun
So I got a version of the code working but only when using the .to_component method. I just can’t seem to understand how to do it “The Correct” way that you showed above. I wrote a bit of code that doesn’t work ( and is obviously incorrect) but “should” work the way I understand it. I created two new definitions, one Cube component and one Main component that should envelop two instances of the cubes. Can you or anyone else give me a hint of where my code is flawed, and how to correct it?

  model = Sketchup.active_model
  entities = model.active_entities
  definitions = model.definitions
  
  definitions.purge_unused #Just to make sure there are no existing definitions i the model
  main = definitions.add "Main_comp"
  cube = definitions.add "Cube_comp"
  
  x = 1000.mm
  pts = [
    [0,0,0],
    [x,0,0],
    [x,x,0],
    [0,x,0]
    ]
   
  face = cube.entities.add_face(pts)
  face.reverse!
  face.pushpull(x)
  
  main.entities.add_instance(cube,[0,x,0])
  main.entities.add_instance(cube,[x,x,0])
  
  entities.add_instance(main,[0,0,0])

The garbage collector here is aggressive about empty definitions. If you want to keep it “alive” you have to put something in it immediately! So, simple rearrange your code lines order… and it “should” work

model = Sketchup.active_model
entities = model.active_entities
definitions = model.definitions
definitions.purge_unused
x = 1000.mm
pts = [
  [0,0,0],
  [x,0,0],
  [x,x,0],
  [0,x,0]
  ]
cube = definitions.add "Cube_comp"
face = cube.entities.add_face(pts)
face.reverse!
face.pushpull(x)
main = definitions.add "Main_comp"
main.entities.add_instance(cube,[0,x,0])
main.entities.add_instance(cube,[x,x,0])
entities.add_instance(main,[0,0,0])
2 Likes

True, and often I will add a cpoint at the entities ORIGIN and delete it later after the geometry has been added.

2 Likes

@dezmo THANK YOU! You have no idea how long I’ve been scratching my head trying to figure out why it wouldn’t work. So if you don’t use a newly created definition right away and but something in it SketchUp deletes it? I guess it kind of makes sense thought, this way the model wont have a bunch of empty components associated with it.

Once again thank you, and thanks to @DanRathbun for giving a excellent explanation on the use of definitions.

1 Like

Yes, also the same for groups (as they are just a special type of component.)

And in the olden days before the API had a method to delete a specific definition from the definitions list, coders could delete all the entities of a definition and SketchUp would “clean it up” by dereferencing it so it was marked for garbage collection.

In the near future this “clean up” may seem even more aggressive as SketchUp updates to Ruby 3 which is advertised to be 3 times faster than Ruby 2.

1 Like

It’s not the Ruby garbage collector. It’s SkechUp that cleans up between operations. Since the sample code wasn’t wrapped inside of model.start/commit_operation it meant that every call to a method that modified the model could trigger this. This cleanup is suspended between model.start/commit_operation.

2 Likes

Interesting… Seams that I managed to create a rather specific senario were my code failed because if i wrap my previously posted code with a model.start_operation and a model.commit_operation it runs just fine. Thanks for helping to clear up my problem @tt_su

  model = Sketchup.active_model
  entities = model.active_entities
  definitions = model.definitions
  definitions.purge_unused #Just to make sure there are no existing definitions i the model
  model.start_operation("Test",true)
  
  main = definitions.add "Main_comp"
  cube = definitions.add "Cube_comp"
  x = 1000.mm
  pts = [
    [0,0,0],
    [x,0,0],
    [x,x,0],
    [0,x,0]
    ]
  face = cube.entities.add_face(pts)
  face.reverse!
  face.pushpull(x)
  
  main.entities.add_instance(cube,[0,x,0])
  main.entities.add_instance(cube,[x,x,0])
  entities.add_instance(main,[0,0,0])
  
  model.commit_operation

We stand corrected. :wink:

I wondered and was going to ask, but ya’ beat me to it.

I opened an API issue to add this tidbit to the documentation.