def doBuild( self, bicep, elbow, wrist, clavicle=None, translateClavicle=True, stretchy=False, **kw ): getWristToWorldRotation( wrist, True ) colour = self.getParityColour() wireColor = 14 if self.getParity() == Parity.LEFT else 13 parentControl, rootControl = getParentAndRootControl( clavicle or bicep ) #build the base controls self.buildBase( ARM_NAMING_SCHEME ) #create variables for each control used ikHandle = self.ikHandle ikArmSpace, fkArmSpace = self.ikSpace, self.fkSpace fkControls = driverBicep, driverElbow, driverWrist = self.driverUpper, self.driverMid, self.driverLower elbowControl = self.poleControl #build the clavicle if clavicle: clavOffset = AX_Y.asVector() * getAutoOffsetAmount( clavicle, listRelatives( clavicle, pa=True ), AX_Y ) clavControl = buildControl( 'clavicleControl%s' % self.getParity().asName(), PlaceDesc( bicep, clavicle, clavicle ), shapeDesc=ShapeDesc( 'sphere' ), scale=self.scale*1.25, offset=clavOffset, offsetSpace=SPACE_WORLD, colour=colour ) clavControlOrient = getNodeParent( clavControl ) parent( clavControlOrient, parentControl ) parent( fkArmSpace, clavControl ) if not translateClavicle: attrState( clavControl, 't', *LOCK_HIDE ) else: clavControl = None parent( fkArmSpace, parentControl ) #build space switching allPurposeObj = self.buildAllPurposeLocator( 'arm' ) buildDefaultSpaceSwitching( bicep, elbowControl, **spaceSwitching.NO_ROTATION ) buildDefaultSpaceSwitching( bicep, self.control, [ allPurposeObj ], [ 'All Purpose' ], True ) buildDefaultSpaceSwitching( bicep, driverBicep, **spaceSwitching.NO_TRANSLATION ) #make the limb stretchy? if stretchy: StretchRig.Create( self.getSkeletonPart(), self.control, fkControls, '%s.ikBlend' % ikHandle, parity=self.getParity() ) controls = self.control, driverBicep, driverElbow, driverWrist, elbowControl, clavControl, allPurposeObj namedNodes = self.ikSpace, self.fkSpace, self.ikHandle, self.endOrient, self.lineNode return controls, namedNodes
def _build(self, skeletonPart, stretchy=True, **kw): scale = kw['scale'] parity = self.getParity() parityMult = parity.asMultiplier() nameMod = kw.get('nameMod', 'front') nameSuffix = '_%s%s' % (nameMod.capitalize(), parity.asName()) colour = self.getParityColour() originalJoints = originalThighJoint, originalKneeJoint, originalAnkleJoint, originalToeJoint = skeletonPart[: 4] getWristToWorldRotation(originalToeJoint, True) #create a duplicate chain for the ik leg - later we create another chain for fk and constrain the original joints between them for ik/fk switching ikJoints = ikThighJoint, ikKneeJoint, ikAnkleJoint, ikToeJoint = duplicateChain( originalThighJoint, originalToeJoint) ### IK CHAIN SETUP #determine the root partParent, rootControl = getParentAndRootControl(ikThighJoint) parent(ikThighJoint, partParent) setAttr('%s.v' % ikThighJoint, 0) ikHandle = cmd.ikHandle(fs=1, sj=ikThighJoint, ee=ikAnkleJoint, solver='ikRPsolver')[0] footCtrl = buildControl( 'Foot%s' % nameSuffix, #PlaceDesc( ikToeJoint, PlaceDesc.WORLD ), ikToeJoint, PivotModeDesc.MID, ShapeDesc('cube', axis=-AIM_AXIS if parity else AIM_AXIS), colour, scale=scale) footCtrlSpace = getNodeParent(footCtrl) setAttr('%s.rotateOrder' % footCtrl, 1) setAttr('%s.v' % ikHandle, 0) attrState(ikHandle, 'v', *LOCK_HIDE) #build the pivots for the foot roll/rock attributes placers = skeletonPart.getPlacers() if placers: footRock_fwd = buildNullControl('footRock_forward_null', placers[0], parent=footCtrl) footRock_back = buildNullControl('footRock_backward_null', placers[1], parent=footRock_fwd) footRoll_inner = buildNullControl('footRoll_inner_null', placers[2], parent=footRock_back) footRoll_outer = buildNullControl('footRoll_outer_null', placers[3], parent=footRoll_inner) else: footRock_fwd = buildNullControl('footRock_forward_null', ikToeJoint, parent=footCtrlSpace) footRock_back = buildNullControl('footRock_backward_null', ikToeJoint, parent=footCtrlSpace) footRoll_inner = buildNullControl('footRoll_inner_null', ikToeJoint, parent=footCtrlSpace) footRoll_outer = buildNullControl('footRoll_outer_null', ikToeJoint, parent=footCtrlSpace) toePos = xform(ikToeJoint, q=True, ws=True, rp=True) moveIncrement = scale / 2 move(0, -toePos[1], moveIncrement, footRock_fwd, r=True, ws=True) move(0, -toePos[1], -moveIncrement, footRock_back, r=True, ws=True) move(-moveIncrement * parityMult, -toePos[1], 0, footRoll_inner, r=True, ws=True) move(moveIncrement * parityMult, -toePos[1], 0, footRoll_outer, r=True, ws=True) cmd.parent(footRock_back, footRock_fwd) cmd.parent(footRoll_inner, footRock_back) cmd.parent(footRoll_outer, footRoll_inner) cmd.parent(footCtrl, footRoll_outer) makeIdentity(footCtrl, a=True, t=True) addAttr(footCtrl, ln='footRock', at='double', dv=0, min=-10, max=10) attrState(footCtrl, 'footRock', *NORMAL) setDrivenKeyframe('%s.rx' % footRock_fwd, cd='%s.footRock' % footCtrl, dv=0, v=0) setDrivenKeyframe('%s.rx' % footRock_fwd, cd='%s.footRock' % footCtrl, dv=10, v=90) setDrivenKeyframe('%s.rx' % footRock_back, cd='%s.footRock' % footCtrl, dv=0, v=0) setDrivenKeyframe('%s.rx' % footRock_back, cd='%s.footRock' % footCtrl, dv=-10, v=-90) addAttr(footCtrl, ln='bank', at='double', dv=0, min=-10, max=10) attrState(footCtrl, 'bank', *NORMAL) setDrivenKeyframe('%s.rz' % footRoll_inner, cd='%s.bank' % footCtrl, dv=0, v=0) setDrivenKeyframe('%s.rz' % footRoll_inner, cd='%s.bank' % footCtrl, dv=10, v=90) setDrivenKeyframe('%s.rz' % footRoll_outer, cd='%s.bank' % footCtrl, dv=0, v=0) setDrivenKeyframe('%s.rz' % footRoll_outer, cd='%s.bank' % footCtrl, dv=-10, v=-90) #setup the auto ankle grpA = buildControl('ankle_auto_null', PlaceDesc(ikToeJoint, ikAnkleJoint), shapeDesc=SHAPE_NULL, constrain=False, parent=footCtrl) grpB = buildAlignedNull(ikAnkleJoint, 'ankle_orientation_null', parent=grpA) orientConstraint(grpB, ikAnkleJoint) for ax in AXES: delete('%s.t%s' % (ikToeJoint, ax), icn=True) cmd.parent(ikHandle, grpA) cmd.parent(footCtrlSpace, self.getWorldControl()) grpASpace = getNodeParent(grpA) grpAAutoNull = buildAlignedNull(PlaceDesc(ikToeJoint, ikAnkleJoint), '%sauto_on_ankle_null%s' % (nameMod, nameSuffix), parent=footCtrl) grpAAutoOffNull = buildAlignedNull(PlaceDesc(ikToeJoint, ikAnkleJoint), '%sauto_off_ankle_null%s' % (nameMod, nameSuffix), parent=footCtrl) grpA_knee_aimVector = betweenVector(grpAAutoNull, ikKneeJoint) grpA_knee_aimAxis = getObjectAxisInDirection(grpAAutoNull, grpA_knee_aimVector) grpA_knee_upAxis = getObjectAxisInDirection(grpAAutoNull, (1, 0, 0)) grpA_knee_worldAxis = getObjectAxisInDirection(footCtrl, (1, 0, 0)) aimConstraint(ikThighJoint, grpAAutoNull, mo=True, aim=grpA_knee_aimAxis.asVector(), u=grpA_knee_upAxis.asVector(), wu=grpA_knee_worldAxis.asVector(), wuo=footCtrl, wut='objectrotation') autoAimConstraint = orientConstraint(grpAAutoNull, grpAAutoOffNull, grpASpace)[0] addAttr(footCtrl, ln='autoAnkle', at='double', dv=1, min=0, max=1) attrState(footCtrl, 'autoAnkle', *NORMAL) cAttrs = listAttr(autoAimConstraint, ud=True) connectAttr('%s.autoAnkle' % footCtrl, '%s.%s' % (autoAimConstraint, cAttrs[0]), f=True) connectAttrReverse('%s.autoAnkle' % footCtrl, '%s.%s' % (autoAimConstraint, cAttrs[1]), f=True) poleCtrl = buildControl('Pole%s' % nameSuffix, PlaceDesc(ikKneeJoint, PlaceDesc.WORLD), PivotModeDesc.MID, shapeDesc=ShapeDesc( 'sphere', axis=-AIM_AXIS if parity else AIM_AXIS), colour=colour, constrain=False, scale=scale, parent=self.getPartsNode()) poleCtrlSpace = getNodeParent(poleCtrl) polePos = findPolePosition(ikAnkleJoint) move(polePos[0], polePos[1], polePos[2], poleCtrlSpace, ws=True, rpr=True, a=True) pointConstraint(ikThighJoint, footCtrl, poleCtrlSpace, mo=True) poleVectorConstraint(poleCtrl, ikHandle) #build the ankle aim control - its acts kinda like a secondary pole vector anklePoleControl = buildControl('Ankle%s' % nameSuffix, ikAnkleJoint, shapeDesc=ShapeDesc('sphere'), colour=colour, scale=scale, constrain=False, parent=grpASpace) ankleAimVector = betweenVector(grpA, anklePoleControl) ankleAimAxis = getObjectAxisInDirection(grpA, ankleAimVector) ankleUpAxis = getObjectAxisInDirection(grpA, (1, 0, 0)) ankleWorldUpAxis = getObjectAxisInDirection(anklePoleControl, (1, 0, 0)) aimConstraint(anklePoleControl, grpA, aim=ankleAimAxis.asVector(), u=ankleUpAxis.asVector(), wu=ankleWorldUpAxis.asVector(), wuo=anklePoleControl, wut='objectrotation') ### FK CHAIN SETUP fkThighControl = buildControl('fkThigh%s' % nameSuffix, originalThighJoint, PivotModeDesc.MID, 'sphere', colour, False, scale=scale, parent=partParent) fkKneeControl = buildControl('fkKnee%s' % nameSuffix, originalKneeJoint, PivotModeDesc.MID, 'sphere', colour, False, scale=scale, parent=fkThighControl) fkAnkleControl = buildControl('fkAnkle%s' % nameSuffix, originalAnkleJoint, PivotModeDesc.MID, 'sphere', colour, False, scale=scale, parent=fkKneeControl) fkToeControl = buildControl('fkToe%s' % nameSuffix, originalToeJoint, PivotModeDesc.MID, 'sphere', colour, False, scale=scale, parent=fkAnkleControl) fkControls = fkThighControl, fkKneeControl, fkAnkleControl, fkToeControl setItemRigControl(originalThighJoint, fkThighControl) setItemRigControl(originalKneeJoint, fkKneeControl) setItemRigControl(originalAnkleJoint, fkAnkleControl) addAttr(footCtrl, ln='ikBlend', at='float', min=0, max=1, dv=1, keyable=True) for ikJ, fkC, orgJ in zip(ikJoints, fkControls, originalJoints): constraintNode = parentConstraint(ikJ, orgJ, w=1, mo=True)[0] constraintNode = parentConstraint(fkC, orgJ, w=0, mo=True)[0] ikAttr, fkAttr = listAttr(constraintNode, ud=True) connectAttr('%s.ikBlend' % footCtrl, '%s.%s' % (constraintNode, ikAttr)) connectAttrReverse('%s.ikBlend' % footCtrl, '%s.%s' % (constraintNode, fkAttr)) ikControls = footCtrl, poleCtrl, anklePoleControl setupIkFkVisibilityConditions('%s.ikBlend' % footCtrl, ikControls, fkControls) #now we need to setup right mouse button menus for ik/fk switching footTrigger = Trigger(footCtrl) footTrigger.createMenu( 'switch to FK', '''python( "import rigPrimitives; rigPrimitives.RigPart.InitFromItem('#').switchToFk()" )''' ) for c in fkControls: t = Trigger(c) t.createMenu( 'switch to IK', '''python( "import rigPrimitives; rigPrimitives.RigPart.InitFromItem('#').switchToIk()" )''' ) #setup stretch as appropriate if stretchy: StretchRig.Create( self._skeletonPart, footCtrl, (ikThighJoint, ikKneeJoint, ikAnkleJoint, ikToeJoint), '%s.ikBlend' % ikHandle, parity=parity, connectEndJoint=True) for ax in CHANNELS: delete('%s.t%s' % (ikToeJoint, ax), icn=True) pointConstraint(footCtrl, ikToeJoint) buildDefaultSpaceSwitching(originalThighJoint, footCtrl, reverseHierarchy=True, space=footCtrlSpace) buildDefaultSpaceSwitching(originalThighJoint, fkThighControl) buildDefaultSpaceSwitching(originalToeJoint, fkToeControl, **spaceSwitching.NO_ROTATION) controls = ikControls + fkControls namedNodes = None, None, ikHandle, None return controls, namedNodes
def doBuild(self, thigh, knee, ankle, stretchy=True, **kw): partParent, rootControl = getParentAndRootControl(thigh) #first rotate the foot so its aligned to a world axis footCtrlRot = Vector(getAnkleToWorldRotation(str(ankle), 'z', True)) footCtrlRot = (0, -footCtrlRot.y, 0) #build the base controls self.buildBase(LEG_NAMING_SCHEME) #if the legs are parented to a root part - which is usually the case but not always - grab the hips and parent the fk control space to the hips hipsControl = partParent partParentRigPart = RigPart.InitFromItem(partParent) if isinstance(partParentRigPart.getSkeletonPart(), Root): hipsControl = partParentRigPart.getControl('hips') #if the part parent in a Root primitive, grab the hips control instead of the root gimbal - for the leg parts this is preferable parentRigPart = RigPart.InitFromItem(partParent) if isinstance(parentRigPart, Root): partParent = parentRigPart.getControl('hips') #create variables for each control used legControl = self.control legControlSpace = getNodeParent(legControl) ikLegSpace, fkLegSpace = self.ikSpace, self.fkSpace driverThigh, driverKnee, driverAnkle = self.driverUpper, self.driverMid, self.driverLower fkControls = driverThigh, driverKnee, driverAnkle kneeControl = self.poleControl kneeControlSpace = getNodeParent(kneeControl) parent(kneeControlSpace, partParent) toe = listRelatives(ankle, type='joint', pa=True) or None toeTip = None if toe: toe = toe[0] #if the toe doesn't exist, build a temp one if not toe: toe = group(em=True) parent(toe, ankle, r=True) move(0, -self.scale, self.scale, toe, r=True, ws=True) toeTip = self.getSkeletonPart().endPlacer if not toeTip: possibleTips = listRelatives(toe, type='joint', pa=True) if possibleTips: toeTip = possibleTips[0] #build the objects to control the foot suffix = self.getSuffix() footControlSpace = buildNullControl("foot_controlSpace" + suffix, ankle, parent=legControl) heelRoll = buildNullControl("heel_roll_piv" + suffix, ankle, offset=(0, 0, -self.scale), parent=footControlSpace) select( heelRoll ) #move command doesn't support object naming when specifying a single axis move, so we must selec the object first move(0, 0, 0, rpr=True, y=True) if toeTip: toeRoll = buildNullControl("leg_toe_roll_piv" + suffix, toeTip, parent=heelRoll) else: toeRoll = buildNullControl("leg_toe_roll_piv" + suffix, toe, parent=heelRoll, offset=(0, 0, self.scale)) footBankL = buildNullControl("bank_in_piv" + suffix, toe, parent=toeRoll) footBankR = buildNullControl("bank_out_piv" + suffix, toe, parent=footBankL) footRollControl = buildNullControl("roll_piv" + suffix, toe, parent=footBankR) #move bank pivots to a good spot on the ground placers = self.getSkeletonPart().getPlacers() numPlacers = len(placers) if placers: toePos = Vector(xform(toe, q=True, ws=True, rp=True)) if numPlacers >= 2: innerPlacer = Vector( xform(placers[1], q=True, ws=True, rp=True)) move(innerPlacer[0], innerPlacer[1], innerPlacer[2], footBankL, a=True, ws=True, rpr=True) if numPlacers >= 3: outerPlacer = Vector( xform(placers[2], q=True, ws=True, rp=True)) move(outerPlacer[0], outerPlacer[1], outerPlacer[2], footBankR, a=True, ws=True, rpr=True) if numPlacers >= 4: heelPlacer = Vector(xform(placers[3], q=True, ws=True, rp=True)) move(heelPlacer[0], heelPlacer[1], heelPlacer[2], heelRoll, a=True, ws=True, rpr=True) #move the knee control so its inline with the leg rotate(footCtrlRot[0], footCtrlRot[1], footCtrlRot[2], kneeControlSpace, p=xform(thigh, q=True, ws=True, rp=True), a=True, ws=True) makeIdentity(kneeControl, apply=True, t=True) #add attributes to the leg control, to control the pivots addAttr(legControl, ln='rollBall', at='double', min=0, max=10, k=True) addAttr(legControl, ln='rollToe', at='double', min=-10, max=10, k=True) addAttr(legControl, ln='twistFoot', at='double', min=-10, max=10, k=True) addAttr(legControl, ln='bank', at='double', min=-10, max=10, k=True) #replace the legControl as a target to the parent constraint on the endOrient transform so the ikHandle respects the foot slider controls footFinalPivot = buildNullControl("final_piv" + suffix, ankle, parent=footRollControl) delete(parentConstraint(footFinalPivot, self.ikHandle, mo=True)) parent(self.ikHandle, footFinalPivot) replaceGivenConstraintTarget(self.endOrientSpaceConstraint, legControl, footFinalPivot) #build the SDK's to control the pivots setDrivenKeyframe('%s.rx' % footRollControl, cd='%s.rollBall' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rx' % footRollControl, cd='%s.rollBall' % legControl, dv=10, v=90) setDrivenKeyframe('%s.rx' % footRollControl, cd='%s.rollBall' % legControl, dv=-10, v=-90) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=10, v=90) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=-10, v=-90) setDrivenKeyframe('%s.ry' % toeRoll, cd='%s.twistFoot' % legControl, dv=-10, v=-90) setDrivenKeyframe('%s.ry' % toeRoll, cd='%s.twistFoot' % legControl, dv=10, v=90) min = -90 if self.getParity() == Parity.LEFT else 90 max = 90 if self.getParity() == Parity.LEFT else -90 setDrivenKeyframe('%s.rz' % footBankL, cd='%s.bank' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rz' % footBankL, cd='%s.bank' % legControl, dv=10, v=max) setDrivenKeyframe('%s.rz' % footBankR, cd='%s.bank' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rz' % footBankR, cd='%s.bank' % legControl, dv=-10, v=min) #setup the toe if we have one if toe: toeSDK = buildControl("toeSDK%s" % suffix, toe, shapeDesc=SHAPE_NULL, parent=footBankR, scale=self.scale, colour=self.getParityColour()) toeConstraint = parentConstraint(driverAnkle, toe, w=0, mo=True)[0] toeConstraintAttrs = listAttr(toeConstraint, ud=True) expression(s='%s.%s = %s.ikBlend;\n%s.%s = 1 - %s.ikBlend;' % (toeConstraint, toeConstraintAttrs[0], self.control, toeConstraint, toeConstraintAttrs[1], self.control), n='toe_parentingConstraintSwitch') addAttr(legControl, ln='toe', at='double', min=-10, max=10, k=True) setDrivenKeyframe('%s.r%s' % (toeSDK, ROT_AXIS.asCleanName()), cd='%s.toe' % legControl, dv=-10, v=90) setDrivenKeyframe('%s.r%s' % (toeSDK, ROT_AXIS.asCleanName()), cd='%s.toe' % legControl, dv=10, v=-90) #build space switching parent(fkLegSpace, hipsControl) allPurposeObj = self.buildAllPurposeLocator('leg') spaceSwitching.build( legControl, (self.getWorldControl(), hipsControl, rootControl, allPurposeObj), ('World', None, 'Root', 'All Purpose'), space=legControlSpace) spaceSwitching.build( kneeControl, (legControl, partParent, rootControl, self.getWorldControl()), ("Leg", None, "Root", "World"), **spaceSwitching.NO_ROTATION) spaceSwitching.build( driverThigh, (hipsControl, rootControl, self.getWorldControl()), (None, 'Root', 'World'), **spaceSwitching.NO_TRANSLATION) spaceSwitching.build( kneeControl, (self.getWorldControl(), hipsControl, rootControl), ('World', None, 'Root'), **spaceSwitching.NO_ROTATION) #make the limb stretchy if stretchy: StretchRig.Create(self.getSkeletonPart(), legControl, fkControls, '%s.ikBlend' % self.ikHandle, parity=self.getParity()) if objExists('%s.elbowPos' % legControl): renameAttr('%s.elbowPos' % legControl, 'kneePos') controls = legControl, driverThigh, driverKnee, driverAnkle, kneeControl, allPurposeObj namedNodes = self.ikSpace, self.fkSpace, self.ikHandle, self.endOrient, self.lineNode return controls, namedNodes
def doBuild(self, bicep, elbow, wrist, clavicle=None, translateClavicle=True, stretchy=False, **kw): scale = kw['scale'] idx = kw['idx'] parity = Parity(idx) getWristToWorldRotation(wrist, True) colour = ColourDesc('green') if parity == Parity.LEFT else ColourDesc( 'red') worldPart = WorldPart.Create() worldControl = worldPart.control partsControl = worldPart.parts parentControl, rootControl = getParentAndRootControl(clavicle or bicep) ikFkPart = IkFkBase.Create(self.getSkeletonPart(), **kw) #create variables for each control used armControl = asMObject(ikFkPart.control) ikHandle = asMObject(ikFkPart.ikHandle) ikArmSpace = asMObject(ikFkPart.ikSpace) fkArmSpace = asMObject(ikFkPart.fkSpace) driverBicep = asMObject(ikFkPart.fkUpper) driverElbow = asMObject(ikFkPart.fkMid) driverWrist = asMObject(ikFkPart.fkLower) elbowControl = asMObject(ikFkPart.poleControl) fkControls = driverBicep, driverElbow, driverWrist #build the clavicle if clavicle: clavOffset = AX_Y.asVector() * getAutoOffsetAmount( clavicle, listRelatives(clavicle, pa=True), AX_Y) clavControl = buildControl('clavicleControl%s' % parity.asName(), PlaceDesc(bicep, clavicle, clavicle), shapeDesc=ShapeDesc('sphere'), scale=scale * 1.25, offset=clavOffset, offsetSpace=SPACE_WORLD, colour=colour) clavControlOrient = getNodeParent(clavControl) parent(clavControlOrient, parentControl) parent(fkArmSpace, clavControl) if not translateClavicle: attrState(clavControl, 't', *LOCK_HIDE) else: clavControl = None parent(fkArmSpace, parentControl) #build space switching allPurposeObj = spaceLocator()[0] allPurposeObj = rename(allPurposeObj, "arm_all_purpose_loc%s" % parity.asName()) attrState(allPurposeObj, 's', *LOCK_HIDE) attrState(allPurposeObj, 'v', *HIDE) parent(allPurposeObj, worldControl) buildDefaultSpaceSwitching(bicep, armControl, [allPurposeObj], ['All Purpose'], True) buildDefaultSpaceSwitching(bicep, driverBicep, **spaceSwitching.NO_TRANSLATION) #make the limb stretchy? if stretchy: StretchRig.Create(self._skeletonPart, armControl, fkControls, '%s.ikBlend' % ikHandle, parity=parity) return armControl, driverBicep, driverElbow, driverWrist, elbowControl, clavControl, allPurposeObj, ikFkPart.poleTrigger
def doBuild(self, thigh, knee, ankle, stretchy=True, **kw): scale = kw['scale'] idx = kw['idx'] parity = Parity(idx) parityMult = parity.asMultiplier() suffix = parity.asName() colour = ColourDesc('green') if parity == Parity.LEFT else ColourDesc( 'red') worldPart = WorldPart.Create() worldControl = worldPart.control partsControl = worldPart.parts #first rotate the foot so its aligned to a world axis footCtrlRot = Vector(getAnkleToWorldRotation(str(ankle), 'z', True)) footCtrlRot = (0, -footCtrlRot.y, 0) ### BUILD THE IKFK BASE ikFkPart = IkFkBase.Create(self.getSkeletonPart(), nameScheme=LEG_NAMING_SCHEME, alignEnd=False, addControlsToQss=False, **kw) partParent, rootControl = getParentAndRootControl(thigh) #if the legs are parented to a root part - which is usually the case but not always - grab the hips and parent the fk control space to the hips hipsControl = partParent partParentRigPart = RigPart.InitFromItem(partParent) if isinstance(partParentRigPart.getSkeletonPart(), Root): hipsControl = partParentRigPart.hips #if the part parent in a Root primitive, grab the hips control instead of the root gimbal - for the leg parts this is preferable parentRigPart = RigPart.InitFromItem(partParent) if isinstance(parentRigPart, Root): partParent = parentRigPart.hips #create variables for each control used legControl = ikFkPart.control legControlSpace = getNodeParent(legControl) ikLegSpace = ikFkPart.ikSpace fkLegSpace = ikFkPart.fkSpace driverThigh = ikFkPart.fkUpper driverKnee = ikFkPart.fkMid driverAnkle = ikFkPart.fkLower ikHandle = ikFkPart.ikHandle kneeControl = ikFkPart.poleControl kneeControlSpace = getNodeParent(kneeControl) toe = listRelatives(ankle, type='joint', pa=True) or None toeTip = None if toe: toe = toe[0] fkControls = driverThigh, driverKnee, driverAnkle #if the toe doesn't exist, build a temp one if not toe: toe = group(em=True) parent(toe, ankle, r=True) move(0, -scale, scale, toe, r=True, ws=True) toeTip = self.getSkeletonPart().endPlacer if not toeTip: possibleTips = listRelatives(toe, type='joint', pa=True) if possibleTips: toeTip = possibleTips[0] #build the objects to control the foot footControlSpace = buildNullControl("foot_controlSpace" + suffix, ankle, parent=legControl) heelRoll = buildNullControl("heel_roll_piv" + suffix, ankle, offset=(0, 0, -scale)) footBankL = buildNullControl("bank_in_piv" + suffix, toe) footBankR = buildNullControl("bank_out_piv" + suffix, toe) footRollControl = buildNullControl("roll_piv" + suffix, toe) toeOrient = buildNullControl("toe_orient_piv" + suffix, toe) if toeTip: toeRoll = buildNullControl("leg_toe_roll_piv" + suffix, toeTip) else: toeRoll = buildNullControl("leg_toe_roll_piv" + suffix, toe, offset=(0, 0, scale)) select( heelRoll ) #stupid move command doesn't support object naming when specifying a single axis move, so we must selec the object first move(0, 0, 0, rpr=True, y=True) #move bank pivots to a good spot on the ground placers = self.getSkeletonPart().getPlacers() numPlacers = len(placers) if placers: toePos = Vector(xform(toe, q=True, ws=True, rp=True)) if numPlacers >= 2: innerPlacer = Vector( xform(placers[1], q=True, ws=True, rp=True)) move(innerPlacer[0], innerPlacer[1], innerPlacer[2], footBankL, a=True, ws=True, rpr=True) if numPlacers >= 3: outerPlacer = Vector( xform(placers[2], q=True, ws=True, rp=True)) move(outerPlacer[0], outerPlacer[1], outerPlacer[2], footBankR, a=True, ws=True, rpr=True) if numPlacers >= 4: heelPlacer = Vector(xform(placers[3], q=True, ws=True, rp=True)) move(heelPlacer[0], heelPlacer[1], heelPlacer[2], heelRoll, a=True, ws=True, rpr=True) #parent the leg pivots together parent(kneeControlSpace, partParent) parent(heelRoll, footControlSpace) parent(toeRoll, heelRoll) parent(footBankL, toeRoll) parent(footBankR, footBankL) parent(footRollControl, footBankR) parent(toeOrient, footBankR) if toe: orientConstraint(toeOrient, toe, mo=True) makeIdentity(heelRoll, apply=True, t=True, r=True) #move the knee control so its inline with the leg rotate(footCtrlRot[0], footCtrlRot[1], footCtrlRot[2], kneeControlSpace, p=xform(thigh, q=True, ws=True, rp=True), a=True, ws=True) makeIdentity(kneeControl, apply=True, t=True) #add attributes to the leg control, to control the pivots addAttr(legControl, ln='rollBall', at='double', min=0, max=10, k=True) addAttr(legControl, ln='rollToe', at='double', min=-10, max=10, k=True) addAttr(legControl, ln='twistFoot', at='double', min=-10, max=10, k=True) addAttr(legControl, ln='toe', at='double', min=-10, max=10, k=True) addAttr(legControl, ln='bank', at='double', min=-10, max=10, k=True) #replace the legControl as a target to teh parent constraint on the endOrient transform so the ikHandle respects the foot slider controls footFinalPivot = buildNullControl("final_piv" + suffix, ankle, parent=footRollControl) endOrientConstraint = listConnections('%s.tx' % ikFkPart.endOrient, type='constraint', d=False)[0] #replaceConstraintTarget( endOrientConstraint, footFinalPivot ) for attr in attributeQuery('target', node=endOrientConstraint, listChildren=True): for con in listConnections('%s.target[ 0 ].%s' % (endOrientConstraint, attr), p=True, type='transform', d=False) or []: node = con.split('.')[0] if cmpNodes(node, legControl): toks = str(con).split('.') toks[0] = str(footFinalPivot) connectAttr('.'.join(toks), '%s.target[0].%s' % (endOrientConstraint, attr), f=True) delete(parentConstraint(footFinalPivot, ikHandle, mo=True)) parent(ikHandle, footFinalPivot) #build the SDK's to control the pivots setDrivenKeyframe('%s.rx' % footRollControl, cd='%s.rollBall' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rx' % footRollControl, cd='%s.rollBall' % legControl, dv=10, v=90) setDrivenKeyframe('%s.rx' % footRollControl, cd='%s.rollBall' % legControl, dv=-10, v=-90) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=10, v=90) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rx' % toeRoll, cd='%s.rollToe' % legControl, dv=-10, v=-90) setDrivenKeyframe('%s.ry' % toeRoll, cd='%s.twistFoot' % legControl, dv=-10, v=-90) setDrivenKeyframe('%s.ry' % toeRoll, cd='%s.twistFoot' % legControl, dv=10, v=90) setDrivenKeyframe('%s.rx' % toeOrient, cd='%s.toe' % legControl, dv=-10, v=90) setDrivenKeyframe('%s.rx' % toeOrient, cd='%s.toe' % legControl, dv=10, v=-90) min = -90 if parity == Parity.LEFT else 90 max = 90 if parity == Parity.LEFT else -90 setDrivenKeyframe('%s.rz' % footBankL, cd='%s.bank' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rz' % footBankL, cd='%s.bank' % legControl, dv=10, v=max) setDrivenKeyframe('%s.rz' % footBankR, cd='%s.bank' % legControl, dv=0, v=0) setDrivenKeyframe('%s.rz' % footBankR, cd='%s.bank' % legControl, dv=-10, v=min) #build all purpose allPurposeObj = spaceLocator(name="leg_all_purpose_loc%s" % suffix)[0] attrState(allPurposeObj, 's', *LOCK_HIDE) attrState(allPurposeObj, 'v', *HIDE) parent(allPurposeObj, worldControl) #build space switching parent(fkLegSpace, hipsControl) spaceSwitching.build( legControl, (worldControl, hipsControl, rootControl, allPurposeObj), ('World', None, 'Root', 'All Purpose'), space=legControlSpace) spaceSwitching.build( kneeControl, (legControl, partParent, rootControl, worldControl), ("Leg", None, "Root", "World"), **spaceSwitching.NO_ROTATION) spaceSwitching.build(driverThigh, (hipsControl, rootControl, worldControl), (None, 'Root', 'World'), **spaceSwitching.NO_TRANSLATION) #make the limb stretchy if stretchy: StretchRig.Create(self._skeletonPart, legControl, fkControls, '%s.ikBlend' % ikHandle, parity=parity) if objExists('%s.elbowPos' % legControl): renameAttr('%s.elbowPos' % legControl, 'kneePos') return legControl, driverThigh, driverKnee, driverAnkle, kneeControl, allPurposeObj, ikFkPart.poleTrigger
def _build( self, skeletonPart, stretchy=True, **kw ): thigh, knee, ankle, toe = skeletonPart[:4] idx = kw[ 'idx' ] scale = kw[ 'scale' ] parity = Parity( idx ) parityMult = parity.asMultiplier() nameMod = kw.get( 'nameMod', 'front' ) worldPart = WorldPart.Create() worldControl, partsControl = worldPart.control, worldPart.parts nameSuffix = '_%s%s' % (nameMod.capitalize(), parity.asName()) colour = ColourDesc( 'red 0.7' ) if parity else ColourDesc( 'green 0.7' ) #first rotate the foot so its aligned to a world axis footCtrlRot = getAnkleToWorldRotation( toe, 'z', False ) rotate( 0, footCtrlRot[1], 0, toe, ws=True, r=True ) #determine the root partParent, rootControl = getParentAndRootControl( thigh ) ikHandle = cmd.ikHandle( fs=1, sj=thigh, ee=ankle, solver='ikRPsolver' )[ 0 ] footCtrl = buildControl( 'Foot%s' % nameSuffix, PlaceDesc( toe, PlaceDesc.WORLD ), PivotModeDesc.MID, ShapeDesc( 'sphere', axis=-AIM_AXIS if parity else AIM_AXIS ), colour, scale=scale ) footCtrlSpace = getNodeParent( footCtrl ) setAttr( '%s.rotateOrder' % footCtrl, 1 ) setAttr( '%s.v' % ikHandle, 0 ) attrState( ikHandle, 'v', *LOCK_HIDE ) #build the pivots for the foot roll/rock attributes placers = skeletonPart.getPlacers() if placers: footRock_fwd = buildNullControl( 'footRock_forward_null', placers[0], parent=footCtrl ) footRock_back = buildNullControl( 'footRock_backward_null', placers[1], parent=footRock_fwd ) footRoll_inner = buildNullControl( 'footRoll_inner_null', placers[2], parent=footRock_back ) footRoll_outer = buildNullControl( 'footRoll_outer_null', placers[3], parent=footRoll_inner ) else: footRock_fwd = buildNullControl( 'footRock_forward_null', toe, parent=footCtrlSpace ) footRock_back = buildNullControl( 'footRock_backward_null', toe, parent=footCtrlSpace ) footRoll_inner = buildNullControl( 'footRoll_inner_null', toe, parent=footCtrlSpace ) footRoll_outer = buildNullControl( 'footRoll_outer_null', toe, parent=footCtrlSpace ) toePos = xform( toe, q=True, ws=True, rp=True ) moveIncrement = scale / 2 move( 0, -toePos[1], moveIncrement, footRock_fwd, r=True, ws=True ) move( 0, -toePos[1], -moveIncrement, footRock_back, r=True, ws=True ) move( -moveIncrement * parityMult, -toePos[1], 0, footRoll_inner, r=True, ws=True ) move( moveIncrement * parityMult, -toePos[1], 0, footRoll_outer, r=True, ws=True ) cmd.parent( footRock_back, footRock_fwd ) cmd.parent( footRoll_inner, footRock_back ) cmd.parent( footRoll_outer, footRoll_inner ) cmd.parent( footCtrl, footRoll_outer ) makeIdentity( footCtrl, a=True, t=True ) addAttr( footCtrl, ln='footRock', at='double', dv=0, min=-10, max=10 ) attrState( footCtrl, 'footRock', *NORMAL ) setDrivenKeyframe( '%s.rx' % footRock_fwd, cd='%s.footRock' % footCtrl, dv=0, v=0 ) setDrivenKeyframe( '%s.rx' % footRock_fwd, cd='%s.footRock' % footCtrl, dv=10, v=90 ) setDrivenKeyframe( '%s.rx' % footRock_back, cd='%s.footRock' % footCtrl, dv=0, v=0 ) setDrivenKeyframe( '%s.rx' % footRock_back, cd='%s.footRock' % footCtrl, dv=-10, v=-90 ) addAttr( footCtrl, ln='bank', at='double', dv=0, min=-10, max=10 ) attrState( footCtrl, 'bank', *NORMAL ) setDrivenKeyframe( '%s.rz' % footRoll_inner, cd='%s.bank' % footCtrl, dv=0, v=0 ) setDrivenKeyframe( '%s.rz' % footRoll_inner, cd='%s.bank' % footCtrl, dv=10, v=90 ) setDrivenKeyframe( '%s.rz' % footRoll_outer, cd='%s.bank' % footCtrl, dv=0, v=0 ) setDrivenKeyframe( '%s.rz' % footRoll_outer, cd='%s.bank' % footCtrl, dv=-10, v=-90 ) #setup the auto ankle grpA = buildControl( 'ankle_auto_null', PlaceDesc( toe, ankle ), shapeDesc=SHAPE_NULL, constrain=False, parent=footCtrl ) grpB = buildAlignedNull( ankle, 'ankle_orientation_null', parent=grpA ) orientConstraint( grpB, ankle ) for ax in AXES: delete( '%s.t%s' % (toe, ax), icn=True ) cmd.parent( ikHandle, grpA ) cmd.parent( footCtrlSpace, worldControl ) grpASpace = getNodeParent( grpA ) grpAAutoNull = buildAlignedNull( PlaceDesc( toe, ankle ), '%sauto_on_ankle_null%s' % (nameMod, nameSuffix), parent=footCtrl ) grpAAutoOffNull = buildAlignedNull( PlaceDesc( toe, ankle ), '%sauto_off_ankle_null%s' % (nameMod, nameSuffix), parent=footCtrl ) grpA_knee_aimVector = betweenVector( grpAAutoNull, knee ) grpA_knee_aimAxis = getObjectAxisInDirection( grpAAutoNull, grpA_knee_aimVector ) grpA_knee_upAxis = getObjectAxisInDirection( grpAAutoNull, (0, 0, 1) ) grpA_knee_worldAxis = getObjectAxisInDirection( footCtrl, (0, 0, 1) ) aimConstraint( thigh, grpAAutoNull, mo=True, aim=grpA_knee_aimAxis.asVector(), u=grpA_knee_upAxis.asVector(), wu=grpA_knee_worldAxis.asVector(), wuo=footCtrl, wut='objectrotation' ) autoAimConstraint = orientConstraint( grpAAutoNull, grpAAutoOffNull, grpASpace )[0] addAttr( footCtrl, ln='autoAnkle', at='double', dv=1, min=0, max=1 ) attrState( footCtrl, 'autoAnkle', *NORMAL ) connectAttr( '%s.autoAnkle' % footCtrl, '%s.target[0].targetWeight' % autoAimConstraint, f=True ) connectAttrReverse( '%s.autoAnkle' % footCtrl, '%s.target[1].targetWeight' % autoAimConstraint, f=True ) poleCtrl = buildControl( 'Pole%s' % nameSuffix, PlaceDesc( knee, PlaceDesc.WORLD ), PivotModeDesc.MID, shapeDesc=ShapeDesc( 'sphere', axis=-AIM_AXIS if parity else AIM_AXIS ), colour=colour, constrain=False, scale=scale, parent=partsControl ) poleCtrlSpace = getNodeParent( poleCtrl ) polePos = findPolePosition( ankle ) move( polePos[0], polePos[1], polePos[2], poleCtrlSpace, ws=True, rpr=True, a=True ) pointConstraint( thigh, footCtrl, poleCtrlSpace, mo=True ) poleVectorConstraint( poleCtrl, ikHandle ) #build the ankle roll addAttr( footCtrl, ln='ankleRoll', at='double', dv=0, min=-10, max=10 ) attrState( footCtrl, 'ankleRoll', *NORMAL ) rollAxis = getObjectAxisInDirection( grpA, (1, 0, 0) ) rollAttrpath = '%s.r%s' % (grpA, rollAxis.asCleanName()) driverAttrpath = '%s.ankleRoll' % footCtrl setDrivenKeyframe( rollAttrpath, currentDriver=driverAttrpath, v=0, dv=0 ) setDrivenKeyframe( rollAttrpath, currentDriver=driverAttrpath, v=85, dv=10 ) setDrivenKeyframe( rollAttrpath, currentDriver=driverAttrpath, v=-85, dv=-10 ) #build the ankle "wag" addAttr( footCtrl, ln='ankleWag', at='double', dv=0, min=-10, max=10 ) attrState( footCtrl, 'ankleWag', *NORMAL ) rollAxis = getObjectAxisInDirection( grpA, (0, 0, 1) ) rollAttrpath = '%s.r%s' % (grpA, rollAxis.asCleanName()) driverAttrpath = '%s.ankleWag' % footCtrl setDrivenKeyframe( rollAttrpath, currentDriver=driverAttrpath, v=0, dv=0 ) setDrivenKeyframe( rollAttrpath, currentDriver=driverAttrpath, v=85, dv=10 ) setDrivenKeyframe( rollAttrpath, currentDriver=driverAttrpath, v=-85, dv=-10 ) if stretchy: StretchRig.Create( self._skeletonPart, footCtrl, (thigh, knee, ankle, toe), '%s.ikBlend' % ikHandle, parity=parity, connectEndJoint=True ) for ax in CHANNELS: delete( '%s.t%s' % (toe, ax), icn=True ) pointConstraint( footCtrl, toe ) return [ footCtrl, poleCtrl ]