347 lines
14 KiB
Python
Executable File
347 lines
14 KiB
Python
Executable File
from pyfbsdk import *
|
|
from pyfbsdk_additions import *
|
|
|
|
from xml.dom import minidom
|
|
|
|
import RS.Globals as glo
|
|
import RS.Config
|
|
import RS.Perforce
|
|
import RS.Core.Reference.Lib
|
|
import RS.Core.Reference.Manager
|
|
import RS.Core.Expression.RelationConstraintUtils
|
|
|
|
|
|
reload (RS.Core.Expression.RelationConstraintUtils)
|
|
reload (RS.Core.Reference.Lib)
|
|
|
|
|
|
def FindAnimationNode(pParent, pName):
|
|
lResult = None
|
|
for lNode in pParent.Nodes:
|
|
if lNode.Name == pName:
|
|
lResult = lNode
|
|
break
|
|
return lResult
|
|
|
|
# Copy Model's TR animation data
|
|
def copyAnimation(pSrc, pDst ):
|
|
for pName in [ 'Translation/X','Translation/Y','Translation/Z', 'Rotation/X','Rotation/Y','Rotation/Z']:
|
|
lSrcNode = findAnimationNode( pName, pSrc.AnimationNode )
|
|
lDstNode = findAnimationNode( pName, pDst.AnimationNode )
|
|
|
|
if lSrcNode and lSrcNode.FCurve and lDstNode:
|
|
lDstNode.FCurve.KeyReplaceBy(lSrcNode.FCurve)
|
|
|
|
|
|
|
|
class MBCharacterSkeleton:
|
|
def __init__(self):
|
|
self.name = ""
|
|
self.nameSpace = ""
|
|
self.character = None
|
|
self.skelRoot = None
|
|
self.allJoints = []
|
|
|
|
def __GetChildJoints(self, joint):
|
|
allChildren = []
|
|
for child in joint.Children:
|
|
allChildren.append(child)
|
|
allChildren += self.__GetChildJoints(child)
|
|
|
|
return allChildren
|
|
|
|
def GetSkeleton(self):
|
|
self.allJoints.append(self.skelRoot)
|
|
self.allJoints += self.__GetChildJoints(self.skelRoot)
|
|
self.allJoints.append(self.skelRoot.Parent)
|
|
|
|
|
|
def PlotSkeleton(self, take=None):
|
|
#Plot all takes if none are supplied
|
|
if take == None:
|
|
for joint in self.allJoints:
|
|
joint.Selected = True
|
|
|
|
|
|
|
|
def loadIKConstraint(recCharacterNamespace, giverCharacterNamespace):
|
|
myXMLPATH = "{0}/etc/config/general/ConvertAnimSkelToSkelIKJoints.xml".format(RS.Config.Tool.Path.Root)
|
|
FBSystem().Scene.Evaluate()
|
|
#rManager = cRelationManager("", "")
|
|
rManager = RS.Core.Expression.RelationConstraintUtils.cRelationManager((recCharacterNamespace +"_IK_REL"), "")
|
|
rManager.pluginName = "temp"
|
|
rManager.characterName = recCharacterNamespace
|
|
rManager.entities.append(recCharacterNamespace)
|
|
rManager.entities.append(giverCharacterNamespace)
|
|
rManager.loadConstraintXML(myXMLPATH)
|
|
rManager.constructConstraint()
|
|
#print rManager.allControllers
|
|
|
|
#rManager.debugPrintConstraint(1)
|
|
|
|
|
|
def getCharacterFromModel( skelModelNode ):
|
|
scene = FBSystem().Scene
|
|
#print "-{0}".format(skelModelNode.LongName)
|
|
for fbChar in scene.Characters:
|
|
#print "-{0}".format(fbChar.LongName)
|
|
for fbCharProp in fbChar.PropertyList:
|
|
if "link" in fbCharProp.Name.lower():
|
|
for obj in fbCharProp:
|
|
#print "-{0}, {1}".format(skelModelNode.LongName, obj.LongName)
|
|
if skelModelNode.LongName.lower() == obj.LongName.lower():
|
|
return fbChar
|
|
|
|
return None
|
|
|
|
|
|
def ConnectJointToJoint(sourceJointBox, destJointBox):
|
|
propsToConnect = ["Rotation", "Translation", "Scaling"]
|
|
for prop in propsToConnect:
|
|
sourceAnimNode = FindAnimationNode(sourceJointBox.AnimationNodeOutGet(), prop )
|
|
destAnimNode = FindAnimationNode(destJointBox.AnimationNodeInGet(), prop)
|
|
if sourceAnimNode and destAnimNode:
|
|
FBConnect (sourceAnimNode, destAnimNode)
|
|
else:
|
|
print "Could not connect! {0}, {1}".format(sourceAnimNode, destAnimNode)
|
|
|
|
|
|
def SkeletonToSkeletonTransfer( sourceCharacter, destCharacter ):
|
|
relationInst = FBConstraintRelation("Mid_To_Final")
|
|
relationInst.Active = True
|
|
y = 0
|
|
for srcJoint in sourceCharacter.allJoints:
|
|
for dstJoint in destCharacter.allJoints:
|
|
|
|
if srcJoint.Name.lower() == dstJoint.Name.lower():
|
|
|
|
sourceBox = relationInst.SetAsSource(srcJoint)
|
|
relationInst.SetBoxPosition(sourceBox, 0, y)
|
|
|
|
destBox = relationInst.ConstrainObject(dstJoint)
|
|
relationInst.SetBoxPosition(destBox, 200, y)
|
|
|
|
ConnectJointToJoint(sourceBox, destBox)
|
|
|
|
y += 75
|
|
return relationInst
|
|
|
|
|
|
def LoadSettingsFile( settingsFilePath ):
|
|
|
|
if settingsFilePath:
|
|
charMap = {}
|
|
xmldoc = minidom.parse( settingsFilePath )
|
|
charNodes = xmldoc.getElementsByTagName( 'character' )
|
|
for charNode in charNodes:
|
|
|
|
fbxPath = str( charNode.attributes[ 'fbx' ].value )
|
|
charName = str( charNode.attributes[ 'namecomp' ].value )
|
|
stage = str( charNode.attributes[ 'stage' ].value )
|
|
if stage == "final":
|
|
charName += "F"
|
|
|
|
charMap[charName] = fbxPath
|
|
return charMap
|
|
else:
|
|
print "Couldn't load settings file:{0}".format(settingsFilePath)
|
|
return {}
|
|
|
|
def ProcessFile( sourceFile, outputFile):
|
|
settingsFilePath = '{0}/etc/config/general/ConvertAnimSkeletonSettings.xml'.format(RS.Config.Tool.Path.Root)
|
|
|
|
transModelPaths = LoadSettingsFile(settingsFilePath)
|
|
'''
|
|
{'player':r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Player_Zero_Transfer_MID.fbx",
|
|
'playerF':r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Player_Zero_Final.fbx",
|
|
'male':r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Male_Skeleton_MID.fbx",
|
|
'maleF':r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Male_Skeleton_Final.fbx",
|
|
'female':r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Female_Skeleton_MID.fbx",
|
|
'femaleF':r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Female_Skeleton_Final.fbx"
|
|
}
|
|
'''
|
|
|
|
try:
|
|
FBApplication().FileNew()
|
|
bOpen = FBApplication().FileOpen(sourceFile, 0)
|
|
|
|
except:
|
|
return 0
|
|
|
|
|
|
scene = FBSystem().Scene
|
|
refManager = RS.Core.Reference.Manager.RsReferenceManager()
|
|
refManager.collectSceneReferences()
|
|
origSceneChars = refManager.characters
|
|
|
|
lOptions = FBPlotOptions()
|
|
lOptions.ConstantKeyReducerKeepOneKey = False
|
|
lOptions.UseConstantKeyReducer = False
|
|
lOptions.PlotAllTakes = True
|
|
lOptions.PlotOnFrame = True
|
|
lOptions.PlotPeriod = FBTime( 0, 0, 0, 1 )
|
|
lOptions.PlotTranslationOnRootOnly = False
|
|
lOptions.PreciseTimeDiscontinuities = True
|
|
lOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterGimbleKiller
|
|
|
|
|
|
|
|
for char in origSceneChars:
|
|
charNamespace = char.namespace
|
|
charName = char.name
|
|
print "{0}:{1}".format(charNamespace,charName)
|
|
charModel = FBFindModelByLabelName("{0}:{1}".format(charNamespace,"SKEL_ROOT"))
|
|
if charModel != None:
|
|
charCharacter = getCharacterFromModel(charModel)
|
|
#charCharacter.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, lOptions)
|
|
|
|
print "Found Giver Character:{0}".format(charCharacter)
|
|
|
|
characterName = "Player_Zero"
|
|
charPath = None
|
|
for key in transModelPaths.keys():
|
|
if key in charNamespace.lower():
|
|
charPath = transModelPaths[key]
|
|
finalCharPath = transModelPaths[key + "F"]
|
|
|
|
if charPath == None:
|
|
charPath = r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Player_Zero_Transfer_MID.fbx"
|
|
finalCharPath = r"X:\rdr3\art\animation\resources\characters\Models\ingame\NewSkel\Player_Zero_Final.fbx"
|
|
|
|
#Ref in both versions of the character for processing...
|
|
newChar = RS.Core.Reference.Lib.rs_CreateReference(charPath, characterName, quiet=True, returnReferenceNull=True )
|
|
newCharFinal = RS.Core.Reference.Lib.rs_CreateReference(finalCharPath, characterName, quiet=True, returnReferenceNull=True )
|
|
print "MID CHAR:{0}".format(newChar)
|
|
print "FINAL CHAR:{0}".format(newCharFinal)
|
|
|
|
if newChar != False and len(newChar) > 0:
|
|
|
|
#Get the reference null object for the character
|
|
newChar = newChar[0]
|
|
|
|
#Get the Skel root if possible
|
|
newCharModel = FBFindModelByLabelName("{0}:{1}".format(newChar.Name,"SKEL_ROOT"))
|
|
|
|
#Get the fbcharacter associated with the model
|
|
newCharCharacter = getCharacterFromModel(newCharModel)
|
|
|
|
if newCharCharacter:
|
|
|
|
newCharCharacter.CreateControlRig(True)
|
|
print "Still Have it {0}".format(charCharacter)
|
|
newCharCharacter.InputCharacter = charCharacter
|
|
|
|
newCharCharacter.InputType = FBCharacterInputType.kFBCharacterInputCharacter
|
|
|
|
newCharCharacter.ActiveInput = True
|
|
|
|
#newCharCharacter.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton, lOptions)
|
|
newCharCharacter.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, lOptions)
|
|
FBSystem().Scene.Evaluate()
|
|
loadIKConstraint(newChar.Name, charNamespace)
|
|
|
|
|
|
charMidInst = MBCharacterSkeleton()
|
|
charMidInst.skelRoot = newCharModel
|
|
charMidInst.GetSkeleton()
|
|
|
|
#Lets handle the final skeleton now
|
|
if newCharFinal != False and len(newCharFinal) > 0:
|
|
#Get the reference null object for the character
|
|
newFinalChar = newCharFinal[0]
|
|
|
|
#Get the Skel root if possible
|
|
newFinalCharModel = FBFindModelByLabelName("{0}:{1}".format(newFinalChar.Name,"SKEL_ROOT"))
|
|
if newFinalCharModel:
|
|
|
|
#Lets make a new skeleton class for organizational purposes
|
|
charInstFinal = MBCharacterSkeleton()
|
|
charInstFinal.skelRoot = newFinalCharModel
|
|
charInstFinal.GetSkeleton()
|
|
|
|
#Now lets create the relation constraint to do skel to skel
|
|
midToFinRel = SkeletonToSkeletonTransfer( charMidInst, charInstFinal)
|
|
|
|
|
|
#Get the fbcharacter associated with the model
|
|
newFinalCharCharacter = getCharacterFromModel(newFinalCharModel)
|
|
|
|
#Create a rig
|
|
newFinalCharCharacter.CreateControlRig(True)
|
|
|
|
#Plot to the rig
|
|
newFinalCharCharacter.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, lOptions)
|
|
|
|
#Turn off the relation constraint
|
|
midToFinRel.Active = False
|
|
|
|
else:
|
|
print "Could not FIND CHAR".format(finalCharPath, newFinalChar)
|
|
|
|
else:
|
|
print "Could not ref in: {0}, {1}".format(finalCharPath, newFinalChar)
|
|
|
|
else:
|
|
print "Could not ref in: {0}, {1}".format(charPath, newChar)
|
|
|
|
|
|
else:
|
|
print "ERROR: Could not find character for {0}!".format(charNamespace)
|
|
|
|
|
|
bSave = FBApplication().FileSave(outputFile)
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
scene = FBSystem().Scene
|
|
refManager = RS.Core.Reference.Manager.RsReferenceManager()
|
|
refManager.collectSceneReferences()
|
|
origSceneChars = refManager.characters
|
|
|
|
|
|
lOptions = FBPlotOptions()
|
|
lOptions.ConstantKeyReducerKeepOneKey = False
|
|
lOptions.UseConstantKeyReducer = False
|
|
lOptions.PlotAllTakes = True
|
|
lOptions.PlotOnFrame = True
|
|
lOptions.PlotPeriod = FBTime( 0, 0, 0, 1 )
|
|
lOptions.PlotTranslationOnRootOnly = False
|
|
lOptions.PreciseTimeDiscontinuities = True
|
|
lOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterGimbleKiller
|
|
|
|
|
|
|
|
MBChars = []
|
|
|
|
for char in origSceneChars:
|
|
print char.name
|
|
charNamespace = char.namespace
|
|
charName = char.name
|
|
charModel = FBFindModelByLabelName("{0}:{1}".format(charNamespace,"SKEL_ROOT"))
|
|
|
|
if charModel:
|
|
charCharacter = getCharacterFromModel(charModel)
|
|
if charCharacter:
|
|
#charCharacter.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, lOptions)
|
|
|
|
charInst = MBCharacterSkeleton()
|
|
charInst.name = charName
|
|
charInst.nameSpace = charNamespace
|
|
charInst.skelRoot = charModel
|
|
charInst.GetSkeleton()
|
|
|
|
MBChars.append(charInst)
|
|
|
|
print MBChars[1].name
|
|
SkeletonToSkeletonTransfer( MBChars[0], MBChars[1])
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|