This is quite easy to do but in most cases a bad idea. The user will not expect entities outside of the active drawing context to be selected. In my view this should only be done in the extreme case when the whole point of the plugin is to be able to select outside the current drawing context. If the purpose of the plugin is something else itās better to find another solution.
# Select an instance and run snippet to select all child instances.
def select_children(instance)
children = instance.definition.entities.select { |e| e.respond_to?(:definition) }
instance.model.selection.add(children)
children.each { |c| select_children(c) }
end
select_children(Sketchup.active_model.selection.first)
Just FYI, this (above) will select both Sketchup::ComponentInstance and Sketchup::Group instances within SketchUp 2015 and higher. (Before that release Sketchup::Group did not have a definition method.)
But, this is usually want you want when dealing with Dynamic Components as they extensively use nested groups.
You cannot select sub-components for only one top level component instance. This is because instances do not āownā entities or sub-component instances. Only definitions do. So if you select sub-components, you are selecting them in ALL of that furniture definitionās instances.
You have asked a similar question [under another guise] over in SketchUcation.com !
As I explained some days agoā¦ why do you need to add entities to the selection-set that span various entities contexts.
You can do nothing with them.
Working across contexts cross-threads things and a BugSplat will almost certainly resultā¦
You can add entities you find across contexts into a ācollectionā - say an array or a hash - and do something to them.
However, since a selection is intended to be applied to the active context, then using it across various contexts is a bad idea - unless perhaps you specifically intend the selection to temporarily show such objects, without changing them - e.g. you collect things to change in an array, and then add those things to a selection āmomentarilyā, so when the user confirms the selection is cleared and the changes are effected in some other wayā¦
Looks like you are modifying the collection you are iterating. That can lead to issues.
Also, bulk select/erase is faster.
For instance:
# Don't do this. You are erasing from the collection you are iterating.
entities.each { |e| e.erase! if e.hidden? }
# This is safer
entities.to_a.each { |e| e.erase! if e.hidden? }
# This is safer and faster
hidden = entities.select { |e| e.hidden? }
entities.erase_entities(hidden)
Similarly with modifying selections:
# This is slow
faces.each { |face| model.selection.add(face) }
# This is faster
model.selection.add(faces)
Itās still not clear to me why you need to select the entities deep into the instances. Your code seems to be making a selection as well as erasing stuff. Why is it doing both?
I am not able to combine method 1 and method 2, to remove the dynamic attributes, components and sub-components of the selection.
def select_children(instance)
children = instance.definition.entities.select { |e| e.respond_to?(:definition) }
children.each { |c| select_children(c);
c.erase! if c.hidden?
}
end
def methode1
select_children(Sketchup.active_model.selection.first)
end
def methode2
m=Sketchup.active_model;
m.start_operation("unDC");
m.definitions.each{|d|d.attribute_dictionaries.delete("dynamic_attributes") if d.attribute_dictionaries and d.attribute_dictionaries["dynamic_attributes"];
d.instances.each{|i|i.attribute_dictionaries.delete("dynamic_attributes") if i.attribute_dictionaries and i.attribute_dictionaries["dynamic_attributes"]}};
m.commit_operation
end
I would like to allow the user to remove all the dynamic attributes of the components present in a selection.
I am really confused of what you are trying to achieve. First you asked about selecting entities and now you are removing attributes? What is the purpose?
Iām a bit confused here. Removing attributes has nothing to do with selecting entities. The selection is a specific part of the user interface that is quite irrelevant here (except for the top level component that the user selects before running the script).
Iāve been thinking for a while about making a plugin that turns dynamic components into regular components myself but never gotten around to di it. Not to save file size though, I donāt think it would make much difference, but to make the components easier to work with and to be able to call the plugin De-DC-ify (I find that name funny). However I ran into an Israeli fellow the other week (canāt remember the name, sorry) who had already made that plugin so now Iām prioritizing other projects.
The biggest problem to overcome here is to make all components present inside the component to de-DC-ify unique so instances elsewhere in the model arenāt affected. Thatās really the only thing that has to be solved to make the plugin.
Regarding your current code it would be much easier to understand it and help you if you styled it properly. With the end keyword not properly indented, closing curly bracket on its own line while the code block and open bracket share the same line, and arbitrarily placed semi-colons the code becomes really hard to read. It would also be easier to help you if you wrote method names in English instead of your local language so we could compare what the methods actually does with what you expect them to do (based on how youāve named them).
You currently have 3 methods. This is what they currently do.
The first adds all components, groups and images in the selected group or component to the selection and calls itself recursively on them.
The second one makes every single component in the whole wide model un-dynamic. And it does it in individual operators which can add hundreds of operations to the undo stack.