Convert component to group


#6

This topic is covered in “Entities.add_group causes Bugsplat!

It shows an script originally posted by TIG, but modified to avoid a bugsplat when the component included an arc or curve.
Dan R advised that its better to add the component instance to a new group, then explode the instance thats inside the group.

If the instance has just been created, then all of the logic to preserve attributes, layers, shadow characteristic, material, scale masks etc, may not be relevant.
But you still might want to purge the compoennt definition from appearing the in “In Model” component panel.

Since the only difference between a component instance and a group is a hidden flag in accessible to the API, you do need to go through all of this to accomplish the task unfortunately.
Also it would be nice if Model.import which results in a component had an option to import as a group. This would again avoid the need for conversion.


#7
my_instance = my_group.to_component
my_definition = my_instance.definition

???


#8

Was also going to post this link. (Barry beat me to it.)
Pay special attention to the last post by TIG, which explain a non-explode way.
(But you’ll still need to do the property and attribute copying part. Then erase the cinstance, a lastly the definition purge.)

Here’s another related topic:
Move all entities to new group

This is butt-backward to what he wants.

And at one time this method (to_component) was bugged in that it dropped all the attribute dictionaries (perhaps other properties.) Was it ever fixed ?


To_group Method?
#9

@Dan is right :blush:
I must read the problem more carefully…

However, as @Dan has linked I also produced the fix for component > group situation…


#10

Thanks guys.
I did see those threads, but I can’t get to the result I’m after.

Here’s my snippet so far :

def self.remove_subcomps(definition)
	definition.entities.each{|e|
		if e.is_a?(Sketchup::ComponentInstance)
			self.comp_to_group(e, definition)
		elsif e.is_a?(Sketchup::Group)
			self.remove_subcomps(e.definition)
		end#if
	}
end#def

def self.comp_to_group(inst, parent_group_def)
	entities = inst.definition.entities
	group = parent_group_def.entities.add_group(entities.to_a)
	inst.erase!
end #def

Sketchup.active_model.start_operation("Remove subcomponents", true)
self.remove_subcomps(Sketchup.active_model.selection[0].definition)
Sketchup.active_model.commit_operation

I attached a test model with the groups/comps hierarchy I’m working with. Check the outliner.
comp_to_group.skp (126.4 KB)

I want to select the top-level group (“group_lvl1”) and convert all subcomponents to groups.
When I do select the top-level group and run the above snippet, new groups are created in the root context, not in the context of the subcomponents. (I don’t mind about the transformation at this point, I’ll resolve that later)
That’s why I came here.

Any idea what I’m doing wrong?

PS : Also, I get a bugsplat when I undo this operation.


#11

Well the first issue is that you are violating the cardinal rule of collections. You cannot modify the collection at the same time you are iterating it.

Solution, create an array copy, and iterate the copy, so that the iteration reference will not loose it’s way, ie:

definition.entities.to_a.each{|e|

#12

(2) The way youv’e written this:

… is actaully the same as this (ie, the 2nd parent_group_def argument is not needed):

def self.comp_to_group(inst, parent_group_def)
	entities = inst.definition.entities
	group    = entities.add_group(entities.to_a)
	inst.erase!
end #def

So, look at the “group =” statement:

group = entities.add_group(entities.to_a)

… in which your trying to add the group into the collection that you want to encapsulate IN this group.


#13

Thanks Dan, although that doesn’t seem to fix the issue.


#14

No, “inst” is nested in “parent_group_def”.
What you say would be true if I called
self.comp_to_group(e, e.definition)
But I’m calling
self.comp_to_group(e, definition)
"e" is part of “definition.entities”. It’s not an instance of “definition”.


#15

Ok I see, but as TIG had explained (I thought) the group and the entities need to be in the same context, and they are not. The group and the parent of the entities are in the same context. So then, BugSplat would not be uncommon.


#16

Oh? I must have skipped that.

Then this should work? But it doesn’t, it still creates groups in the root context.

def self.remove_subcomps(definition)
	definition.entities.to_a.each{|e|
		if e.is_a?(Sketchup::ComponentInstance)
			self.comp_to_group(e)
		elsif e.is_a?(Sketchup::Group)
			self.remove_subcomps(e.definition)
		end#if
	}
end#def

def self.comp_to_group(inst)
	entities = inst.definition.entities
	entities_ary = entities.to_a
	entities.add_group(entities_ary)
	group = inst.explode[0]
end #def

Sketchup.active_model.start_operation("Remove subcomponents", true)
	self.remove_subcomps(Sketchup.active_model.selection[0].definition)
Sketchup.active_model.commit_operation

#17

NO !
You are missing a vital point.

group = entities.add_group()

safely makes an empty group in ANY entities context.
You can then add objects into that group.entities context.

entities.add_group(entities_ary)

will only work if the entities reference is pointing to the model.active_entities.
It cannot point at some other entities context - even if the array of entities is in the same entities context as your new group…
You will get BugSplats.


How about this less risky approach ?
entities = inst.parent.entities
group = entities.add_group()
temp = group.entities.add_instance(inst.definition, inst.transformation)
group.layer = inst.layer
group.material = inst.material
group.locked = inst.locked?
group.hidden = inst.hidden?
### perhaps copy over attribute dictionaries too ?
inst.erase!
temp.explode

To_group Method?
Copy Group and Rename Layers
#18

I see, thanks.

Which involves exploding the component. This is what I wanted to avoid.

Thanks for the help guys, I guess I’ll stick with exploding.


#19

Yes it would be so much simpler if the API had a to_group() instance method of the ComponentDefinition class, that would convert it to a group definition without all this rigmarole and exploding. All the definition’s instances then would become group instances, and there’d be no need to copy attribute dictionaries and native properties.


To_group Method?
#20

I’m not sure I understand. I do what I think you want all the time. When something is already a group or a component, select it and explode it. Without doing anything else first, now take the highlighted entities, right click and make them into the other, from a component to a group or vice versa. I rarely use components, only when I decide to build something and keep it for further use, like a table or door. If I just need things to stay separate, I use groups almost exclusively. Occasionally I regret having a group if I discover changes I hadn’t thought of, and now must change each group separately. Balusters for example would be drawn once as a group until all details are complete, then copy as many as you need. With components, you’d distribute the copies first, and finish the details later, but I prefer doing it the first way.


#21

Robert, I wanted to convert components to groups in code, without exploding (which is slow).


#22

I thought it was too easy, but after reading a related post, figured this was ‘other worldly’. In the '90s, when we needed code for websites or macros or something, we always copied it from elsewhere. Too complicated otherwise.


#23

@Robert5643, if you look up at the topbar (with the topic title and icons on the right,) you’ll see under the title, a breadcrumb list of categories. It indicates that this thread is in the Ruby programming sub-category, of the Developers category.

So, we always are talking about doing things via code in here, and answering a question in these categories with a manual procedure is just “noise”. (So you’ve earned your first “off-topic” flag.)


#24

This would be super helpful! Any progress on this plugin? My primary need is to be able to convert the 3000+ components that come in with a revit import into groups, thus speeding up the skp component library itself, which in-turn speeds up vray turnaround time… along with general housecleaning benefits. Thx for looking into this one.


#25

Agreed that this would be very helpful. I also have the problem of dealing with really component heavy Revit Imports that freeze my component library and prevent me from further importing the updated model into 3ds Max because of some x86 limit. If anyone discovers a simple code or plugin to replace all components with groups, please post it here! Exploding is not an option either as it causes too many problems with faces, materials and layers… and just take too long. Thanks.


Problem with a model imported from Revit