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)

4 Likes
Well done Neil Burkholder you understood exactly what I wanted to do. 
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