Files
gtav-src/tools_ng/techart/dcc/motionbuilder2014/python/RS/Tools/GhostTake.py
T
2025-09-29 00:52:08 +02:00

435 lines
19 KiB
Python
Executable File

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 lGhostStartFrame<lActualStartFrame:
lPlayer.ZoomWindowStart = FBTime(0,0,0,lGhostStartFrame)
lPlayer.LoopStart = FBTime(0,0,0,lGhostStartFrame)
lPlayer.Goto (FBTime(0,0,0,lGhostStartFrame))
if lGhostStopFrame>lActualStopFrame:
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")