Is there some kind of "set parent" method to "move" a Group inside a container?

In my experience scripting in Vectorworks, there was a way of ‘moving’ an object from inside a container to another one, a function called SetParent.

I would like a method to move a Group inside a ComponentInstance, like a user would at the Outliner window!

I need to point out an error in your thinking.

Component Instances do not “have” entities. It is Component Definitions that “have” (or “own”) an entities collection.

All instances of a certain definition will share the parent’s entities collection.

So you’d actually move a group instance, into a definition’s entities collection.

Perhaps something like:

cdef.entities.add_instance( grp.definition, grp.transformation )
grp.erase!

But there was some caveat concerning context. I cannot remember off hand what it is.

Perhaps @TIG knows ?

1 Like

Thanks Dan!

I understand your point, the container is the ComponentDefinition not the Instance (a mere reference placed in the drawing).

I’m doing exactly the .add_instance thing, using group.entities.parent for versions before 2015.

Is this the only way? For instance (no pun intended), adding a component to a container/ComponentDefinition I lose the ‘externally’ applied materials…

Cheers!

To ‘Move’ a group into another context and keep all of its original ‘properties’ - so it appears you have haven’t actually ‘Copied’ it - you make references to them apply them to the new ‘instance’, then erase the original group…

grp ### the reference to the original group
newgrp = cdef.entities.add_instance( grp.entities.parent, grp.transformation )
newgrp.material = grp.material
newgrp.layer = grp.layer
newgrp.name = grp.name
attds = grp.attribute_dictionaries
attds.each{|d|
  n = d.name
  d.each_pair{|k, v|
    newgrp.set_attribute(n, k, v)
  }
} if attds
### you can also transfer any other properties like hidden?, locked? etc
grp.erase!
4 Likes

Wow! Thank you so much for the code!

Am I wrong or does this Bugsplat if cdef is not Sketchup.active_model?

I suppose that depending on what cdef actually refers to it might BugSplat, and that would be a bug because SketchUp should trap and reject illegal operations. But I tried setting cdef to be the ComponentDefinition for a group and grp to be another group, and it ran correctly without a BugSplat. What were the classes and validity status of the objects referenced by cdef and grp when you got the BugSplat, and were there any prior relationships between them such as nested in the same parent?

I’ve never had such a bugsplat and I quite often add instances to groups and components.

1 Like

Really? But what about…

@ TIG Move all entities to new group

Maybe I misunderstand what is being warned against.

Are we talking about add_instance or add_group now? I’ve gotten the latter to crash by passing entities not in the active drawing context, but never the former.

Correct.
You can add_ geometry etc, or instances of component definitions or groups into any entities context - i.e. to the model.entities, model.active_entities, and group.entities and definition.entities
A new group can be added to any entities context using gp = some_entities.add_group()
If ents==model.active_entities you can also add the new group with entities [just as you might manually]
e.g. gp = model.active_entities.add_group(model.selection.to_a)
BUT if you try that in an entities context that’s not ‘active’ it’ll BugSplat!
In such a case you must first add a new empty group, and then add things into its entities collection afterwards…

Oh yeah right, I got confused and remeber that add_instance() seems to be less perilous/tricky.

if you try that in an entities context that’s not ‘active’ it’ll BugSplat!

So if I am editing a particular group and call something not at the active context, say at the root level…

gp = model.entities.add_group(model.selection.to_a)

That will crash.

AND vice versa

If I am at the root level and I call something not at the root level…

gp = some_group.add_group(model.selection.to_a)

That will crash too, right?

In your example:
gp = model.entities.add_group(model.selection.to_a)
it will BugSplat if the model.entities are NOT the model.active_entities
That’s because the manually created* model.selection is taken from the model.active_entities, and if you are inside a group/component edit when you invoke that code you would be trying to add a group containing those selected things outside of that context [i.e. directly in the model’s entities] - thereby cross threading the data-base.
*You can add objects to the model’s selection across entities contexts using the API but there is almost never a need to do this and a BugSplat awaits you if you try to use that cross-threaded selection !

Your second example is wrong:
gp = some_group.add_group(model.selection.to_a)
But you cannot add a group to some other group, you can add a group to some other group’s entities collection - e.g.
gp = some_group.entities.add_group(model.selection.to_a)
And provided that the selection is in the some_group.entities context you’re OK.
However, a ‘check’ on the contexts might be safer…
gp = some_group.entities.add_group(model.selection.to_a) if some_group.entities==model.active_entities
If you know that some_group.entities is NOT the model.active_entities context, then you must find another way of adding the selection into a new empty group within some_group.entities
gp = some_group.entities.add_group()
If the selected object is a group[s] or a component-instance[s] you can add new instances into ‘gp’, thus:
new_group = gp.entities.add(selected_group.definition, selected_group.transformation)
That ‘copies’ the group into the other context.
If you want to ‘move’ it, then you can simply erase the original with selected_group.erase!
Leaving the copy in place…
To copy ‘geometry’ you can recreate that inside the other non-active groups entities context…

1 Like

If you experience any crashes, please log them in out API issue tracker: Issues · SketchUp/api-issue-tracker · GitHub