Here's my proposal, mostly relevant to point 2. Many elements of this proposal have been influenced by my experiment called Part-o-magic.
0. Container tree or container graph?
With tree, it is easy to figure out the container path to an object given just the object. That makes things simpler, because otherwise we must implement link type that will track changes to container tree. And in general, I think this makes things simpler and easier to manage overall.
As for full graph support for containers, it's not clear to me, what it should be used for. Multiple instances of same part? Like:
Code: Select all
Part
solid1
solid2
Part001
solid1
solid2
If that is supposed to present two instances of the same part, it's unclear how would we add another solid to both parts. Multiple active containers at once? I don't know.
So I would like to see Part - Instance pair. However, that has problems too. For example, how do I make a derivative of a Part, which is slightly different (e.g. has a number engraved onto some surface)? That will require another kind of object, something like "DerivedPart" container, and I'm not sure how to organize it.
1. Single active container.
There should be exactly one active container, because dealing with current situation that allows two active containers, one of type Body and one of type Part, doesn't make any sense IMO. What if we have active body that doesn't belong to active part, what is it for?
It's enough to have only one, because from it, we can easily figure out all upper level containers in case we need them.
If container structure is to support graphs, active container has to store the whole path, not just pointer to object.
2. Introduce ActiveContainer as member of App, so that we can use "App.ActiveContainer.addObject('class','name')". And then, replace all "App.ActiveDocument.addObject(..)" with calls to ActiveContainer, in all other workbenches.
That will allow object type filtering on container side. For example, if I try to add a Part Cube when I have a PartDesign Body active, App.ActiveContainer.addObject is to throw an error that this container doesn't accept this object.
A more ugly approach to this problem is to re-use App.ActiveDocument for App.ActiveContainer. This will have a benefit that no porting of other code is necessary, but is ugly because the attribute is named not according to what it actually is.
A compromise approach is to make App.ActiveDocument.addObject(...) act as if it is App.ActiveContainer.addObject. Again, no porting of other workbenches is necessary, and there is no terribly wrong naming.
3. Selection
I think, this is the easiest way to ban cross-container links: make getSelection and getSelectionEx, by default, only return selected objects from active container. And make it return more only when supplied with additional argument, like so: Gui.Selection.getSelection(App.ActiveDocument)
Next tricky part is selection of objects in instances. This is definitely needed for assemblies, and I don't know how technically easy it is to do that. Maybe, for each selection object, provide a Path attribute, something similar to coin's SoPath.
This will require specialized link type. If we are not dealing with graph container structure, but with tree, then it's enough to provide the actual object and the list of instance objects to use when resolving placement. If we go for full graph, then it becomes necessary (I think) to include the whole container path into the link, and track/update it as the container structure changes. I think this tracking is very tricky, and this is the main reason to stick with container tree rather than graph. If you have a solution to that, then we can go for full graph of course, as it is more flexible.
I think that's it for now.
summary (my preferred way).
* Container structure must form a tree. Multiple instantiations of objects are to be realized with Instance object, which is NOT a container. Instance object is to have special meaning for new propertylink type.
* only one active container. Expose it in very accessible App.ActiveContainer (not hidden as some attribute of viewer), and it must work without Gui.
* App.ActiveDocument.addObject is to act as if it were App.ActiveContainer.addObject (and there must be a way to suppress it, maybe extra argument). -> no porting of other workbenches required
* Gui.Selection.getSelection() should return the selection limited to active container. Gui.Selection.getSelection(App.ActiveDocument) should be required to get full selection. This automatically provides the general ban for cross-container links.
* Selection is to be able to provide path by listing instance objects the actual selected object is to be reached through.
* new PropertyLink type, to store list of instances through which the linked object is to be reached. All container-related transformations can be computed on the fly, so they should not be stored by the property.
More minor points:
* ShapeBinder should become the tool to make cross-container shape links. I propose to move it to Part module.