def addTangentMPTo(startMP, endMP, direction, default=0.5, reverse=False): ''' add a "tangent" attribute to startLoc, and a tangentLoc to startLoc at 0, tangentLoc would be exactly on startLoc at 1, tangentLoc would be projected on direction vector onto endLoc's plane direction (string): 'x', 'y', or 'z' reverse (bool): reverse direction return tangentLoc ''' # add tangentLoc tangentLoc = mc.spaceLocator(n=startMP+'_tangent_loc')[0] rt.parentSnap(tangentLoc, startMP) # add planeLoc - moves on plane of endMP, to help calculcate max distance planeLoc = mc.spaceLocator(n=endMP+'_plane_loc')[0] rt.parentSnap(planeLoc, endMP) # pointConstraint planeLoc to startMP # skip "direction" axis, to maintain sliding on endMP's plane mc.pointConstraint(startMP, planeLoc, skip=direction) # get distance between startMP and planeLoc # this is the maximum length for tangent maxDistance = cn.create_distanceBetween(startMP, planeLoc) # add "tangent" attribute to startMP mc.addAttr(startMP, ln='tangent', at='double', min=0, max=1, dv=default, k=True) # multiply tangent value by maxDistance tangentDistance = cn.create_multDoubleLinear(startMP+'.tangent', maxDistance) # reverse the direction if necessary if reverse: tangentDistance = cn.create_multDoubleLinear(tangentDistance, -1) # this will be used to drive the tangentLoc translatePlug = '%s.t%s' % (tangentLoc, direction) mc.connectAttr(tangentDistance, translatePlug, f=True) # connect locators for debug rt.connectVisibilityToggle((planeLoc, tangentLoc), startMP, 'debugTangentLocs', default=False) rt.connectVisibilityToggle(tangentLoc, startMP, 'tangentLoc', False) return tangentLoc
def addJntsOnSurfIntersection(surf1, surf2, jntsNum): ''' Places jnts along intersection curve between surf1 and surf2 naming convention based on surf1 ''' # intersect surfaces crvGrp, intNode = mc.intersect(surf1, surf2, fs=True, ch=True, o=True, cos=False)[:2] intNode = mc.rename(intNode, surf1+'_ints') crvGrp = mc.rename(crvGrp, surf1+'_ints_crv_grp') crv = mc.listRelatives(crvGrp, c=True)[0] crv = mc.rename(crv, surf1+'_ints_crv') # rebuild curve to jntNum spans rbdCrv, rbdNode = mc.rebuildCurve(crv, ch=True, o=True, rpo=False, spans=jntsNum, rt=0, kr=2, n=crv+'_rbd_crv') rbdNode = mc.rename(rbdNode, crv+'_rbd') # offset curve to control size of eye hole offsetCrv, offsetNode = mc.offsetCurve(rbdCrv, ch=True, distance=0, o=True, ugn=0, n=crv+'_offset_crv') offsetNode = mc.rename(offsetNode, crv+'_offset') locs = [] locName = '_'.join(surf1.split('_')[:2]) # attach locators to intersection curve for locId in range(jntsNum): loc = mc.spaceLocator(n=locName+'_loc_%d' % locId)[0] rt.attachToMotionPath(offsetCrv, locId, loc, fm=False) mc.setAttr(loc+'.localScale', 0.05, 0.05, 0.05) locs.append(loc) # normal constraint to surf1 for loc in locs: mc.normalConstraint(surf2, loc, aim=(1,0,0)) jnts = [] # add joints under locators for loc in locs: mc.select(cl=True) jnt = mc.joint(n=loc.replace('_loc_','_jnt_')) rt.parentSnap(jnt, loc) mc.setAttr(jnt+'.jointOrient', 0,0,0) jnts.append(jnt) # groups grp = mc.group(crvGrp, offsetCrv, rbdCrv, locs, n=surf1+'_intersect_loc_grp') # create offset attribute mc.addAttr(grp, ln='collideOffset', at='double', dv=0, k=True) offsetPlug = cn.create_multDoubleLinear(grp+'.collideOffset', -1) mc.connectAttr(offsetPlug, offsetNode+'.distance', f=True) # connect debug rt.connectVisibilityToggle(offsetCrv, grp, 'offsetCrv', False) rt.connectVisibilityToggle(rbdCrv, grp, 'rebuildCrv', False) rt.connectVisibilityToggle(crvGrp, grp, 'intersectCrv', False) rt.connectVisibilityToggle(locs, grp, 'crvLocs', False) rt.connectVisibilityToggle(jnts, grp, 'crvJnts', False)
def addFootRoll(ctl, heelPivot, ballPivot, toePivot): """ """ #=========================================================================== # ADD ATTRIBUTES for toe-straight, toe-lift and roll #=========================================================================== mc.addAttr(ctl, ln='roll', dv=0, at='double', k=True) mc.addAttr(ctl, ln='toeLift', dv=30, at='double', k=True) mc.addAttr(ctl, ln='toeStraight', dv=60, at='double', k=True) #=========================================================================== # CONNECT HEEL # just use negative roll values, ignore positive #=========================================================================== clp = mc.createNode('clamp', n=ctl + '_roll_heel_clp') mc.connectAttr(ctl + '.roll', clp + '.minR', f=True) mc.connectAttr(ctl + '.roll', clp + '.inputR', f=True) mc.connectAttr(clp + '.outputR', heelPivot + '.rx', f=True) #=========================================================================== # CONNECT TOE # linstep(lift, straight, roll) * roll #=========================================================================== srg = mc.createNode('setRange', n=ctl + '_roll_srg') mc.connectAttr(ctl + '.toeLift', srg + '.oldMinX', f=True) mc.connectAttr(ctl + '.toeStraight', srg + '.oldMaxX', f=True) mc.connectAttr(ctl + '.roll', srg + '.valueX', f=True) mc.connectAttr(ctl + '.roll', srg + '.maxX', f=True) mc.connectAttr(srg + '.outValueX', toePivot + '.rx', f=True) #=========================================================================== # CONNECT BALL # linstep(0, lift, roll) * (1 - linstep(lift, straight, roll)) * roll #=========================================================================== # "increasing" part mc.connectAttr(ctl + '.toeLift', srg + '.oldMaxY', f=True) mc.connectAttr(ctl + '.roll', srg + '.valueY', f=True) mc.connectAttr(ctl + '.toeLift', srg + '.maxY', f=True) # "decreasing" part mc.connectAttr(ctl + '.toeLift', srg + '.oldMinZ', f=True) mc.connectAttr(ctl + '.toeStraight', srg + '.oldMaxZ', f=True) mc.connectAttr(ctl + '.roll', srg + '.valueZ', f=True) mc.setAttr(srg + '.minZ', 1) mc.setAttr(srg + '.maxZ', 0) # reversed normalized range from 1-0 # multiply the parts ballVal = cn.create_multDoubleLinear(srg + '.outValueY', srg + '.outValueZ') mc.connectAttr(ballVal, ballPivot + '.rx', f=True)
def addFootRoll(ctl, heelPivot, ballPivot, toePivot): """ """ #=========================================================================== # ADD ATTRIBUTES for toe-straight, toe-lift and roll #=========================================================================== mc.addAttr(ctl, ln='roll', dv=0, at='double', k=True) mc.addAttr(ctl, ln='toeLift', dv=30, at='double', k=True) mc.addAttr(ctl, ln='toeStraight', dv=60, at='double', k=True) #=========================================================================== # CONNECT HEEL # just use negative roll values, ignore positive #=========================================================================== clp = mc.createNode('clamp', n=ctl+'_roll_heel_clp') mc.connectAttr(ctl+'.roll', clp+'.minR', f=True) mc.connectAttr(ctl+'.roll', clp+'.inputR', f=True) mc.connectAttr(clp+'.outputR', heelPivot+'.rx', f=True) #=========================================================================== # CONNECT TOE # linstep(lift, straight, roll) * roll #=========================================================================== srg = mc.createNode('setRange', n=ctl+'_roll_srg') mc.connectAttr(ctl+'.toeLift', srg+'.oldMinX', f=True) mc.connectAttr(ctl+'.toeStraight', srg+'.oldMaxX', f=True) mc.connectAttr(ctl+'.roll', srg+'.valueX', f=True) mc.connectAttr(ctl+'.roll', srg+'.maxX', f=True) mc.connectAttr(srg+'.outValueX', toePivot+'.rx', f=True) #=========================================================================== # CONNECT BALL # linstep(0, lift, roll) * (1 - linstep(lift, straight, roll)) * roll #=========================================================================== # "increasing" part mc.connectAttr(ctl+'.toeLift', srg+'.oldMaxY', f=True) mc.connectAttr(ctl+'.roll', srg+'.valueY', f=True) mc.connectAttr(ctl+'.toeLift', srg+'.maxY', f=True) # "decreasing" part mc.connectAttr(ctl+'.toeLift', srg+'.oldMinZ', f=True) mc.connectAttr(ctl+'.toeStraight', srg+'.oldMaxZ', f=True) mc.connectAttr(ctl+'.roll', srg+'.valueZ', f=True) mc.setAttr(srg+'.minZ', 1) mc.setAttr(srg+'.maxZ', 0) # reversed normalized range from 1-0 # multiply the parts ballVal = cn.create_multDoubleLinear(srg+'.outValueY', srg+'.outValueZ') mc.connectAttr(ballVal, ballPivot+'.rx', f=True)
def addJntsOnSurfIntersection(surf1, surf2, jntsNum): ''' Places jnts along intersection curve between surf1 and surf2 naming convention based on surf1 ''' # intersect surfaces crvGrp, intNode = mc.intersect(surf1, surf2, fs=True, ch=True, o=True, cos=False)[:2] intNode = mc.rename(intNode, surf1 + '_ints') crvGrp = mc.rename(crvGrp, surf1 + '_ints_crv_grp') crv = mc.listRelatives(crvGrp, c=True)[0] crv = mc.rename(crv, surf1 + '_ints_crv') # rebuild curve to jntNum spans rbdCrv, rbdNode = mc.rebuildCurve(crv, ch=True, o=True, rpo=False, spans=jntsNum, rt=0, kr=2, n=crv + '_rbd_crv') rbdNode = mc.rename(rbdNode, crv + '_rbd') # offset curve to control size of eye hole offsetCrv, offsetNode = mc.offsetCurve(rbdCrv, ch=True, distance=0, o=True, ugn=0, n=crv + '_offset_crv') offsetNode = mc.rename(offsetNode, crv + '_offset') locs = [] locName = '_'.join(surf1.split('_')[:2]) # attach locators to intersection curve for locId in range(jntsNum): loc = mc.spaceLocator(n=locName + '_loc_%d' % locId)[0] rt.attachToMotionPath(offsetCrv, locId, loc, fm=False) mc.setAttr(loc + '.localScale', 0.05, 0.05, 0.05) locs.append(loc) # normal constraint to surf1 for loc in locs: mc.normalConstraint(surf2, loc, aim=(1, 0, 0)) jnts = [] # add joints under locators for loc in locs: mc.select(cl=True) jnt = mc.joint(n=loc.replace('_loc_', '_jnt_')) rt.parentSnap(jnt, loc) mc.setAttr(jnt + '.jointOrient', 0, 0, 0) jnts.append(jnt) # groups grp = mc.group(crvGrp, offsetCrv, rbdCrv, locs, n=surf1 + '_intersect_loc_grp') # create offset attribute mc.addAttr(grp, ln='collideOffset', at='double', dv=0, k=True) offsetPlug = cn.create_multDoubleLinear(grp + '.collideOffset', -1) mc.connectAttr(offsetPlug, offsetNode + '.distance', f=True) # connect debug rt.connectVisibilityToggle(offsetCrv, grp, 'offsetCrv', False) rt.connectVisibilityToggle(rbdCrv, grp, 'rebuildCrv', False) rt.connectVisibilityToggle(crvGrp, grp, 'intersectCrv', False) rt.connectVisibilityToggle(locs, grp, 'crvLocs', False) rt.connectVisibilityToggle(jnts, grp, 'crvJnts', False)
def addOns(): ''' Add ons to Advanced Skeleton fitV027, buildV001 ''' # START WITH RIGHT SIDE #=========================================================================== # ADD REVERSE ROLL #=========================================================================== bendPivot, leftPivot, rightPivot = ms.placePivotsForReverseRoll( 'Wrist_R', (0.715, -0.011, 0.038), (0, -0.194, -0.687), (0, -0.194, 0.631)) jnts = [ 'Wrist_R', ['FKOffsetPinkyFinger1_R', 'FKXPinkyFinger3_R'], ['FKOffsetMiddleFinger1_R', 'FKXMiddleFinger3_R'], ['FKOffsetIndexFinger1_R', 'FKXIndexFinger3_R'], ['FKOffsetThumbFinger1_R', 'FKXThumbFinger3_R'] ] rollGrp, baseJnt = ms.addReverseRoll(jnts, bendPivot, leftPivot, rightPivot) # drive rollGrp via FKIK switching FKDriver = 'FKWrist_R' IKDriver = 'IKArm_R_IKFKOffsetBlend_grp' FKIKSwitch = 'FKIKArm_R' pCons = mc.parentConstraint(FKDriver, IKDriver, rollGrp, mo=True)[0] wal = mc.parentConstraint(pCons, q=True, wal=True) FKIKValue = cn.create_multDoubleLinear(FKIKSwitch + '.FKIKBlend', 0.1) #=========================================================================== # SET DRIVERS AND DRIVENS #=========================================================================== # drive blend in constraint rollGrp = rollGrp.split('|')[1] rev = mc.createNode('reverse', n=rollGrp + '_FKIKSwitch_rev') mc.connectAttr(FKIKValue, rev + '.inputX', f=True) mc.connectAttr(rev + '.outputX', pCons + '.' + wal[0], f=True) mc.connectAttr(FKIKValue, pCons + '.' + wal[1], f=True) # baseJnt to drive ikHandle & IKFKOffsetBlend IKHandle = 'IKXArmHandle_R' IKFKMix = 'FKIKMixWrist_R' mc.parentConstraint(baseJnt, IKHandle, mo=True) mc.delete(IKFKMix + '_parentConstraint1') mc.parentConstraint(baseJnt, IKFKMix, mo=True) #=========================================================================== # FIX LENGTH MEASUREMENT #=========================================================================== endLoc = 'IKmessureConstrainToArm_R' mc.parentConstraint(baseJnt, endLoc) # DO SAME FOR LEFT SIDE #=========================================================================== # ADD REVERSE ROLL #=========================================================================== bendPivot, leftPivot, rightPivot = ms.placePivotsForReverseRoll( 'Wrist_L', (-0.715, -0.011, 0.038), (0, 0.194, -0.687), (0, 0.194, 0.631)) jnts = [ 'Wrist_L', ['FKOffsetPinkyFinger1_L', 'FKXPinkyFinger3_L'], ['FKOffsetMiddleFinger1_L', 'FKXMiddleFinger3_L'], ['FKOffsetIndexFinger1_L', 'FKXIndexFinger3_L'], ['FKOffsetThumbFinger1_L', 'FKXThumbFinger3_L'] ] rollGrp, baseJnt = ms.addReverseRoll(jnts, bendPivot, rightPivot, leftPivot) # drive rollGrp via FKIK switching FKDriver = 'FKWrist_L' IKDriver = 'IKArm_L_IKFKOffsetBlend_grp' FKIKSwitch = 'FKIKArm_L' pCons = mc.parentConstraint(FKDriver, IKDriver, rollGrp, mo=True)[0] wal = mc.parentConstraint(pCons, q=True, wal=True) FKIKValue = cn.create_multDoubleLinear(FKIKSwitch + '.FKIKBlend', 0.1) #=========================================================================== # SET DRIVERS AND DRIVENS #=========================================================================== # drive blend in constraint rollGrp = rollGrp.split('|')[1] rev = mc.createNode('reverse', n=rollGrp + '_FKIKSwitch_rev') mc.connectAttr(FKIKValue, rev + '.inputX', f=True) mc.connectAttr(rev + '.outputX', pCons + '.' + wal[0], f=True) mc.connectAttr(FKIKValue, pCons + '.' + wal[1], f=True) # baseJnt to drive ikHandle & IKFKOffsetBlend IKHandle = 'IKXArmHandle_L' IKFKMix = 'FKIKMixWrist_L' mc.parentConstraint(baseJnt, IKHandle, mo=True) mc.delete(IKFKMix + '_parentConstraint1') mc.parentConstraint(baseJnt, IKFKMix, mo=True) #=========================================================================== # FIX LENGTH MEASUREMENT #=========================================================================== endLoc = 'IKmessureConstrainToArm_L' mc.parentConstraint(baseJnt, endLoc)
def reverseAttr(obj, attr): outPlugs = mc.listConnections(obj+'.'+attr, s=False, p=True) revPlug = cn.create_multDoubleLinear(obj+'.'+attr, -1) for eachPlug in outPlugs: mc.connectAttr(revPlug, eachPlug, f=True)
def reverseAttr(obj, attr): outPlugs = mc.listConnections(obj + '.' + attr, s=False, p=True) revPlug = cn.create_multDoubleLinear(obj + '.' + attr, -1) for eachPlug in outPlugs: mc.connectAttr(revPlug, eachPlug, f=True)
def addOns(): ''' Add ons to Advanced Skeleton fitV027, buildV001 ''' # START WITH RIGHT SIDE #=========================================================================== # ADD REVERSE ROLL #=========================================================================== bendPivot, leftPivot, rightPivot = ms.placePivotsForReverseRoll('Wrist_R', (0.715, -0.011, 0.038), (0,-0.194,-0.687), (0,-0.194,0.631)) jnts = ['Wrist_R', ['FKOffsetPinkyFinger1_R', 'FKXPinkyFinger3_R'], ['FKOffsetMiddleFinger1_R', 'FKXMiddleFinger3_R'], ['FKOffsetIndexFinger1_R', 'FKXIndexFinger3_R'], ['FKOffsetThumbFinger1_R', 'FKXThumbFinger3_R'] ] rollGrp, baseJnt = ms.addReverseRoll(jnts, bendPivot, leftPivot, rightPivot) # drive rollGrp via FKIK switching FKDriver = 'FKWrist_R' IKDriver = 'IKArm_R_IKFKOffsetBlend_grp' FKIKSwitch = 'FKIKArm_R' pCons = mc.parentConstraint(FKDriver, IKDriver, rollGrp, mo=True)[0] wal = mc.parentConstraint(pCons, q=True, wal=True) FKIKValue = cn.create_multDoubleLinear(FKIKSwitch+'.FKIKBlend', 0.1) #=========================================================================== # SET DRIVERS AND DRIVENS #=========================================================================== # drive blend in constraint rollGrp = rollGrp.split('|')[1] rev = mc.createNode('reverse', n=rollGrp+'_FKIKSwitch_rev') mc.connectAttr(FKIKValue, rev+'.inputX', f=True) mc.connectAttr(rev+'.outputX', pCons+'.'+wal[0], f=True) mc.connectAttr(FKIKValue, pCons+'.'+wal[1], f=True) # baseJnt to drive ikHandle & IKFKOffsetBlend IKHandle = 'IKXArmHandle_R' IKFKMix = 'FKIKMixWrist_R' mc.parentConstraint(baseJnt, IKHandle, mo=True) mc.delete(IKFKMix+'_parentConstraint1') mc.parentConstraint(baseJnt, IKFKMix, mo=True) #=========================================================================== # FIX LENGTH MEASUREMENT #=========================================================================== endLoc = 'IKmessureConstrainToArm_R' mc.parentConstraint(baseJnt, endLoc) # DO SAME FOR LEFT SIDE #=========================================================================== # ADD REVERSE ROLL #=========================================================================== bendPivot, leftPivot, rightPivot = ms.placePivotsForReverseRoll('Wrist_L', (-0.715, -0.011, 0.038), (0,0.194,-0.687), (0,0.194,0.631)) jnts = ['Wrist_L', ['FKOffsetPinkyFinger1_L', 'FKXPinkyFinger3_L'], ['FKOffsetMiddleFinger1_L', 'FKXMiddleFinger3_L'], ['FKOffsetIndexFinger1_L', 'FKXIndexFinger3_L'], ['FKOffsetThumbFinger1_L', 'FKXThumbFinger3_L'] ] rollGrp, baseJnt = ms.addReverseRoll(jnts, bendPivot, rightPivot, leftPivot) # drive rollGrp via FKIK switching FKDriver = 'FKWrist_L' IKDriver = 'IKArm_L_IKFKOffsetBlend_grp' FKIKSwitch = 'FKIKArm_L' pCons = mc.parentConstraint(FKDriver, IKDriver, rollGrp, mo=True)[0] wal = mc.parentConstraint(pCons, q=True, wal=True) FKIKValue = cn.create_multDoubleLinear(FKIKSwitch+'.FKIKBlend', 0.1) #=========================================================================== # SET DRIVERS AND DRIVENS #=========================================================================== # drive blend in constraint rollGrp = rollGrp.split('|')[1] rev = mc.createNode('reverse', n=rollGrp+'_FKIKSwitch_rev') mc.connectAttr(FKIKValue, rev+'.inputX', f=True) mc.connectAttr(rev+'.outputX', pCons+'.'+wal[0], f=True) mc.connectAttr(FKIKValue, pCons+'.'+wal[1], f=True) # baseJnt to drive ikHandle & IKFKOffsetBlend IKHandle = 'IKXArmHandle_L' IKFKMix = 'FKIKMixWrist_L' mc.parentConstraint(baseJnt, IKHandle, mo=True) mc.delete(IKFKMix+'_parentConstraint1') mc.parentConstraint(baseJnt, IKFKMix, mo=True) #=========================================================================== # FIX LENGTH MEASUREMENT #=========================================================================== endLoc = 'IKmessureConstrainToArm_L' mc.parentConstraint(baseJnt, endLoc)