Working with fbx files with python in maya

fbx, or fbx(why are you such a pain?)

Working with fbx files in maya using python isn’t the most frustrating format to work with, just very picky.

When using python, try to stay away from using maya file command:

import maya.cmds as Mc

Mc.file(strFile, i=True, type='fbx')

You can by all means use that command, but it’s buggy when you want to have certain options for your import. i.e. if your open file preferences are set to maya native compared to os native, the fbx import options windows doesn’t always come up before import.

A better way is to use maya.mel commands for fbx:

import maya.mel as Mm
import maya.cmds as Mc

Mm.eval('FBXImportMode -v Exmerge')
Mm.eval('FBXImportMergeAnimationLayers -v true')
Mm.eval('FBXImportProtectDrivenKeys -v true')
Mm.eval('FBXImportConvertDeformingNullsToJoint -v true')
Mm.eval('FBXImportMergeBackNullPivots -v false')
Mm.eval('FBXImportSetLockedAttribute -v true')
Mm.eval('FBXImportConstraints -v false')
		
Mm.eval('FBXImport -f "yourFileHere.fbx"')

Strange right?

The way fbx code works is kinda like building up what you want for options and then importing your file.

It would make more sense to have a command with options built into it, i.e:

import maya.mel as Mm

Mm.eval('FBXImport -f "yourFileHere" -importMode "exmerge", -protectKeys')

Alas, we can’t have something nice to work with. Now, since we are using mel commands in python, we need a way to transfer between python and mel variables.

To store python data in a mel variable we can use:

float $melDir = `python "pythonDir"`;

To store mel data in a python variable we can use:

import maya.cmds as Mc
import maya.mel as Mm

pythonDir = Mm.eval("$temp=$melDir")

Now that’s all fine and dandy, but we are working with python from the start. So we need a way to store a python variable in mel, from python.

So, to do that:

import maya.cmds as Mc
import maya.mel as Mm

strDir = "C:\Something\Something\Darkside"

Mm.eval('string $strDir = `python "strDir"`;')

So we can finally put it all together in a python function:

import maya.cmds as Mc
import maya.mel as Mm


def importFbx():
    strDir = "C:\Something\Something\Darkside.fbx"

    Mm.eval('string $strDir = `python "strDir"`;')

    Mm.eval('FBXImportMode -v Exmerge')
    Mm.eval('FBXImportMergeAnimationLayers -v true')
    Mm.eval('FBXImportProtectDrivenKeys -v true')
    Mm.eval('FBXImportConvertDeformingNullsToJoint -v true')
    Mm.eval('FBXImportMergeBackNullPivots -v false')
    Mm.eval('FBXImportSetLockedAttribute -v true')
    Mm.eval('FBXImportConstraints -v false')

    Mm.eval('FBXImport -f $strDir')

You can find references for commands here:
http://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/Maya/files/GUID-699CDF74-3D64-44B0-967E-7427DF800290-htm.html

stretchy ik spline maya python

A quick function for creating a stretchy ik spline.

strCurve = name of the curve, or have a curve selected
iNum = number of joints you would like created
CreateStretchyIk(strCurve, iNum)

def CreateStretchyIk(strCurve=None, iNum):
    strCurve = strCurve
    
    if not strCurve:
        Mc.ls(sl=True)[0]
        
    lStrJnt = []
    
    Mc.select(cl=True)
    
    for i in range(iNum):
        strI = '%s' %i
        strJnt = Mc.joint(n=strCurve+strI)
        lStrJnt.append(strJnt)
        
    strCurveIk = Mc.ikHandle(sj=lStrJnt[0], ee=lStrJnt[-1], c=strCurve, n=strCurve+'_ik', sol='ikSplineSolver', ccv=False, rootOnCurve=True, parentCurve=False)[0]   
    
    gArcLen = Mc.arclen(strCurve)
    
    gAverage = gArcLen/(iNum-1)
    
    strCurveNode = Mc.createNode('curveInfo', n=strCurve+'_curveInfo')
    
    strMultNode = Mc.createNode('multiplyDivide', n=strCurve+'_divide')
    Mc.setAttr(strMultNode+'.operation', 2)
    Mc.setAttr(strMultNode+'.input2X', gArcLen)
    
    Mc.connectAttr(strCurveNode+'.arcLength', strMultNode+'.input1X')
    
    Mc.connectAttr(strCurve+'Shape.worldSpace', strCurveNode+'.inputCurve')
    
    for i in range(iNum):
        if i > 0:
            Mc.setAttr(lStrJnt[i]+'.tx', gAverage)
            
    for jnt in lStrJnt:
        Mc.connectAttr(strMultNode+'.outputX', jnt+'.scaleX')