Create a subcomponent of a selected component

Hello,

I want to create a subcomponent from a component that is selected:

In this example I have selected a “Parent Box” which is an existing component and I want to create a method in Ruby which allows to create the "Child Box ".
I took the example of a box to keep it simple but the code must work with any selected component.

For the moment, I am able to create a Parent component to a selected component:

mod = Sketchup.active_model
ents = mod.active_entities
sel = mod.selection
selection = sel.grep(Sketchup::ComponentInstance)
selection.each do |s|
  grp = ents.add_group(s)
  ins = grp.to_component
  defn = ins.definition
  defn.invalidate_bounds
  defn.name = "Component#1"
  sel.add(ins)         
end

I need your help to do the opposite.

Thank you in advance for your help.

Is the Child component definition already defined ?

If yes, then …

parent = sel.grep(Sketchup::ComponentInstance).first
parent.definition.add_instance(child_def, ORIGIN)

Hello,
No, the definition of the child component is not defined.
So I need your help to define it.
Thanks in advance.

Then define it … definition objects are created using a factory method of the model’s DefinitionList collection. See:

Once the “child” definition exists, code can add instances of it to any entities collection, be it the model’s or one of the (group or component) definition’s entities.

1 Like

I can’t even import an instance into the scene with the “add_instance” method.

point = Geom::Point3d.new 0,0,0
transform = Geom::Transformation.new (point)
model = Sketchup.active_model
entities = model.active_entities
definitions = model.definitions
componentdefinition = definitions.add "Parent Box"
instance = entities.add_instance componentdefinition, transform
if (instance)
  UI.messagebox instance
else
  UI.messagebox "Failure"
end

I need your help to understand my mistake.

Thank you

The mistake is here:

entities is the model’s active entities, but should be a new component definition’s entities.

NOTE: It cannot be componentdefinition.enities as that would not be allowed as a circular reference.


(1) Do not insert spaces between a method call and it’s argument list as you did in:

(2) You should always wrap arguments for instance method calls in parenthesis. As in:

componentdefinition = definitions.add("Parent Box")

… etc., …

(3) Ruby is not JavaScript, conditional expressions do not need to be wrapped in parenthesis:

if instance

… not …

if (instance)

Thanks for your information Dan.

Despite your efforts in the explanations I did not manage to understand your method.

mod  = Sketchup.active_model
sel  = mod.selection
definitions = mod.definitions
ents = mod.active_entities
inst = sel.grep(Sketchup::ComponentInstance)
inst.each do |s1|
  @sel1 = s1
end
cmp1 = inst.first
def1 = cmp1.definition
copy = ents.add_instance(def1, IDENTITY)
inst = copy.make_unique
name = inst.definition.name
sel.clear
sel.add(inst)
sel.grep(Sketchup::ComponentInstance).each do |s|
  s.erase!
end
definitionadd = []
definitions.each do |d|
  if d.name == name
    definitionadd << d
  end
end
sel.add(@sel1)
point = Geom::Point3d.new 0,0,0
transformation = Geom::Transformation.new(point)
sel.grep(Sketchup::ComponentInstance).each do |s|
instance = s.definition.entities.add_instance(definitionadd[0], transformation)
end

So I tinkered with a code that works but that can be really simplified by those who master ruby in SketchUp:

Now that I have found a method that works I wouldn’t dwell on it again unless you publish a complete method that is simpler and does the same job.

A new empty definition would be created, and then you add an instance to this new empty definition.

NOTE: I corrected my previous post as I had indicated a circular reference, in error.


Your latest snippet has numerous errors and just detracts from the main issue, so I will not even attempt to critique that.

Precisely I do not know how to add my selected instance to the new definition which is empty.
To do this I would need an example.

We seem to be going 'round in circles. I asked you previously if the “child” was defined, and you said no. So I gave you a link so that you could create a new “child” component definition.

See the above post.

You can also create a new empty “parent” definition using the same method.

Now, you are talking about a “selected instance”.

I had stated in the same post where I asked if the “child” definition was already defined, that if so

Are you trying to make a copy of the selected component and place a copy (unique) of the parent inside the parent?

If so try this.

sel = Sketchup.active_model.selection
parent = sel.grep(Sketchup::ComponentInstance).first
child = Sketchup.active_model.entities.add_instance(parent.definition, ORIGIN)
child.make_unique
child_def = child.definition
child_def.name = "child box"
child.erase!
#if you want to remove the geometry from the parent component uncomment the line below
#parent.definition.entities.clear!
parent.definition.entities.add_instance(child_def, ORIGIN)

Copy

3 Likes

Well done Neil Burkholder you understood exactly what I wanted to do. :clap:

I made a last method shorter than the first but yours is even simpler and more efficient.

Here is where I was:

  mod  = Sketchup.active_model
  sel  = mod.selection
  sel1 = sel.first
  ents = mod.active_entities
  parent = sel.grep(Sketchup::ComponentInstance).first
  defn = parent.definition
  name = defn.name  
  copy = ents.add_instance(defn, IDENTITY)
  inst = copy.make_unique
  definitions = mod.definitions
  definitions.each do |d|
    if d.name == name
      d.entities.add_instance(inst.definition, ORIGIN) 
    end
  end
  sel.clear
  sel.add(inst)
  sel.grep(Sketchup::ComponentInstance).each do |s|
    s.erase!
  end 
  sel.add(sel1)

I will study your method in order to improve my knowledge.
_

Dan unfortunately we didn’t understand each other from the start.
Despite everything, your examples have allowed me to evolve.

3 Likes