Skip to content

Instantly share code, notes, and snippets.

@miabrahams
Created April 16, 2021 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save miabrahams/b4c16af0f13385320fcdcdb8b97dad4a to your computer and use it in GitHub Desktop.
Save miabrahams/b4c16af0f13385320fcdcdb8b97dad4a to your computer and use it in GitHub Desktop.
Mocap tools with namespace support
import os
import pymel.core as pm
import mgear.core.attribute as att
import mgear.core.transform as tra
import mgear.shifter.component as comp
from mgear.core.anim_utils import getNamespace
# All FK joints used to align the skeleton
# Rig FK controls will be constrained to these
mocapFK = [
u"mGear_Mocap_interface_" + joint
for joint in (
u"Hips",
u"LeftUpLeg",
u"LeftLeg",
u"LeftFoot",
u"LeftToeBase",
u"RightUpLeg",
u"RightLeg",
u"RightFoot",
u"RightToeBase",
u"Spine",
u"Spine1",
u"Spine2",
u"LeftShoulder",
u"LeftArm",
u"LeftForeArm",
u"LeftHand",
u"LeftHandThumb1",
u"LeftHandThumb2",
u"LeftHandThumb3",
u"LeftHandIndex1",
u"LeftHandIndex2",
u"LeftHandIndex3",
u"LeftHandMiddle1",
u"LeftHandMiddle2",
u"LeftHandMiddle3",
u"LeftHandRing1",
u"LeftHandRing2",
u"LeftHandRing3",
u"LeftHandPinky1",
u"LeftHandPinky2",
u"LeftHandPinky3",
u"RightShoulder",
u"RightArm",
u"RightForeArm",
u"RightHand",
u"RightHandThumb1",
u"RightHandThumb2",
u"RightHandThumb3",
u"RightHandIndex1",
u"RightHandIndex2",
u"RightHandIndex3",
u"RightHandMiddle1",
u"RightHandMiddle2",
u"RightHandMiddle3",
u"RightHandRing1",
u"RightHandRing2",
u"RightHandRing3",
u"RightHandPinky1",
u"RightHandPinky2",
u"RightHandPinky3",
u"Neck",
u"Neck1",
u"Head"
)
]
rigFK = [
u"body_C0_ctl",
u"leg_L0_fk0_ctl",
u"leg_L0_fk1_ctl",
u"leg_L0_fk2_ctl",
u"foot_L0_fk0_ctl",
u"leg_R0_fk0_ctl",
u"leg_R0_fk1_ctl",
u"leg_R0_fk2_ctl",
u"foot_R0_fk0_ctl",
u"spine_C0_fk0_ctl",
u"spine_C0_fk1_ctl",
u"spine_C0_fk2_ctl",
u"shoulder_L0_ctl",
u"arm_L0_fk0_ctl",
u"arm_L0_fk1_ctl",
u"arm_L0_fk2_ctl",
u"thumb_L0_fk0_ctl",
u"thumb_L0_fk1_ctl",
u"thumb_L0_fk2_ctl",
u"finger_L0_fk0_ctl",
u"finger_L0_fk1_ctl",
u"finger_L0_fk2_ctl",
u"finger_L1_fk0_ctl",
u"finger_L1_fk1_ctl",
u"finger_L1_fk2_ctl",
u"finger_L2_fk0_ctl",
u"finger_L2_fk1_ctl",
u"finger_L2_fk2_ctl",
u"finger_L3_fk0_ctl",
u"finger_L3_fk1_ctl",
u"finger_L3_fk2_ctl",
u"shoulder_R0_ctl",
u"arm_R0_fk0_ctl",
u"arm_R0_fk1_ctl",
u"arm_R0_fk2_ctl",
u"thumb_R0_fk0_ctl",
u"thumb_R0_fk1_ctl",
u"thumb_R0_fk2_ctl",
u"finger_R0_fk0_ctl",
u"finger_R0_fk1_ctl",
u"finger_R0_fk2_ctl",
u"finger_R1_fk0_ctl",
u"finger_R1_fk1_ctl",
u"finger_R1_fk2_ctl",
u"finger_R2_fk0_ctl",
u"finger_R2_fk1_ctl",
u"finger_R2_fk2_ctl",
u"finger_R3_fk0_ctl",
u"finger_R3_fk1_ctl",
u"finger_R3_fk2_ctl",
u"neck_C0_fk0_ctl",
u"neck_C0_fk1_ctl",
u"neck_C0_head_ctl"
]
# Subset used to align IK controls
alignFK = [
u"arm_L0_fk2_ctl",
u"arm_L0_ikcns_ctl",
u"arm_L0_fk1_ctl",
u"arm_R0_fk2_ctl",
u"arm_R0_ikcns_ctl",
u"arm_R0_fk1_ctl"]
alignIK = [
u"arm_L0_ikcns_ctl",
u"arm_L0_ik_ctl",
u"arm_L0_upv_ctl",
u"arm_R0_ikcns_ctl",
u"arm_R0_ik_ctl",
u"arm_R0_upv_ctl"
]
mocapIK = [
u"mGear_Mocap_interface_LeftFoot",
u"mGear_Mocap_interface_RightFoot",
u"mGear_Mocap_interface_LeftUpLeg",
u"mGear_Mocap_interface_RightUpLeg",
u"mGear_Mocap_interface_LeftHand",
u"mGear_Mocap_interface_LeftForeArm",
u"mGear_Mocap_interface_RightHand",
u"mGear_Mocap_interface_RightForeArm",
u"mGear_Mocap_interface_LeftLeg",
u"mGear_Mocap_interface_RightLeg",
u"mGear_Mocap_interface_LeftForeArm",
u"mGear_Mocap_interface_RightForeArm"
]
rigIK = [
u"leg_L0_ik_ctl",
u"leg_R0_ik_ctl",
u"leg_L0_upv_ctl",
u"leg_R0_upv_ctl",
u"arm_L0_ik_ctl",
u"arm_L0_upv_ctl",
u"arm_R0_ik_ctl",
u"arm_R0_upv_ctl",
u"leg_L0_mid_ctl",
u"leg_R0_mid_ctl",
u"arm_L0_mid_ctl",
u"arm_R0_mid_ctl"
]
def importSkeletonBiped(*args):
path = os.path.dirname(comp.__file__)
pm.importFile(os.path.join(path, "_templates", "MOCAP_interface_01.ma"))
def getMocapAttach(ns):
try:
gCtl = pm.PyNode(ns + "global_C0_ctl")
if gCtl.hasAttr("mocapAttach"):
mocapAttach = gCtl.mocapAttach
mocapAttach.set(1)
else:
mocapAttach = att.addAttribute(
gCtl,
"mocapAttach",
"float",
1.0,
minValue=0.0,
maxValue=1.0
)
return mocapAttach
except Exception:
pm.displayWarning("global_C0_ctl: Is not in the scene")
return None
def matchSkeleton(ns, *args):
if not getMocapAttach(ns):
return
# Align mocap skeleton to rig
for a, b in zip(mocapFK, rigFK):
try:
oA = pm.PyNode(a)
except Exception:
pm.displayWarning(a + ": Is not in the scene")
continue
try:
oB = pm.PyNode(ns + b)
except Exception:
pm.displayWarning(b + ": Is not in the scene")
continue
tra.matchWorldTransform(oB, oA)
def characterizeBiped(ns, *args):
mocapAttach = getMocapAttach(ns)
# Constrain FK controls
for a, b in zip(mocapFK, rigFK):
oA = pm.PyNode(a)
oB = pm.PyNode(ns + b)
cns = pm.parentConstraint(oA, oB, mo=True)
pb_node = pm.createNode("pairBlend")
pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
pm.connectAttr(pb_node + ".outRotateX", oB + ".rotateX", f=True)
pm.connectAttr(pb_node + ".outRotateY", oB + ".rotateY", f=True)
pm.connectAttr(pb_node + ".outRotateZ", oB + ".rotateZ", f=True)
pm.setKeyframe(oB, at="rotateX")
pm.setKeyframe(oB, at="rotateY")
pm.setKeyframe(oB, at="rotateZ")
pm.connectAttr(cns + ".constraintTranslateX",
pb_node + ".inTranslateX2")
pm.connectAttr(cns + ".constraintTranslateY",
pb_node + ".inTranslateY2")
pm.connectAttr(cns + ".constraintTranslateZ",
pb_node + ".inTranslateZ2")
pm.connectAttr(pb_node + ".outTranslateX", oB + ".translateX", f=True)
pm.connectAttr(pb_node + ".outTranslateY", oB + ".translateY", f=True)
pm.connectAttr(pb_node + ".outTranslateZ", oB + ".translateZ", f=True)
pm.setKeyframe(oB, at="translateX")
pm.setKeyframe(oB, at="translateY")
pm.setKeyframe(oB, at="translateZ")
pm.connectAttr(mocapAttach, pb_node.attr("weight"))
# Align IK controls with FK controls
for a, b in zip(alignIK, alignFK):
oA = pm.PyNode(ns + a)
oB = pm.PyNode(ns + b)
tra.matchWorldTransform(oB, oA)
if a in [u"arm_L0_upv_ctl", u"arm_R0_upv_ctl"]:
oA.attr("tz").set(-3)
if a == u"arm_L0_ikcns_ctl":
oA.attr("rx").set((oA.attr("rx").get() + 90))
if a == u"arm_R0_ikcns_ctl":
oA.attr("rx").set((oA.attr("rx").get() - 90))
# constrain IK controls
for a, b in zip(mocapIK, rigIK):
oA = pm.PyNode(a)
oB = pm.PyNode(ns + b)
print(b)
pb_node = pm.createNode("pairBlend")
try:
if b in (u"leg_L0_upv_ctl", u"leg_R0_upv_ctl"):
att.lockAttribute(pm.PyNode(b), lock=False, keyable=True)
if b in (u"leg_L0_mid_ctl",
u"leg_R0_mid_ctl",
u"arm_L0_mid_ctl",
u"arm_R0_mid_ctl"):
cns = pm.pointConstraint(oA, oB, mo=True)
else:
cns = pm.parentConstraint(oA, oB, mo=True)
pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
pm.connectAttr(pb_node + ".outRotateX", oB + ".rotateX", f=True)
pm.connectAttr(pb_node + ".outRotateY", oB + ".rotateY", f=True)
pm.connectAttr(pb_node + ".outRotateZ", oB + ".rotateZ", f=True)
pm.setKeyframe(oB, at="rotateX")
pm.setKeyframe(oB, at="rotateY")
pm.setKeyframe(oB, at="rotateZ")
except Exception:
cns = pm.pointConstraint(oA, oB, mo=True)
pm.connectAttr(cns + ".constraintTranslateX",
pb_node + ".inTranslateX2")
pm.connectAttr(cns + ".constraintTranslateY",
pb_node + ".inTranslateY2")
pm.connectAttr(cns + ".constraintTranslateZ",
pb_node + ".inTranslateZ2")
pm.connectAttr(pb_node + ".outTranslateX", oB + ".translateX", f=True)
pm.connectAttr(pb_node + ".outTranslateY", oB + ".translateY", f=True)
pm.connectAttr(pb_node + ".outTranslateZ", oB + ".translateZ", f=True)
pm.setKeyframe(oB, at="translateX")
pm.setKeyframe(oB, at="translateY")
pm.setKeyframe(oB, at="translateZ")
pm.connectAttr(mocapAttach, pb_node.attr("weight"))
def bakeMocap(ns, *args):
start = pm.playbackOptions(query=True, min=True)
end = pm.playbackOptions(query=True, max=True)
if pm.selected() and pm.selected()[0].name()[-3:] == "ctl":
controls = [ns + c for c in rigFK + rigIK]
# Using a custom bake system because bakeResults is
# slow with pairblend nodes.
for x in range(int(start), int(end + 1)):
pm.currentTime(x)
pm.setKeyframe(controls)
else:
pm.displayWarning("Please select on control of the rig to "
"determine which character will be baked")
# To reset
def reset_setup(ns, *args):
getMocapAttach(ns).set(0)
pm.delete(pm.ls("pairBlend*"))
pm.delete(pm.ls("mocap*"))
pm.delete(pm.ls("*mGear_Mocap*"))
pm.delete(pm.ls("MOCAP*"))
for c in pm.ls("*Constraint*"):
try:
pm.delete(c)
print(c)
except Exception as e:
continue
class MocapUI():
"""Mocap tools UI"""
def __init__(self):
self.namespaceField = None
return
def show(self):
if pm.window("mGear_mocap_window", exists=True):
pm.deleteUI("mGear_mocap_window")
window = pm.window("mGear_mocap_window",
title="mGear mocap tool",
w=350,
h=150,
mxb=False,
sizeable=False)
pm.columnLayout(columnAttach=('both', 5),
rowSpacing=10, columnWidth=350)
pm.text("Choose Namespace")
pm.namespace(setNamespace=':')
namespaces = pm.namespaceInfo(listOnlyNamespaces=True, recurse=True)
namespaces = [ns + ":" for ns in namespaces[0:-2]]
namespaces = [':'] + namespaces
self.namespaceField = pm.textScrollList("namespaceList",
numberOfRows=8,
append=namespaces,
w=100, sii=1)
pm.button(label="Reset setup", w=150, h=50,
command=self.reset_setup)
pm.button(label="Import mocap skeleton", w=150, h=50,
command=importSkeletonBiped)
pm.button(label="Match skeleton to rig", w=150, h=50,
command=self.matchSkeleton)
pm.button(label="Create HIK control rig", w=150, h=50,
command=self.createControlRig)
pm.button(label="Characterize skeleton", w=150, h=50,
command=self.characterize)
pm.button(label="Bake Mocap", w=150, h=50,
command=self.bakeMocap)
pm.showWindow(window)
return
def ns(self):
return self.namespaceField.getSelectItem()
def reset_setup(self, *args):
reset_setup(self.ns())
def matchSkeleton(self, *args):
matchSkeleton(self.ns())
def createControlRig(self, *args):
pm.mel.eval('hikSetCurrentCharacter("mGear_Mocap_interface");hikCreateControlRig()')
def bakeMocap(self, *args):
bakeMocap(self.ns())
def characterize(self, *args):
characterizeBiped(self.ns())
def show_ui(*args):
"""Show UI"""
M = MocapUI()
M.show()
return M
show_ui()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment