from pyfbsdk import * import RS.Globals as glo import RS.Utils.Scene import RS.Perforce import os ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Compare And Rename ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### global gArray gArray = [] ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Find Animation Node Helper Function ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def findAnimationNode( pName, pNode ): lResult = None lName = pName.split( '/' ) for lNode in pNode.Nodes: if lNode.Name == lName[0]: if len( lName ) > 1: lResult = findAnimationNode( pName.replace( '%s/' % lName[0], '' ), lNode ) else: lResult = lNode return lResult # This recursive function finds the first and last keyframe of an # animation node. def FindLimits( pNode, pLLimit=None, pRLimit=None ): # First let's see if the node has any keys if pNode.FCurve: # Got thru the list, updating the first and last frame if necessary. # Limits are initialised on first comparaison attempt. for lKey in pNode.FCurve.Keys: if pLLimit: if lKey.Time.Get() < pLLimit.Get(): pLLimit.Set( lKey.Time.Get()) else: pLLimit = FBTime() pLLimit.Set( lKey.Time.Get()) if pRLimit: if lKey.Time.Get() > pRLimit.Get(): pRLimit.Set( lKey.Time.Get()) else: pRLimit = FBTime() pRLimit.Set( lKey.Time.Get()) # If the node has any children nodes, we navigate those. if pNode.Nodes: for lNode in pNode.Nodes: ( pLLimit, pRLimit ) = FindLimits( lNode, pLLimit, pRLimit ) return ( pLLimit, pRLimit ) ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Move Animation Helper Function ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def MoveAnimation(pNode, pDelta): # Modify all the keys of the current node. if pNode.FCurve: # Create a list of the keys. This new list can be re-sorted without # affecting the internal list. lKeys = [ lKey for lKey in pNode.FCurve.Keys ] # If the delta is positive, we need to move the keys starting with # the last. This prevent any changes in the order of the keys in the # internal list. if pDelta.Get() > 0: lKeys.reverse() # Set the new time value for all the keys. for lKey in lKeys: lTime = FBTime() lTime.Set( lKey.Time.Get() + pDelta.Get() ) lKey.Time = lTime # Now deal with all the children nodes. if pNode.Nodes: for lNode in pNode.Nodes: MoveAnimation( lNode, pDelta ) ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Copy the Animation Helper Function ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def copyAnimation(pSrc): global gArray lArray = [] lArray.append(pSrc.Name) for pName in [ 'Lcl Translation/X','Lcl Translation/Y','Lcl Translation/Z', 'Lcl Rotation/X','Lcl Rotation/Y','Lcl Rotation/Z']: lSrcNode = findAnimationNode( pName, pSrc.AnimationNode ) if lSrcNode and lSrcNode.FCurve: lArray.append(lSrcNode.FCurve) gArray.append(lArray) ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Creat Ghost ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def CreateGhost(pPath, pName): lPath = pPath lOptions = FBFbxOptions(True, lPath) lOptions.SetAll(FBElementAction.kFBElementActionDiscard, False) lOptions.Bones = FBElementAction.kFBElementActionAppend lOptions.Models = FBElementAction.kFBElementActionAppend lOptions.Groups = FBElementAction.kFBElementActionAppend lOptions.TakeSpan = FBTakeSpanOnLoad.kFBLeaveAsIs lOptions.NamespaceList = "GHOST" for lTakeIndex in range( lOptions.GetTakeCount() ): lOptions.SetTakeSelect( lTakeIndex, False ) lOptions.BaseCameras = False lOptions.CameraSwitcherSettings = False lOptions.CurrentCameraSettings = False lOptions.CamerasAnimation = False lOptions.TransportSettings = False lOptions.GlobalLightingSettings = False # Make sure you have a copy of this file on your computer: if not os.path.isfile( lPath ): RS.Perforce.Sync( lPath ) lApp = FBApplication() lApp.FileMerge(lPath, False, lOptions) lMover = FBFindModelByLabelName("GHOST:mover") if not lMover: FBMessageBox("CreateGhost", "Can't find ghost mover!", "OK") return lMover.Show = True lProp = lMover.PropertyCreate('Ghost Type', FBPropertyType.kFBPT_charptr, 'String', False, True, None) if lProp: lProp.Data = pName for lTake in glo.gTakes: lTake.PropertyCreate('Ghost Take Anim', FBPropertyType.kFBPT_charptr, 'String', False, True, None) lShaderManager = FBShaderManager() lShader = lShaderManager.CreateShader( "LightedShader" ) lShader.Name = "GHOST:Shader" lShader.Transparency = FBAlphaSource.kFBAlphaSource2DTransparency lShader.Alpha = 0.51 lGeometry = FBFindModelByLabelName("GHOST:Geometry") if lGeometry: for iChild in lGeometry.Children: iChild.ShadingMode = FBModelShadingMode.kFBModelShadingAll lShader.ReplaceAll( iChild ) glo.gScene.Evaluate() ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def rs_CopyAnimationFromTake(ghostTake, ghost, startFrame): lScene = FBSystem().Scene # This get the current Take in the scene lCurrentTake = FBSystem().CurrentTake for iTake in lScene.Takes: # if the current take in the scene is set to the one in the Ghost Take the user set, then set the current take Ghost Take if iTake.Name == ghostTake: FBSystem().CurrentTake = iTake #If we migrate this code to 2013 and higher, there is no bool value for the first variable, so remove the parameter then. lPlayer = FBPlayerControl() lGhostStartFrame = lPlayer.ZoomWindowStart.GetFrame() lGhostStopFrame = lPlayer.ZoomWindowStop.GetFrame() lSizeGhostAnimFrame = lGhostStopFrame - lGhostStartFrame lFound = False for lSkel in glo.gSkelArray: if lSkel == "mover": lFound = True if lFound == False: glo.gSkelArray.append("mover") # Copy Animation for iBone in glo.gSkelArray: lSrc = FBFindModelByLabelName(ghost + ":" + iBone) if lSrc: lSrc.Translation.SetAnimated(True) lSrc.Rotation.SetAnimated(True) lSrc.Scaling.SetAnimated(True) copyAnimation(lSrc) FBSystem().CurrentTake = lCurrentTake # Setting the Transport Controls View lActualStartFrame = lPlayer.ZoomWindowStart.GetFrame() lActualStopFrame = lPlayer.ZoomWindowStop.GetFrame() # Putting Animation on the Ghost for i in range(len(gArray)): # The first item in each list in the list is the bone name, first we find that bone on the ghost # This is what the array holds ['SKEL_L_Finger0_NUB', 1->XTranslation, 2->YTranslation, 3->ZTranslation, 4->XRotation, 5->YRotation, 6->ZRotation] lBone = FBFindModelByLabelName("GHOST:" + gArray[i][0]) if lBone: print lBone.LongName lBone.Translation.SetAnimated(True) lBone.Rotation.SetAnimated(True) lBone.Translation.GetAnimationNode().Nodes[0].FCurve.EditClear() lBone.Translation.GetAnimationNode().Nodes[1].FCurve.EditClear() lBone.Translation.GetAnimationNode().Nodes[2].FCurve.EditClear() lBone.Translation.GetAnimationNode().Nodes[0].FCurve.KeyReplaceBy(gArray[i][1]) #lKeys = [ lKey for lKey in gArray[i][1].Keys ] #for lKey in lKeys: # print lKey.Value print lBone.Translation.GetAnimationNode().Nodes[0] lBone.Translation.GetAnimationNode().Nodes[1].FCurve.KeyReplaceBy(gArray[i][2]) lBone.Translation.GetAnimationNode().Nodes[2].FCurve.KeyReplaceBy(gArray[i][3]) lBone.Rotation.GetAnimationNode().Nodes[0].FCurve.EditClear() lBone.Rotation.GetAnimationNode().Nodes[1].FCurve.EditClear() lBone.Rotation.GetAnimationNode().Nodes[2].FCurve.EditClear() lBone.Rotation.GetAnimationNode().Nodes[0].FCurve.KeyReplaceBy(gArray[i][4]) lBone.Rotation.GetAnimationNode().Nodes[1].FCurve.KeyReplaceBy(gArray[i][5]) lBone.Rotation.GetAnimationNode().Nodes[2].FCurve.KeyReplaceBy(gArray[i][6]) # Only need to Move the Animation if an alternate start frame is provided in the UI if startFrame != "": print "Not Moving the animation" startFrame = int(startFrame) for i in range(len(gArray)): # The first item in each list in the list is the bone name, first we find that bone on the ghost # This is what the array holds ['SKEL_L_Finger0_NUB', 1->XTranslation, 2->YTranslation, 3->ZTranslation, 4->XRotation, 5->YRotation, 6->ZRotation] lBone = FBFindModelByLabelName("GHOST:" + gArray[i][0]) if lBone: # Find the earliest keyframe. ( lLTime, lRTime ) = FindLimits( lBone.AnimationNode ) # If we do have a first keyframe... if lLTime: # Compute the delta between the current time and the first key. lNewStartTime = FBTime(0,0,0,startFrame) lDelta = FBTime() lDelta.Set( lNewStartTime.Get() - lLTime.Get()) # Do the work... MoveAnimation( lBone.AnimationNode, lDelta ) # Makes sure the Transport Control spans both the actual take and the ghost take animation if startFrame < lActualStartFrame: lPlayer.ZoomWindowStart = FBTime(0,0,0,startFrame) lPlayer.LoopStart = FBTime(0,0,0,startFrame) lPlayer.Goto (FBTime(0,0,0,startFrame)) if (startFrame+lSizeGhostAnimFrame) > lActualStopFrame: lPlayer.ZoomWindowStop = FBTime(0,0,0,(startFrame+lSizeGhostAnimFrame)) lPlayer.LoopStop = FBTime(0,0,0,(startFrame+lSizeGhostAnimFrame)) # Makes sure the Transport Control spans both the actual take and the ghost take animation else: if lGhostStartFramelActualStopFrame: lPlayer.ZoomWindowStop = FBTime(0,0,0,lGhostStopFrame) lPlayer.LoopStop = FBTime(0,0,0,lGhostStopFrame) ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Compare And Rename ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def rs_CreateGhost(ghost): # By Design you can only create one ghost in the scene at a time cl = RS.Utils.Scene.FindObjectsByNamespace( "GHOST*" ) if cl: FBMessageBox("rs_CreateGhost", "There is already a ghost, you cannot create another one, unless you delete it", "OK") return lNull = FBFindModelByLabelName("RS_Null:" + ghost) if lNull: # Get the file location of the reference lProp = lNull.PropertyList.Find("Reference Path") if lProp: CreateGhost(lProp.Data, ghost) ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: The puts the animation from the selected take onto the ghost in the current take ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def rs_CreateGhostTake(ghostTake, startFrame): lMover = FBFindModelByLabelName("GHOST:mover") if lMover: lProp = lMover.PropertyList.Find('Ghost Type') if lProp: if lProp.Data: ghost = lProp.Data rs_CopyAnimationFromTake(ghostTake, ghost, startFrame) else: FBMessageBox("rs_GhostTakeCoreFunctions", "There is no ghost is this file, please add one first", "OK") ############################################################################################################### ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## ## Description: Delete the Ghost from the file ## ##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ############################################################################################################### def DestroyGroup(Model): for child in Model.Children: if len (child.Children) < 1: child.FBDelete() else: DestroyGroup(child) def DestroyModel( pModel ): # Always destroy from the last children to the first while len( pModel.Children ) > 0: DestroyModel( pModel.Children[-1] ) pModel.FBDelete() def rs_DeleteGhost(pControl, pEvent): # Remove 'Ghost Take Anim' Property from Takes for lTake in FBSystem().Scene.Takes: lProp = lTake.PropertyList.Find("Ghost Take Anim") if lProp: lTake.PropertyRemove (lProp) lObj = FBFindObjectByFullName ("GHOST:RexRageCutsceneExportMarkup") if lObj: lObj.FBDelete() # Since this works off selection, we have to make sure nothing else is selected. for lComp in FBSystem().Scene.Components: lComp.Selected = False FBSystem().Scene.NamespaceSelectContent("GHOST", True) lModelList = FBModelList() # Deleting Models for i in range(10): FBGetSelectedModels( lModelList ) if lModelList.count() > 0: DestroyModel( lModelList[0] ) lModelList.Clear() # Since this works off selection, we have to make sure nothing else is selected. for lComp in FBSystem().Scene.Components: lComp.Selected = False # Clean up all the empty folders for folder in FBSystem().Scene.Folders: for item in folder.Items: if isinstance(item,FBCharacter): folder.Items.remove(item) lFolderList = [] for lFolder in glo.gFolders: if len(lFolder.Items) == 0: lFolderList.append(lFolder) map( FBComponent.FBDelete, lFolderList ) FBSystem().Scene.NamespaceSelectContent("GHOST", True) # Deleting all the remaining components in the scene lList = [] for lComp in FBSystem().Scene.Components: if lComp != None and lComp.Selected: if lComp.ClassName() == 'FBGroup': # Appending to list to be deleted after lList.append(lComp) for iDelete in lList: try: iDelete.FBDelete() except: pass # The stupid Decklink Video Capture, gets the GHOST namespace cl = RS.Utils.Scene.FindObjectsByNamespace("GHOST") for item in cl: item.ProcessObjectNamespace(FBNamespaceAction.kFBRemoveAllNamespace, "GHOST")