I believe most of you are familiar with File Reference System, it’s commonly used in different Autodesk products, including Motionbuilder.
Recently, some partners are working with file reference in Motionbuilder, they have some confusion and also find some issues. I reviewed this feature on Mobu SDK help again, and I think it worth a post to mention some important point about modifying referenced file within Motionbuilder, we will start with some questions.
First of all, there are following 2 terms you need to understand:
- Referenced Object – A referenced object is a top level object that contains zero or more referenced items.
- Referenced Item – A referenced item is any node (in a hierarchy or alone) within a referenced object.
Question 1: How to modify a referenced item/object?
Ok, when an external FBX file is referenced into the scene, how to modify the items in referenced object? Actually, it’s pretty simple, you can modify them almost like a native object, for example, we can change scale of a cube in referenced file as follow:
FBSystem().Scene.NamespaceImport( "NS", "C:/cube.fbx", True ) my_cube = FBFindObjectByFullName( "Model::NS:Cube" ) my_cube.Scaling = FBVector3d(50, 20, 10)
But, for a referenced item/object, unlike a native object in the scene, there are a couple of limitations you need to be aware of including:
- A referenced item cannot be renamed.
- A referenced item cannot be deleted.
- An item within a referenced hierarchy cannot be re-parented.
- Referenced objects cannot be nested.
- Keyframe animation is not possible on referenced items unless those items are animated using the Story tool.
- Connections between items within a referenced object are not allowed .
Question 2: How to keep/save the modification for referenced object?
When we made modifications to the referenced items, can we save it for later use? The answer is “Yes”. When you modify items within a referenced object, MotionBuilder writes the changes in Python script and stores them within the FBX file. This enables the changes to persist when you save and reopen the FBX scene that contains the referenced object.
For example, with above sample code, we scaled the “NS:Cube” in the scene, when the file is saved, the changes and the file reference object are stored inside the FBX scene file. The next time when this scene is opened, the file reference object is created while loading and the changes are also applied to it. You can view the reference edit by using following codes:
lFileReference = FBFindObjectByFullName( “FileReference::NS” ) print lFileReference.GetRefEdit()
The result should be:
>>> from pyfbsdk import * ########################################################################### #pArgList[0] indicates if instancing is happening or not. #pArgList[1:] indicates the namespace list that the reference edit will affect. ########################################################################### def FBApplyReferenceEdits( pArgList ): for pNamespace in pArgList[1:]: lComp = FBFindObjectByFullName( "Model::" + pNamespace + ":Cube" ) if lComp <> None: lProperty = lComp.PropertyList.Find("Lcl Scaling") if lProperty <> None: lProperty.SetString( "{50,20,10}" ) FBSystem().Scene.Evaluate() ########################################################################### #pArgList[0] indicates if instancing is happening or not. #pArgList[1:] indicates the namespace list that the reference edit will affect. ########################################################################### def FBRevertReferenceEdits( pArgList ): for pNamespace in pArgList[1:]: lComp = FBFindObjectByFullName( "Model::" + pNamespace + ":Cube" ) if lComp <> None: lProperty = lComp.PropertyList.Find("Lcl Scaling") if lProperty <> None: lProperty.SetString( "{1,1,1}" ) FBSystem().Scene.Evaluate() >>>
Question 3: Can we really save the changes to the source referenced file?
Sometimes, people asks if they can save the modification to the original referenced file, and the method FBFileReference::BakeRefEditToFile(const char *pFilePath=((void *) 0)) is very likely to do such things. I did some test with this method, but unfortunately, Motionbuilder will crash when I try to bake the edit. Currently, a change request is logged to track this issue. So unless this is improved, currently, we can not save the changes directly to the source file.
Question 4: Can we track changes of Source File?
The answer is “Yes”, the event FBFileMonitoringManager.OnFileChangeFileReference is provided to monitor the change of source file, you can refer here if you are not familiar with that.
Questions 5: Can we track changes of referenced object/items?
The answer is still “Yes”, MotionBuilder provides a query based system using dirty flags for retrieving a list of changes. You can get a list of objects and their property changes. The two functions:
and GetSelfModified
are used for checking the dirty flags of a reference object or a reference item. Still use the code above, since we changed the scale of Cube, we will get “True” if we use the following methods to check the status: GetContentModified
file_reference_object.GetContentModified(FBPlugModificationFlag.kFBContentDataModified) my_cube.PropertyList.Find("Lcl Scaling").GetSelfModified( FBPlugModificationFlag.kFBSelfDataModified )
For some other flag, please refer the enum FBPlugModificationFlag for more details.
Comments
You can follow this conversation by subscribing to the comment feed for this post.