Professional Documents
Culture Documents
import pymel.core as pm
import maya.cmds as mc
import os
class TinyDAG(object):
#
# Small helper class to keep track of parents
#
def __str__(self):
# returns object name
return str(self.obj)
def _fullPath(self):
# returns full object path
if self.pObj is not None:
return "%s|%s" % (self.pObj._fullPath(), self.__str__())
return str(self.obj)
class BVHImporterDialog(object):
#
# Dialog class..
#
# UI related
self._textfield = ""
self._scaleField = ""
self._frameField = ""
self._rotationOrder = ""
self._reload = ""
# Other
self._rootNode = None # Used for targeting
self._debug = debug
self.setup_ui()
def setup_ui(self):
# Creates the great dialog
win = self._name
if mc.window(win, ex=True):
mc.deleteUI(win)
mc.columnLayout(adj=1, rs=5)
mc.separator()
mc.text("Options")
mc.separator()
mc.rowColumnLayout( numberOfColumns=2,
columnWidth=[(1, 80), (2, 150)],
cal=[(1, "right"), (2, "center")],
cs=[(1,5), (2,5)],
rs=[(1,5), (2,5)])
mc.text("Rig scale")
self._scaleField = mc.floatField(minValue=0.01, maxValue=2, value=1)
mc.text("Frame offset")
self._frameField = mc.intField(minValue=0)
mc.text("Rotation Order")
self._rotationOrder = mc.optionMenu()
mc.menuItem( label='XYZ' )
mc.menuItem( label='YZX' )
mc.menuItem( label='ZXY' )
mc.menuItem( label='XZY' )
mc.menuItem( label='YXZ' )
mc.menuItem( label='ZYX' )
mc.setParent("..")
mc.separator()
# Targeting UI
mc.text("Skeleton Targeting")
mc.text("(Select the hips)")
mc.separator()
mc.rowColumnLayout( numberOfColumns=2,
columnWidth=[(1, 150), (2, 80)],
cs=[(1,5), (2,5)],
rs=[(1,5), (2,5)])
self._textfield = mc.textField(editable=False)
mc.button("Select/Clear", c=self._on_select_root)
mc.setParent("..")
mc.separator()
mc.button("Import..", c=self._on_select_file)
self._reload = mc.button("Reload", enable=False, c=self._read_bvh)
# Sorry :)
mc.text("Created by Jeroen Hoolmans")
if dialog is None:
return
if not len(dialog):
return
self._filename = dialog[0]
# Action!
self._read_bvh()
with open(self._filename) as f:
# Check to see if the file is valid (sort of)
if not f.next().startswith("HIERARCHY"):
mc.error("No valid .bvh file selected.")
return False
if self._rootNode is None:
# Create a group for the rig, easier to scale. (Freeze
transform when ungrouping please..)
mocapName = os.path.basename(self._filename)
grp = pm.group(em=True,name="_mocap_%s_grp" % mocapName)
grp.scale.set(rigScale, rigScale, rigScale)
for line in f:
line = line.replace(" "," ") # force spaces
if not motion:
# root joint
if line.startswith("ROOT"):
# Set the Hip joint as root
if self._rootNode:
myParent = TinyDAG(str(self._rootNode),
None)
else:
myParent = TinyDAG(line[5:].rstrip(),
myParent)
if "JOINT" in line:
jnt = line.split(" ")
# Create the joint
myParent = TinyDAG(jnt[-1].rstrip(), myParent)
if "}" in line:
# Ignore when safeClose is on
if safeClose:
safeClose = False
continue
# Go up one level
if myParent is not None:
myParent = myParent.pObj
if myParent is not None:
mc.select(myParent._fullPath())
if "CHANNELS" in line:
chan = line.strip().split(" ")
if self._debug:
print chan
if "OFFSET" in line:
offset = line.strip().split(" ")
if self._debug:
print offset
jntName = str(myParent)
# skip if exists
if mc.objExists(myParent._fullPath()):
jnt = pm.PyNode(myParent._fullPath())
jnt.rotateOrder.set(rotOrder)
jnt.translate.set([float(offset[1]),
float(offset[2]), float(offset[3])])
continue
if "MOTION" in line:
# Animate!
motion = True
if self._debug:
if myParent is not None:
print "parent: %s" % myParent._fullPath()
else:
# We don't really need to use Framecount and
time(since Python handles file reads nicely)
if "Frame" not in line:
data = line.split(" ")
if len(data) > 0:
if data[0] == "": data.pop(0)
if self._debug:
print "Animating.."
print "Data size: %d" % len(data)
print "Channels size: %d" %
len(self._channels)
# Set the values to channels
for x in range(0, len(data) - 1 ):
if self._debug:
print "Set Attribute: %s %f" %
(self._channels[x], float(data[x]))
mc.setKeyframe(self._channels[x],
time=frame, value=float(data[x]))
frame = frame + 1
def _clear_animation(self):
# select root joint
pm.select(str(self._rootNode), hi=True)
nodes = pm.ls(sl=True)
if __name__ == "__main__":
dialog = BVHImporterDialog()