Skip to content

Instantly share code, notes, and snippets.

@bohdon
Last active December 22, 2022 06:46
Show Gist options
  • Select an option

  • Save bohdon/33a1af1133b1b9b67779ef6be5ce9968 to your computer and use it in GitHub Desktop.

Select an option

Save bohdon/33a1af1133b1b9b67779ef6be5ce9968 to your computer and use it in GitHub Desktop.
Export all skeletal meshes from a Maya scene using object sets
import os
import maya.cmds as cmds
import pymel.core as pm
import pulse
def exportSKSets(sourceScenePath, destDir):
"""
Export all SK_* sets from the given scene, unparenting all members
and deleting any SK_*_DEL nodes first.
"""
allSets = pm.ls(type='objectSet')
skSets = [s for s in allSets if s.name().startswith(
"SK_") and not s.name().endswith("_DEL")]
# track the sets by name, since we will need to re-open the source file repeatedly
skSetNames = [s.name() for s in skSets]
for skSetName in skSetNames:
# cleanly re-open the file...
pm.openFile(sourceScenePath, force=True)
# get the set
skSet = pm.PyNode(skSetName)
setMembers = pm.sets(skSet, q=True)
if not setMembers:
pm.warning("Nothing to export from set: %s" % skSetName)
continue
rig = pulse.core.rigs.get_rig_from_node(setMembers[0])
if rig:
# break bake node connections
bake_nodes = pulse.core.rigs.Rig(rig).get_bake_nodes()
for node in bake_nodes:
node.t.setLocked(False)
node.r.setLocked(False)
node.s.setLocked(False)
node.sh.setLocked(False)
node.t.disconnect()
node.r.disconnect()
node.s.disconnect()
node.sh.disconnect()
# delete the 'ctls' core hierarchy from the rig
ctls = pulse.core.rigs.Rig(rig).get_core_hierarchy_node('ctls')
if ctls:
pm.delete(ctls)
# look for a _DEL set and delete its members
try:
skDelSet = pm.PyNode(skSetName + '_DEL')
except:
skDelSet = None
delSetMembers = pm.sets(skDelSet, q=True) if skDelSet else []
top_nodes = pulse.nodes.get_parent_nodes(setMembers)
for top_node in top_nodes:
top_node.setParent(None)
pm.delete(delSetMembers)
destFilePath = os.path.join(destDir, skSetName + '.fbx')
exportFBX(destFilePath, setMembers)
# re-open the file again to finish in a clean state
pm.openFile(sourceScenePath, force=True)
def exportFBX(destFilePath, nodes):
if not nodes:
return
pm.select(nodes)
pm.mel.FBXResetExport()
# core
pm.mel.eval('FBXProperty "Export|AdvOptGrp|AxisConvGrp|UpAxis" -v "Z"')
pm.mel.eval('FBXProperty "Export|IncludeGrp|InputConnectionsGrp|IncludeChildren" -v 0')
# meshes
pm.mel.eval('FBXProperty "Export|IncludeGrp|Geometry|SmoothingGroups" -v 1')
pm.mel.eval('FBXProperty "Export|IncludeGrp|Geometry|expHardEdges" -v 0')
pm.mel.eval('FBXProperty "Export|IncludeGrp|Geometry|TangentsandBinormals" -v 1')
pm.mel.eval('FBXProperty "Export|IncludeGrp|Geometry|SmoothMesh" -v 1')
# animation
pm.mel.eval('FBXProperty "Export|IncludeGrp|Animation" -v 0')
pm.mel.eval('FBXProperty "Export|IncludeGrp|Animation|BakeComplexAnimation" -v 1')
pm.mel.eval('FBXProperty "Export|AdvOptGrp|Collada|FrameRate" -v 30')
#export
pm.mel.FBXExport(f=destFilePath, s=True)
def exportSKSetsForCurrentScene():
sceneName = pm.sceneName()
if not sceneName:
raise ValueError("Current scene is not saved")
sourceScenePath = str(sceneName).replace('\\', '/')
workIndex = sourceScenePath.find('/work/')
destDir = sourceScenePath[:workIndex] + '/publish/unreal'
exportSKSets(sourceScenePath, destDir)
exportSKSetsForCurrentScene()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment