I have for example 4 component instances (all from the same component definition).
In Sketchup, if I select 2 components, right click, and make them unique. I will end up with 2 component definitions with 2 instances per each definition.
That’s good! It’s what I want.
How can I replicate this behavior with a selection of components in ruby?
What I really want to do, is loop over all entities within a component. And make them all unique from their instances in other components, but not unique from each other…
Just using instance.make_unique within the loop, makes each and every one of them unique… not what I want.
Now make other instances [if any] of their definitions unique - UNLESS they are in ents
instances.each{|i|
next unless i.definition.instances[1]
i.make_unique unless i.parent.entities == ents
}
So now if you have two instances in ents they are still referencing the same definition, but all other instances in other entities contexts will now be unique…
Hi Neil,
That’s an interesting one. In what practical situations would you use that?
If all the instances have the same parent… It’s like they are all in the same component? so it wouldn’t make a difference… would it!? Unless the parent is maybe a… group? (this stuff is confusing :))
[quote=“Yoni, post:5, topic:36660”]
next unless i.definition.instances[1]
[/quote] If the instance’s definition has only one instance, then there is no need to make it unique [there’s only one already], so we skip it with the ‘next’.
The likelihood is that the API will itself skip over the unnecessary make_unique anyway, but in case it doesn’t [to avoid hiccups], and also to save a nano-second of processing time, you might as well skip processing it yourself…
Sorry, I misread one of your lines Neil, and thought you meant something else (I’m not even sure anymore what it was I was imagining ;))
It seems like both your code and TIGs are doing what I asked. I’ve adapted it to a little plugin I’m working on. Hope to release it soon.
Looking at the code again, in both suggestions, the scripts make all ‘unrelated’ instances unique instead of making only the selected instances or their sub-components unique.
In TIG’s code, all instances in other parents are made unique of each other (or at least that’s what happens in my adaptation).
In the animation that Neil posted, in each ‘Big Box’ the small boxes are becoming unique (small_box#1 x 6, small_box#2 x 6, small_box#3 x 6… etc.).
I wouldn’t want my operation on one Big Box and it’s sub-boxes affecting the similarities of the small boxes in the other Big Boxes…
If I were to ‘select’ manually (with the mouse) one Big Box, ‘right click’, ‘make unique’. Go into it, and select 6 small boxes, ‘right click’, ‘make unique’, it still only makes those selected unique, without touching anything else outside of context. I wish to replicate that exact function in Ruby without messing with other components “by accident”.
Or, if I were ‘forced’ to mess with all other components (I’d rather not), I would want to maintain all similarities outside my selection. (including in multiple nested levels).
def make_selection_unique
inst = Sketchup.active_model.selection.grep(Sketchup::ComponentInstance)
if inst.count == 0 then end
inst[0].make_unique
pdef = inst[0].definition
inst.each do |i|
i.definition = pdef
end
end
a. inst.empty? is one method call that does not use a literal, whilst inst.count == 0 is two method calls. The count method is called returning a reference to an integer, whose == method is called passing the literal 0 by reference into it (where a comparison is made.)
b. I am always wary of having too many end keywords in the file.
(Have gotten too many SyntaxErrors on files, with messages like “unexpected end” or “missing end”, etc.)
Thanks Dan. Neil, in your last suggestion, if the selection had multiple instances, with different definitions, it would turn them all into instances of one definition (the first) - which is unlike how the ‘right click’ - ‘make unique’ works.
With the tips from all of you, I think I managed to get what I want.
The following code works almost like the ‘right click’ - ‘make unique’, except when making a selection of ALL similar instances (all in selection are of the same definition) - It still makes them all unique (adding a new definition), instead of ignoring them. (why add new definitions if no need to).
def make_sel_unique
def_hash = Hash.new
sel = Sketchup.active_model.selection.grep(Sketchup::ComponentInstance)
return if sel.empty?
sel.each { |i|
# if the instant's definition exists in the hash
# assign to it the new definition value (new_def).
if def_hash.key?(i.definition)
i.definition = def_hash[i.definition]
else
# If not in the hash - make unique while adding to the hash the
# definitions - before & after making unique - {old_def -> new_def}
old_def = i.definition
i.make_unique
new_def = i.definition
def_hash[old_def] = new_def
end
}
return nil
end