Ruby Group Copy - Regardless of Context?
-
Hello All,
I have created a script the copies groups on a certain layer, call them target groups to a new temporary group I am planning to use for later shenanigans. The trouble I'm having is that the add_instance method needs the transformation of both the target group I am copying AND the parent. HOWEVER, sometimes the target groups will be nested in other groups and sometimes they won't. Sometimes they could be nested many times over.
How would I create a transform argument that somehow "senses" the nesting level of the entities being copied in in order to preserve their original position?
Here is what I have so far, which seems to work at only one nesting level.
Sketchup.active_model.definitions.each{|defn| #puts "definition name; #{defn.name} | layer; #{defn.layer.name}" defn.instances.each{|inst| inst.definition.entities.each{ |defn_inst| if(defn_inst.layer.name == "OPENING_PRIMITIVES") puts "defn_inst; #{defn_inst} name; #{defn_inst.name} | layer; #{defn_inst.layer.name}" @@temp_opening_primitives.entities.add_instance(defn_inst.entities.parent, inst.transformation*defn_inst.transformation) end } } }
Honestly, this seems like an overly complicated way to do this. I wish there was a way to quickly say "give me everything on this layer and copy it to a temporary group." Having to loop, then loop again, going back and forth between the instance and the definition bends my head in knots. As best I can tell from this forum though, this is the way I guess.
-
OK folks, I figured it out... how long has it been? A week or so. Jeez! Anyway, I found this thread where Thomas answered a similar question:
https://groups.google.com/forum/#!topic/sketchupruby/pyHIRLEm6Mc
I could not get it to work for my purposes as written so modified it as shown in my reply. I've tested it to 4 levels and seems to be working. Hopefully this is helpful to someone.
-
@hank said:
I wish there was a way to quickly say "give me everything on this layer and copy it to a temporary group."
Just FYI, SketchUp layers are not like CAD layers. (They are IMO mis-named.)
SketchUp layers are nothing more than behavioral display property sheets, that any entity can point at, in order to know how to "act" with regard to display behaviors.In SketchUp layers do not have entity collections, so objects are not "on layers." So this is why you cannot quickly iterate a layer's entity collection, as it doesn't have one.
And yes, transformations of nested objects are a PITB.
-
Thanks Dan.
So it sounds like really what I am doing is saying
give me entities whose layer property is 'X'
Right?And regarding...
@unknownuser said:
And yes, transformations of nested objects are a PITB.
I am glad I'm not alone in that sentiment!
-
@hank said:
So it sounds like really what I am doing is saying
give me entities whose layer property is 'X'
Right?YES.
And this is almost what you are doing in the nested iteration loops above.
Except that you are being inefficient. You are creating a new literal string in each loop, and doing SLOW string comparison in each loop. You should do fast object comparison.Outside and before the loops, check the layers collection for a layer named "OPENING_PRIMITIVES", and get it's object reference in a local variable. Then use that reference for comparison inside the loop.
if defn_inst.layer == target_layer
Another thing you should do is not assume the entity subclass type inside the loop.
(You use the ref namedefn_inst
, but I will useobj
in this example, because there are many different subclasses of entity in the entities collections.)Always have a "bail out" conditional expression, thus:
next unless obj.is_a?(Sketchup::Group) || obj.is_a?(Sketchup::ComponentInstance)
Otherwise in the few statements a call upon the objentities
method will raise an exception for primitives (or any other entity subclass object that doesn't have this method.)
Another way of safeguarding in Ruby, is a conditional "bailout" that tests if an object can respond to a method name:
next unless obj.respond_to?(:definition)
When the loop's block tests these kind of conditionals and they evaluate true the loop will cycle from there immediately to the next iteration.
-
Thank you Dan!
Advertisement