* App::Link supports inter document object linking. I added PropertXLink which is derived from PropertyLink. It can handle both internal and external linking. External referenced document will be automatically opened along with the document containing PropertyXLink.
* App::Link'ed object has independent placement, scale, and visibility. The linked object's placement can be either overridden or combined.
* App::Link tree view item shares the linked object's icon and claimed children. When selected, the property view merges the link and the linked objects property for easy editing. If multi-level linking is used, it will merge the final linked object.
* App::Link has python method getSubObjects to retrieve selected sub object or subelement (Face, Edge, Vertex) that are fully transformed and scaled.
* App::Link'ed object in 3D view supports hierarchy selection. When you click an already selected item, it will automatically selects its parent object, with full tree view synchronization to help navigate through complex hierarchies. You need enable selection sync in tree view context menu first. See the demo below.
* There is also Part::Link. which I've added an icon to Part workbench, that supports geometry modeling, meaning you can use it with other Part operations. This feature is still experimental at the moment. The benefits over Draft.Clone is that no geometry data is saved, and no duplicates in 3D representation, and fully utilize OCC's internal geometry data sharing. The shape linking can be turned off with LinkShape property, which will then makes it behave just like App::Link.
* You can now freely hide any items in the tree, and toggle those hidden items, all through tree view context menu. It can also be done in script.
* SceneInspector is upgraded to show linking nodes, you can check out how the coin nodes are shared.
You can try it with my branch at https://github.com/realthunder/FreeCAD/tree/Link
@DeepSOIC you may need to checkout a new one because I just rebased it.
Now some demo here. It makes heavy use of multi-level linking, which I think would really benefits assembly use cases. What you are seeing is 400 cubes, divided into 4 groups (App::Part). Each group contains 100 links to the same typelink containing in other App::Part. The purpose of those type links is so that you can change individual group of the objects, which I haven't shown in the demo. All typelinks are link to rootLink, which cross link to another document partDoc containing and actual cube object. Now, if I change the rootLink to point to a sphere, you can see instant change of all objects in the 3D view. Mind you that all objects in the 3D view actually shares the Coin node, but as you can see they are fully independent here. You can select, move, hide/show independently. Next I point rootLink to a self taping screw with full threading details. Again the change is instant. Finally, I point rootLink to partGroup inside the same document. partGroup contains four external screw links. Now you have 1.6K screws on screen, and again the change is almost instant, although my PC without dedicated graphics card is skipping frame here.
The component document size is 189KB, while the assembly file is only 24KB. The files are attached. The loading time is a bit slow, about 10 second on my PC because of the number items. Need optimization here. Assuming you had the component file, the code to produce the assembly is
Code: Select all
def test6(count=(10,10), groupCount=(2,2)): partDoc = None try: partDoc = FreeCAD.getDocument('partDoc') except Exception: partDoc = FreeCAD.openDocument('partDoc.fcstd') doc = FreeCAD.newDocument('partLink') doc.saveAs('partLink.fcstd') partGroup = doc.addObject('App::Part', 'partGroup') partGroup.ViewObject.Visibility = False partGroup.ViewObject.ShowInTree = False partRoot = doc.addObject('App::Link','partRoot') partRoot.LinkedObject = partDoc.Compound partRoot.ViewObject.Visibility = False for i in range(groupCount): for j in range(groupCount): link = doc.addObject('App::Link','partLink') link.LinkedObject = partRoot link.LinkPlacement.Base.x = i*2 link.LinkPlacement.Base.y = j*2 partGroup.addObject(link) part = doc.addObject('App::Part', 'part') part.ViewObject.Visibility = False rootLink = doc.addObject('App::Link','rootLink') rootLink.LinkedObject = partDoc.Box rootLink.ViewObject.Visibility = False groups = doc.addObject('App::Part', 'groups') groups.ViewObject.Visibility = False groups.ViewObject.ShowInTree = False linkGroups = doc.addObject('App::Link', 'linkGroups') linkGroups.LinkedObject = groups for i in range(groupCount): for j in range(groupCount): link = doc.addObject('App::Link','typeLink') link.LinkedObject = rootLink link.LinkPlacement.Base.x = i*4 link.LinkPlacement.Base.y = j*4 part.addObject(link) group = doc.addObject('App::Part','group') group.ViewObject.Visibility = False group.ViewObject.ShowInTree = False linkGroup = doc.addObject('App::Link','linkGroup') linkGroup.LinkedObject = group groups.addObject(linkGroup) for x in range(count): for y in range(count): l = doc.addObject('App::Link','link') l.LinkedObject = link l.LinkPlacement.Base.x = count*4*i + x*4 l.LinkPlacement.Base.y = count*4*j + y*4 group.addObject(l) doc.recompute()