Yeah, I wrote a script that turns the eyes and lips curves into ribbons. It changes the curve constraint to a nurbs ribbon that is skinned by joints I add at the position of each controller. (You can just loft the existing curves to make the ribbon.)
That way I can use the face rig components without mGear plugins at least.
- I have not even attempted to remove the IK solvers, or make a custom vanilla Shifter component. That will be a much bigger job.
- It’s a bit too integrated with my other tools, so this won’t run for you without modification.
- Eyes is similar.
- Some parts of this script might also depend on my own custom naming conventions.
- I haven’t tested this since mGear 3.7.11 when the new matrix constraint plugin was added, so this also might not work anymore! This is just for inspiration:
import pymel.core as pm
from mgear import rigbits
from mgear.core import attribute, primitive, curve
def turn_lips_to_ribbon():
''' Turn the lips motion paths into ribbons. '''
# Create some intial groups
org = pm.group(em=True, n='lips_ribbon_org')
face_org = pm.PyNode('face_org')
joint_org = pm.group(em=True, n='lips_control_joints_org')
pm.parent(org, face_org)
pm.parent(joint_org, org)
org.visibility.set(0)
upLipCurve = pm.PyNode('lips_C_upCtl_crv')
lowLipCurve = pm.PyNode('lips_C_lowCtl_crv')
# Create loft curves
up1 = pm.duplicate(upLipCurve, n='lips_C_up_crvA')[0]
up2 = pm.duplicate(upLipCurve, n='lips_C_up_crvA')[0]
low1 = pm.duplicate(lowLipCurve, n='lips_C_up_crvA')[0]
low2 = pm.duplicate(lowLipCurve, n='lips_C_up_crvA')[0]
up2.tz.set(-2)
low2.tz.set(-2)
pm.parent(up1, up2, low1, low2, None)
# Loft them into ribbons
upLoft = pm.loft(up1, up2, ch=False, range=True, n='lips_C_up_ribbon')[0]
lowLoft = pm.loft(low1, low2, ch=False, range=True, n='lips_C_low_ribbon')[0]
pm.delete(up1, up2, low1, low2)
pm.parent(upLoft, lowLoft, org)
# Get the lipRopes for all the remaining joints.
lipRopes = []
for each in pm.ls('lips_C0*_*LipRope_jnt', type='joint'):
ropeNode = each.inputs(type='decomposeMatrix')[0].inputs()[0].inputs()[0]
lipRopes.append(ropeNode)
upRopes = [rope for rope in lipRopes if 'up' in rope.name()]
lowRopes = [rope for rope in lipRopes if 'low' in rope.name()]
# Delete any existing constraints on the ropes
badConstraints = pm.PyNode('lips_C_rope').getChildren(ad=True, type='constraint')
pm.delete(badConstraints)
# Plot a matrix follicle at the closestPoint for every lipRope transform.
# Disconnect and constrain or parent the ropes under the follicles.
def plot_folls(org, ribbon, coll, scaleMeasure):
oRoot = pm.group(em=True, n=ribbon.name() + '_folls')
pm.parent(oRoot, org)
for eachJoint in coll:
oFoll = create_follicle.pin_to_surface(ribbon, eachJoint, 5, 5)
oLoc = pm.group(em=True, n=oFoll.getTransform().name() + '_ROOT#')
oLoc.setTranslation(oFoll.getTransform().getTranslation(space='world'), space='world')
pm.parent(oLoc, oFoll.getTransform())
pm.parent(oFoll.getTransform(), oRoot)
oLoc.r.set([0,0,0])
for eachAttr in ['t', 'r', 's', 'tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz']:
eachJoint.attr(eachAttr).disconnect()
#pm.parentConstraint(oFoll.getTransform(), eachJoint, mo=True)
#pm.scaleConstraint(oFoll.getTransform(), eachJoint, mo=True)
pm.parent(eachJoint, oLoc)
scaleMeasure.sx.connect(oFoll.getTransform().sx)
scaleMeasure.sy.connect(oFoll.getTransform().sy)
scaleMeasure.sz.connect(oFoll.getTransform().sz)
# rig parent, ribbon, list of nodes to plot closest point to.
plot_folls(org, upLoft, upRopes, pm.PyNode('head_scale_measure'))
plot_folls(org, lowLoft, lowRopes, pm.PyNode('head_scale_measure'))
# Create control joints to skin the ribbons to.
upperLipControls = pm.ls(['lips_R_corner_ctl', 'lips_R_upOuter_ctl', 'lips_R_upInner_ctl', 'lips_C_upper_ctl', 'lips_L_upInner_ctl', 'lips_L_upOuter_ctl', 'lips_L_corner_ctl'])
lowerLipControls = pm.ls(['lips_R_corner_ctl', 'lips_R_lowOuter_ctl', 'lips_R_lowInner_ctl', 'lips_C_lower_ctl', 'lips_L_lowInner_ctl', 'lips_L_lowOuter_ctl', 'lips_L_corner_ctl'])
upJoints = []
for each in upperLipControls:
pm.select(None)
if pm.objExists(each.name().replace('_ctl','_ribbon_ctl_jnt')):
oJoint = pm.PyNode(each.name().replace('_ctl','_ribbon_ctl_jnt'))
else:
oJoint = pm.joint(n=each.name().replace('_ctl','_ribbon_ctl_jnt'))
pm.parentConstraint(each, oJoint, mo=False)
pm.scaleConstraint(each, oJoint, mo=True)
upJoints.append(oJoint)
lowJoints = []
for each in lowerLipControls:
pm.select(None)
if pm.objExists(each.name().replace('_ctl','_ribbon_ctl_jnt')):
oJoint = pm.PyNode(each.name().replace('_ctl','_ribbon_ctl_jnt'))
else:
oJoint = pm.joint(n=each.name().replace('_ctl','_ribbon_ctl_jnt'))
pm.parentConstraint(each, oJoint, mo=False)
pm.scaleConstraint(each, oJoint, mo=True)
lowJoints.append(oJoint)
pm.parent(upJoints, lowJoints, joint_org)
oSkin = tenave.skin_geometry(upJoints, upLoft, 'upper_lip_ribbon_skinCluster')
oSkin = tenave.skin_geometry(lowJoints, lowLoft, 'lower_lip_ribbon_skinCluster')
# Delete all the remaining lip curves, wires and unused lip rope transforms.
pm.delete(pm.PyNode('lips_C_rope'), pm.PyNode('lips_C_crvs'))
# Constrain the 2 end joints to the corner lips.
rightLips = pm.ls(
"lips_C000_upLipRope",
"lips_C001_upLipRope",
"lips_C000_lowLipRope",
"lips_C001_lowLipRope",
type='transform')
leftLips = pm.ls(
"lips_C023_upLipRope",
"lips_C024_upLipRope",
"lips_C023_lowLipRope",
"lips_C024_lowLipRope",
type='transform')
rightLipControl = pm.PyNode('lips_R_corner_ctl')
leftLipControl = pm.PyNode('lips_L_corner_ctl')
for each in rightLips:
pm.orientConstraint(rightLipControl, each.getParent(), mo=True)
for each in leftLips:
pm.orientConstraint(leftLipControl, each.getParent(), mo=True)
def remove_mgear_eye_curve_nodes():
#TODO: Add a check so it only runs over eyes.
for curveCns in pm.ls(type='mgear_curveCns'):
inputControls = curveCns.inputs(type='transform')
outCurve = outCurve = curveCns.outputs(type='nurbsCurve')[0]
if not 'eye_' in outCurve.name():
continue
oRoot = outCurve.getParent(2)
if pm.objExists(oRoot.name().replace('_root','_controlJoints_org')):
jointRoot = pm.PyNode(oRoot.name().replace('_root','_controlJoints_org'))
else:
jointRoot = pm.group(em=True, n=oRoot.name().replace('_root','_controlJoints_org'))
pm.parent(jointRoot, oRoot)
newControlJoints = []
# Curve will double transform
outCurve.inheritsTransform.set(0)
# Delete the history on the curve. Deleting the curveCns causes the right side to flip.
pm.delete(outCurve, constructionHistory=True)
#pm.delete(curveCns)
for each in inputControls:
pm.select(None)
if pm.objExists(each.name().replace('_ctrl','_jnt').replace('_ctl','_jnt')):
oJoint = pm.PyNode(each.name().replace('_ctrl','_jnt').replace('_ctl','_jnt'))
else:
oJoint = pm.joint(n=each.name().replace('_ctrl','_jnt').replace('_ctl','_jnt'))
pm.parentConstraint(each, oJoint, mo=False)
pm.scaleConstraint(each, oJoint, mo=True)
pm.parent(oJoint, jointRoot)
newControlJoints.append(oJoint)
oSkin = tenave.skin_geometry(newControlJoints, outCurve, '{}_skinCluster'.format(outCurve.name()))