SketchUp / api-issue-tracker

Public issue tracker for the SketchUp and LayOut's APIs
https://developer.sketchup.com/
38 stars 10 forks source link

See what scenes a section is used in #25

Open Eneroth3 opened 6 years ago

Eneroth3 commented 6 years ago

Being able to see how a section plane is used in a model would be useful, both for developers and users.

For instance it could be used to purge all sections not referenced by any scene. Currently as a SketchUp user I'm reluctant to add temporary cuts to better see what I'm working on, even though it's highly useful. These temporary sections can't be easily distinguished from the ones used by scenes that are referenced in LO, and manually deleting the former risks accidentally also deleting the latter causing lots of issues in the final drawing output.

Direct read access to the section/scene relations would also be very useful for extensions such as my Eneroth View Memory. Currently I have to iterate over all scenes and activate them in order to see what section planes they use.

A SectionPlane object could have a method that returns an Array of scenes referencing it. Scenes (Page objects) could also have a method that returns a Hash of all their active cuts, indexed by ComponentDefinition (or Sketchup::Model for the cut in the model root). Perhaps ComponentDefinition and Model could also have methods returning a Hash of contained SectionPlanes indexed by the Page referencing them.

Perhaps all mentions of ComponentDefinition above should really be Entities; this idea still isn't 100% finished.

DanRathbun commented 6 years ago

Firstly, I support this FR.

(a) Scenes (Page objects) could also have a method that returns a Hash of all their active cuts, indexed by ComponentDefinition (or Sketchup::Model for the cut in the model root).

This makes sense, as Page class already has method that return collections of "remembered" entities, like #layers(), #hidden_entities(), etc., as well as the other thing it remembers, ie, camera, style, shadow info, etc.

So this is a glaring omission.

But (it would make more sense to me,) if the hash indices (keys) were the section plane objects, and the values the "parent" object references. Especially if the method is named something like ... #active_cuts ... or ... #active_section_cuts

(And thinking about observer workarounds I see we are also missing an #onPageUpdate() observer callback. I'll file a separate issue for this. Tests show nothing firing when a page is updated.) ~

(b) A SectionPlane object could have a method that returns an Array of scenes referencing it.

#used_by_pages() ... or since a page only remembers "active" SPs and reactivates them when they themselves become the active page, how about ... #active_on_pages() ?

(c) Perhaps ComponentDefinition and Model could also have methods returning a Hash of contained SectionPlanes indexed by the Page referencing them.

(1) I think such a method would need to belong to the Sketchup::Entities class. But there is a caveat here. All section planes are in this collection, including those not "activated" (or remembered) by any scene page.

(2) The other problem with this muse is that hash keys need to be unique, and although only 1 section plane can be active per entities context, all section planes in the context could be active in some scene page, and some activated by multiple scene pages. So this eliminates a scene page object as the hash key. But you can do the opposite, since all of the SectionPlane objects in the entities collection are unique objects, they can be the hash key, and their value can be an array of the referencing Scene Pages.

I'd recommend that the method return ALL section plane child objects as keys, and that the value just be either an empty array or nil for unreferenced SPs ... #get_section_plane_references ... or, just ... #section_plane_references ... then checking the booleaness or emptiness of a hash member is basically a test if the SP is referenced. (Useful in the absence of a specific query method to ask if a SP is "activated" by any page.)

This method could leverage the one proposed in (b) above, calling it in a loop to build the hash.

(d) These temporary sections can't be easily distinguished from the ones used by scenes that are referenced in LO, and manually deleting the former risks accidentally also deleting the latter causing lots of issues in the final drawing output.

Scene names were added in the last version. (I remember filing a FR for this myself.)

I know it is a "hack" but you could prefix section plane names with "[TEMP]" so as to find them again more easily later.

temp_cuts = model.entities.grep(Sketchup::SectionPlane).find_all {|sp|
  sp.name.start_with?('[TEMP]')
}
model.definitions.each {|cdef|
  temp_cuts.concat(
    cdef.entities.grep(Sketchup::SectionPlane).find_all {|sp|
      sp.name.start_with?('[TEMP]')
    }
  )
}

Then mass hide or erase the collection. You might even implement and observer to "collect" such prefixed section planes dynamically ?

Eneroth3 commented 6 years ago

But (it would make more sense to me,) if the hash indices (keys) were the section plane objects, and the values the "parent" object references. Especially if the method is named something like ...

If we are discussing an instance method for Page it could just return an Array when I think of it. The parents can be easily found using the DrawingElement#parent method.

Regarding the Entities instance method, a method that lists section planes by scenes activating them would just be a shorthand to iterating all planes in the collection and list those being referenced by any page, by that page. That could probably be left out of the API itself as it is easy to code (and the API could focus on making data accessible rather than formatting it in various ways).

To sum it up:

SectionPlane#activated_by_pages returns Array of Page object that activates the cut. Page#active_cuts returns an Array of SectionPlane objects that are active in this scene.

I still don't use named planes. For quick temporary planes it goes against the whole quick temporary thing to have to spend time writing a name. For referenced cuts I think the name is somewhat redundant as it is the same as of the scene (and if I rename the scene, which I very often do, I don't want to have to rename all cuts too).

Eneroth3 commented 6 years ago

SectionPlane#activating_pages is probably an even better name.

DanRathbun commented 6 years ago

SectionPlane#activating_pages is probably an even better name.

Sure reduce the number of underscores and words.

Regarding the Entities instance method, a method that lists section planes by scenes activating them would just be a shorthand to iterating all planes in the collection and list those being referenced by any page, by that page. That could probably be left out of the API itself as it is easy to code (and the API could focus on making data accessible rather than formatting it in various ways).

This is true. However we usually ask for "factory" collectors / iterators when they'll work much faster on the C-side than on the Ruby-side. It is not out of the realm of possibility that we get these methods, as some have been implemented recently. Sketchup::Model#find_entity_by_id comes to mind. But the "use case" must show that implementing in Ruby cause excessive slow down. So methods used during animation, tools or other rendering situations are the best candidates.

If this doesn't fall into that realm, then ...

section_plane_references = Hash[
  model.entities.grep(Sketchup::SectionPlane).map {|sp|
    [ sp, sp.activating_pages ]
  }
]

... would work in a pinch.

I still don't use named planes. For quick temporary planes it goes against the whole quick temporary thing to have to spend time writing a name.

I'd think about coding a button that transparently added the prefix to the name. Another button could hide all the temp planes, another could erase them.

The main reason why they were given a name was so that they could be referenced in the Outliner. There was an issue where hidden section planes could not be found, and a name was the easiest way to find them. (There's a public forum thread on this from only last summer I think. I was surprised at how fast the "name" FR was implemented, but I suppose it was luck as they were overhauling the Outliner that cycle.)

thomthom commented 6 years ago

Logged as SU-38572

noelwarren commented 2 years ago

šŸ‘ +1 for this feature request Please also expose in C-API

clarkbremer commented 7 months ago

I would also like to see this feature. It came up again during the discussion of this bug