Assigning Layers in SU directly vs. Assigning by Script

layers

#1

Hello everybody - Please excuse my amateurish ignorance as I ask…

I’ve been trying to develop a script that will automatically look at all model entities, take all the entities in a particular Layer, and group those entities by Layer. So far so good, but I also decided to add a function to assign all entities in the group to Layer0 (with the group itself assigned the Layer in question), but the process seems to take unusually long…

For comparison sake, I took my model with 36,000+ entities and, in the Entity Info window, assigned them all Layer0, it takes less a second.

However, when I type in this bit of code into the Ruby Console, it takes well over 5 minutes to reach the same results:

 ents = Sketchup.active_model.entities
 ents.each{ |i| i.layer= "Layer0" }

Am I missing somthing basic in my workflow? Thanks for your time,

-Antonio


#2

Try assigning the actual Layer object rather than the name of “Layer0”. That may save you a conversion from a String to Layer for each iteration of the loop.

ents = Sketchup.active_model.entities
layer = Sketchup.active_model.layers[0]
ents.each{ |i| i.layer= layer }


#3

One thing is you should create a edit operation and use the disable UI refresh argument.

model.start_operation("Group as Layer0",false)

EDIT: Jim beat me to the post.

You would likely get a bit more speed by getting the object reference to the layer named “Layer0”, and then reuse it within the iteration block. Currently you are making SketchUp do this conversion with each loop through the block:

model = Sketchup.active_model
ents = model.entities
target = model.layers["Layer0"]
model.start_operation("Group as Layer0",false)
  ents.each {|i| i.layer= target if i.layer != target }
model.commit_operation

Your code only works upon the model’s toplevel entities. It will not go through the entities belonging to group or component definitions.


#4

Be aware SketchUp does not have geometric layer collections. So the entities are not “in” nor “on” a layer. Instead, they have a “layer” property that points at a layer object in the layers collection. A layer object is a property sheet of display behavior that can be shared amongst many entity objects.


#5

Definitely this - especially if the Outliner is open.


#6

Jim, Dan - Thank you both for some excellent feedback.

I tried out the variation where the “each” iteration assigns the Layer object directly, without having it do a string conversion, but I wasn’t able to save much time (at least with my rudimentary method of looking at the Windows system clock, rounding to the nearest 5 seconds)

The variation with the UI refresh disabled seems to be ticket - the results were as immediate as going through the Entity Info menu. And here I thought the “start_operation” method was only useful for making the Undo stack more convenient…

Worth mentioning though - after snooping around the Sketchup Ruby API, I changed one of the values in your example code in the start_operation method:

… excuse the vernacular :sweat_smile: - it’s really quite tricky to think like a developer after years of being an end user for so many years.

Thanks again for everything!


#7

Yea, a brainfart. I meant true,… hehe.

No. If you don’t use them in an extension, it’ll be rejected by the preliminary review of the Extension Warehouse. (So get in the habit of using them.)

Use the Ruby Time class.

model = Sketchup.active_model
ents = model.entities
target = model.layers["Layer0"]
model.start_operation("Group as Layer0",true)
  start_time = Time.now
  ents.each {|i| i.layer= target if i.layer != target }
  end_time = Time.now
model.commit_operation
elapsed_time = end_time.to_f - start_time.to_f