''' Description: Helper module for working with FBX files. Author: Jason Hayes ''' from fbx import * from FbxCommon import * import RS.Core.Reference.Manager class RsStoryObject(): def __init__(self): self.fbxSdkObject = None self.characterTracks = {} self.shotTracks = {} self.globalStoryToggle = False self.properties = {} class RsFbxFileHelper( object ): ''' Description: Helper class for easily loading an FBX file and getting information out of it. Author: Jason Hayes Example: fbxObj = RsFbxFileHelper( pathToFbxFilename ) if fbxObj.openFile(): ... fbxObj.closeFile() ''' def __init__( self, fbxFilename ): self.__fbxFilename = fbxFilename self.__scene = None self.__sdkManager = None ## Public Properties ## @property def filename( self ): return self.__fbxFilename @property def scene( self ): return self.__scene @property def sdkManager( self ): return self.__sdkManager ## Methods ## def openFile( self ): ''' Description: Loads the FBX filename into memory. Author: Jason Hayes ''' self.__sdkManager, self.__scene = InitializeSdkObjects() return LoadScene( self.__sdkManager, self.__scene, self.__fbxFilename ) def closeFile( self ): ''' Description: Destroys the loaded FBX SDK objects from memory. Author: Jason Hayes ''' self.__sdkManager.Destroy() def getStoryInfo(self): #== Returns story object storyInfo = RsStoryObject() storyInfo.fbxSdkObject = self.getObjectsByName('Story root') storyInfo.properties = self.getObjectProperties(storyInfo.fbxSdkObject['Story root']) storyInfo.shotTracks = self.getObjectsByType('TimelineXTrack', 'Shot') if "Muted" in storyInfo.properties.keys(): storyInfo.globalStoryToggle = storyInfo.properties['Muted'] return storyInfo def getObjectProperties(self, iObject): ''' Description: Returns the properties on an object as a dictionary Author: Kyle Hansen ''' blobObjects = [] propertyList = {} lProperty = iObject.GetFirstProperty() while lProperty.IsValid(): propertyName = str(lProperty.GetName()) propertyType = lProperty.GetPropertyDataType().GetName().lower() #print "PROPERTY:", propertyName, propertyType try: if propertyType == 'kstring': propertyValue = lProperty.Get() propertyList[propertyName] = str( propertyValue.Buffer() ) elif propertyType == 'object': propertyValue = lProperty.GetFbxObject() propertyList[propertyName] = propertyValue elif propertyType == 'blob': #print "Found a blob:", propertyName for i in range(0, lProperty.GetDstObjectCount()): print Property.GetDstObject(i) #== Not supported yet propertyValue = None propertyList[propertyName] = propertyValue elif propertyType == "time": #== Not supported yet propertyValue = None propertyList[propertyName] = propertyValue elif propertyType == "ulonglong": #== Not supported yet propertyValue = None propertyList[propertyName] = propertyValue else: propertyValue = lProperty.Get() propertyList[propertyName] = propertyValue except: #== Turn on when debugging.... print "Error getting type:", propertyType, " value:", sys.exc_info()[0] propertyList[propertyName] = None lProperty = iObject.GetNextProperty(lProperty) return propertyList def getObjectsByType( self, argObjectType, argObjectSubType = None): ''' Description: Returns any objects with the given flag Author: Kyle Hansen ''' userObjects = {} if self.__sdkManager: rootNode = self.__scene.GetRootNode() for nodeId in range( self.__scene.GetMemberCount() ): childNode = self.__scene.GetMember( nodeId ) childNodeProperties = self.getObjectProperties(childNode) if 'MoBuTypeName' in childNodeProperties.keys(): if argObjectType == childNodeProperties['MoBuTypeName']: if argObjectSubType != None: if argObjectSubType == childNodeProperties['MoBuSubTypeName']: userObjects[len(userObjects.keys())] = childNode else: userObjects[len(userObjects.keys())] = childNode return userObjects def getObjectsByName( self, argObjectName): ''' Description: Returns the user objects with "exportmarkup" in the name as a dict Author: Kyle Hansen ''' userObjects = {} if self.__sdkManager: rootNode = self.__scene.GetRootNode() for nodeId in range( self.__scene.GetMemberCount() ): childNode = self.__scene.GetMember( nodeId ) childNodeName = childNode.GetName() if argObjectName == childNodeName: userObjects[argObjectName] = childNode return userObjects def getReferences( self ): ''' Description: Finds all of the references listed in the file and returns them and their properties in a dictionary. Author: Jason Hayes ''' references = {} if self.__sdkManager: rootNode = self.__scene.GetRootNode() for nodeId in range( rootNode.GetChildCount() ): childNode = rootNode.GetChild( nodeId ) if str( childNode.GetName() ) == RS.Core.Reference.Manager.GetReferenceSceneNullName(): for childId in range( childNode.GetChildCount() ): refChildNode = childNode.GetChild( childId ) name = str( refChildNode.GetName() ) namespace, refName = name.split( ':' ) if namespace == 'RS_Null' and 'BugNull' not in refName: if refName not in references: references[ refName ] = {} else: print 'Found a duplicate reference name!' refPath = refChildNode.FindProperty( 'Reference Path' ) refNamespace = refChildNode.FindProperty( 'Namespace' ) refAssetType = refChildNode.FindProperty( 'rs_Asset_Type' ) refReload = refChildNode.FindProperty( 'Reload' ) refP4Version = refChildNode.FindProperty( 'P4_Version' ) refUpdate = refChildNode.FindProperty( 'Update' ) try: refPath = refPath.Get() references[ refName ][ 'Reference Path' ] = str( refPath.Buffer() ) except: references[ refName ][ 'Reference Path' ] = None try: refNamespace = refNamespace.Get() references[ refName ][ 'Namespace' ] = str( refNamespace.Buffer() ) except: references[ refName ][ 'Namespace' ] = None try: refAssetType = refAssetType.Get() references[ refName ][ 'rs_Asset_Type' ] = str( refAssetType.Buffer() ) except: references[ refName ][ 'rs_Asset_Type' ] = None try: refReload = refReload.Get() references[ refName ][ 'Reload' ] = refReload except: references[ refName ][ 'Reload' ] = None try: refP4Version = refP4Version.Get() references[ refName ][ 'P4_Version' ] = int( refP4Version.Buffer() ) except: references[ refName ][ 'P4_Version' ] = None try: refUpdate = refUpdate.Get() references[ refName ][ 'Update' ] = refUpdate except: references[ refName ][ 'Update' ] = None else: print 'Node ({0}) is a child of the reference node, but does not have the correct namespace!'.format( refName ) return references def moveAllSceneObjects( destinationScene, sourceScene): # Move the node tree of the destinationScene scene into the sourceScene scene. # This is the route node for the meshes lRootNode = sourceScene.GetRootNode() if lRootNode: ChildNodeList = [] for i in range(lRootNode.GetChildCount()): lChildNode = lRootNode.GetChild(i) if lChildNode != None: ChildNodeList.append(lChildNode) for item in ChildNodeList: # Attach the child node to the reference scene's root node. destinationScene.GetRootNode().AddChild(item) # Remove the children from the root node # As such, the objective of this step is to remove the children from the current scene's root node so they may become the children of the reference scene's root node. sourceScene.GetRootNode().DisconnectAllSrcObject() return True def moveAllConnections(destinationScene, sourceScene): # Move other objects to the reference scene. lNumSceneObjects = sourceScene.GetSrcObjectCount() for i in range(lNumSceneObjects): lObj = sourceScene.GetSrcObject(i); if lObj == sourceScene.GetRootNode() or lObj == sourceScene.GetGlobalSettings(): # Don't move the root node or the scene's global settings; these objects are created for every scene. continue # Attach the object to the reference scene. lObj.ConnectDstObject(destinationScene) # Disconnect all scene objects. sourceScene.DisconnectAllSrcObject(); return True