The patch set of this stage introduced quite a few new core APIs to build the foundation for the Link concept, and at the same time, as a solution for handling of various local coordinates. Everything added is callable and can be overridden in Python, which makes it possible to create fully functional Link object in script, as is shown in the attached test script. It is not trivial to implement the link right, which is why a C++ built-in feature, App::Link, will be added in the upcoming final stage.
To test, please clone my branch at https://github.com/realthunder/FreeCAD/tree/LinkStage2. Download and put the testing script in the attachment to your Macro directory (Edit: oops, just found out that I attached wrong script. Please try download again.). You can read the script code and the comments inside, in case you are interested to find out which new APIs are responsible for the new behaviors.
The first demo continues from stage one, and shows the correct tree view behavior of a link group.
Code: Select all
import linkDemo
linkDemo.linkGroupTest()
As I mentioned in the previous stage, the objects added to a LinkGroup exists both in group's local coordinate system (CS), and the global CS. All existing FC tools only works with objects in global CS. So, to show the object in global CS, expand the fusion object, and toggle its child's visibility, you can see the object at a different placement. If, however, there is no FC tool claiming a member object, you can't access the group's children in the global CS using tree view, which is why I added a new API to let object control whether to remove the claimed children from tree root. Toggle group object's 'ChildAtRoot' property, you can reveal the fusion object in global CS at the tree root. The other members of the group, box and cone, are not shown at root because they have been claimed by fusion, which has the default remove-children-from-root behavior. Move the fusion object in the global CS also moves the one in the local coordinate, as expected. Moving the group object only affects the object inside group, not those at the global CS.
Because now one object can potentially be inside a lot of different groups, hence, different at coordinates, tree view has a convenience menu action to select all appearances of the objects in the entire application (you will soon find out that an object can now appear in multiple documents).
LinkGroup uses a different approach from GeoGroup to implement the group behavior. It uses Coin3D node sharing for visual representation as mentioned in stage one. The current stage introduced a new API, DocumentObject.getSubObject(), to impelement the non-visual behavior of a group with local coordinate system. Gui.Selection has been modified to accept a new parameter 'resolve' (defaults to True) in some of its API (getSelection(), getSelectionEx(), getCompleteSelection(), getTypeOfObjects(), addSelectionGate(), etc), which calls getSubObject() to resolve the object reference inside a full qualified SubName. Existing FC tools can work with objects inside a LinkGroup without modification. However, the default 'resolve' behavior is to resolve to object in global CS. You can select the box and cone inside the group object, and choose Part.Fusion tool to create a fusion object and notice the resulting fusion's placement. To work directly with objects in local coordinate, the tool needs to be modified to resolve the object manually by calling getSubObject(), which is capable of returning the full transformation matrix of the sub object. However, it is my opinion that this is an unnecessary complication, and that all existing tools shall still operate in global CS as they are now. A special Link type object can be used to link to sub object in nested local coordinates. The link itself still exists in global CS and can be operated as usual by existing tools, with minimum modification.
The testing script implements a Link type called _Link (and the upcoming stage will bring you App::Link) to do just that. The Link can link directly to an object in global CS, overriding its placement, and thus creates a separate entity in global CS. Or, it can link to a sub object inside arbitarily nested groups. It overrides the top level group's placement, but preserves and automatically sychronizes the accumulated local coordinates of the (nested) sub object. The Link is also capable of override the linked object's material. The following test sets a distinct color of each link for easy demonstration. One thing though, neither Link nor LinkGroup can work with App::Part because of App::Part's unique way of grouping children visually. The upcoming App::Link has special code to support that.
Code: Select all
linkDemo.linkTest()
The next demo shows that Part::Feature tool can work with links. Currently, Part workbench only has partial support of link type object. Toolbar commands only works when the link actually points to a real Part::Feature. You can use non Part::Feature linked object in script, as long as the linked object has a proper implementation of getSubObject() (such as LinkGroup here) that can return Part.Shape when asked. You can trick the GUI to accept non Part::Feature links by assigning the link to a Part::Feature first, create the the tool with the link, and then change the link afterwards, as shown in the following screencast. The screencast also shows how to assign the link using GUI. You can either use property editor, which only selects objects in global coordinates, or use drag and drop which supports sub objects in local coordinates.
Code: Select all
linkDemo.linkFusion()
The next demo shows the newly added PropertyXLink that can link to object outside the current document. It can be used just the same as PropertyLink. It stores additional information of the object's document path (relative to the owner document) and the document file's time stamp. As shown in the following screencast, you can simply drag the object across document boundary and drop to the link. Or, simply assign the property with any object using script. It will store the document information if the object is external. The tree view has been enhanced to show external object, and its claimed children. An overlay arrow is shown in the right bottom of the icon to indicate that it is an external object. When the external document is closed, all linked PropertyXLink automatically lose the linked object reference, but still retains the document and object name information, so that when the external document is opened again, the links can be automatically restored. The document recomputation logic is also enhanced to support external object dependency. Finally, the screencast shows that when a document containing PropertyXLink is opened, FC will automatically open all referenced external documents.
Code: Select all
linkDemo.linkXTest()
The final screencast shows some of the other tree view enhancements.
* Sync Selection, when enabled, selection in 3D view will automatically select the corresponding tree item and expand its parent(s) if necessary.
* Sync View, selecting an object in the tree will automatically switch to its 3D view.
* Select all instances, select all occurance of an object, expand the parents if necessary.
* Select all links, select all links (direct or indirect) to some object.
* Hide item, hide the object in the tree view. All tree items (including externally linked) corresponding to this object will be hidden. The setting is stored into 'ShowInTree' property of the object.
* Show hidden item, reveal the hidden items. This setting is per document, and stored in the document's 'ShowHidden' property. When this setting is on, the hidden items' icons are marked by a small 'eye' overlay image in the left top corner.
Edit: oops, just found out that I attached wrong script. Please try download again.