Hi Folks,
I’m writing a script to delete unused section planes as an aid to working with large models and drawing sets
I’ve so far been able to get a script to work by walking through the scenes via the pages.selected_page method and using an if loop to find the section planes to delete.
Its is possible to determine if a section plane is active in a scene directly. Ideally, I would not like to activate every scene?
It’s often useful to post the code you have, and an example skp…
people short on time are more likely to test yours and modify if they know [or suspect] a solution…
john
I’m on my tablet so I’ll do the best I can.
I’m currently doing something like this puesdo code.
Getting it to work is not the issue. I’m wondering if there’s a cleaner way to do it.
#make a list of section planes to delete later
Pages = SketchUp.model.pages
List = grep(SketchUp::section_planes)
#walk through and activate each scene
Pages.each { |page|
Pages.selected_page = page
#iterate through list of planes, remove from list if
#active
List.each { |section_plane|
If section_planes.active?
List.delete.section_plane
End
}
}
#delete whatever is left in the list array
List.each { |section_plane|
section_plane.erase!
}
Activating the scenes is really slow if animations are turned on. It’s not a huge deal to turn them off. That said I’d like to query the API about what is active in each scene without activating the scene. I’ve run into a roadblock here and am wondering if there is any insight.
I will assume that your tablet is capitalizing all lines.
Variables should not be constants. (In Ruby constants begin with a capital letter.)
(1) So, you cannot call Enumerable#grep()
upon nothing. It must be called upon a collection object whose class has mixed in the Enumerable
library module.
(2) There is no master collection of just Sketchup::SectionPlane
instance objects. They are a Sketchup::Drawingelement
subclass, and as this they can be a member of any Entities
collection. This means either the model’s top level collection of entities, or of the entities collection of definitions (as images, groups and component instances do not themselves “own” entities.)
So, a., either iterate the DefinitionsList collecting the section planes,…
cutplanes = model.entities.grep(Sketchup::SectionPlane)
model.definitions.each {|cdef|
cutplanes.concat( cdef.entities.grep(Sketchup::SectionPlane) )
}
or b., collect all section planes in the ObjectSpace, and filter out those that do not belong to the active model:
cutplanes = []
ObjectSpace.each_object(Sketchup::SectionPlane) {|obj|
cutplanes << obj if obj.model == Sketchup::active_model
}
The concept of active and used are different. Just because a section plane is not active at any given time, does not mean it is unused.
You have already noted that scene pages can switch planes on and off, and you’ve handled that well by first keeping any section plane that is activated by scene changes.
But section planes can also be activated by extensions, or created manually for use in a single “Work” scene. Your example would brute force remove these.
Perhaps present the user with a list of Section Planes to confirm deletion ? (We have requested that they get a “name” attribute.)
… or, one by one, show and select the section plane, zoom to selection, then ask the user whether to delete the shown plane ?
confusion is what I get for trying to write code on a tablet after a long mountain bike ride…
I had meant to say I had a working code similar to the “code” I typed in. What I stumped on, is finding away to search for active section planes without activating the scene. Any thoughts?
I agree with you from your above post. In this case, the simplicity is fine for me, I’ll sometimes have to deal with a model that looks like a sea of gray and just want it gone. In my particular case, I very infrequently work with extensions that use section planes and would know when to be careful.
Below is my working code.
#make a list of section planes to delete later
pages = Sketchup.active_model.pages
entities = Sketchup.active_model.entities
list = entities.grep(Sketchup::SectionPlane)
#walk through and activate each scene
pages.each { |page|
pages.selected_page = page
#iterate through list of planes, remove from list if
#active
list.each { |section_plane|
if section_plane.active? == true
list.delete(section_plane)
end
}
}
#delete whatever is left in the list array
list.each { |section_plane|
section_plane.erase!
}
Your code ignores section planes inside groups and components.
Catch-22. The plane cannot be active until the scene is set as the current view.
You may also need to implement a FrameChangeObserver
, to delay the active? test until the scene is done rendering.
Also, what I usually do in cases like this is switch page transitions off (saving the old value and restoring it afterward.)
model = Sketchup::active_model
prev = model.options["PageOptions"]["ShowTransition"]
model.options["PageOptions"]["ShowTransition"]= false
afterward:
model.options["PageOptions"]["ShowTransition"]= prev