def cleanUp(self): # joint Grp jointGrp = core.MovableSystem(side=self.side, part=self.part, endSuffix="JointGrp") jointGrp.setParent(self) self.jointGrp = jointGrp # Reparent the Joint self.reparentIkJoint(jointGrp) # Reparent the two curve and ik Handle for crv in [self.ikCurve, self.controlCurve, self.ikHandle.prnt]: if crv: crv.setParent(self.infoGrp) crv.setParent(self.infoGrp) # Create the control grp mainCtrls = self.mainCtrls if mainCtrls: ctrlGrp = core.MovableSystem(side=self.side, part=self.part, endSuffix="MainCtrlGrp") ctrlGrp.rotateOrder = self.rotateOrder ctrlGrp.snap(mainCtrls[0]) ctrlGrp.setParent(self) for ctrl in mainCtrls: ctrl.setParent(ctrlGrp) self.ctrlGrp = ctrlGrp
def build(self): # Create the annotation pm.select(clear=True) locPosition = libUtilities.get_world_space_pos(self.pynode) pm.select(self.mNode) fakeJoint = pm.annotate(self.mNode, point=locPosition).getParent() fakeJoint.setParent(self.pynode) fakeJoint.v.set(False) fakeJointMeta = core.MovableSystem(fakeJoint.name()) fakeJointMeta.template = True self.transferPropertiesToChild(fakeJointMeta, "FakeJoint") fakeJointMeta.part = self.part fakeJointMeta.resetName() self.fakeJoint = fakeJointMeta # Build the label annotation annotation = pm.annotate(self.mNode, point=locPosition, tx=self.trueName).getParent() annotation.displayArrow.set(False) annotationMeta = core.MovableSystem(annotation.name()) annotationMeta.template = True self.transferPropertiesToChild(annotationMeta, "Anno") annotationMeta.part = self.part annotationMeta.resetName() annotationMeta.setParent(self) self.annotation = annotationMeta
def buildControl(self): super(Hip, self).buildControl() # First joint alias aimJoint = self.jointSystem.joints[0] self.positionHipControl(aimJoint) upVector = self.buildHipSpaceSwitch(aimJoint) if self.hipIkSolver != "Single": self.buildAutoCompress() # Create main grp mainGrp = core.MovableSystem(part="{}Main".format(self.part), side=self.side) hipGrp = core.MovableSystem(part="{}Hip".format(self.part), side=self.side) # Reparent self.addSupportNode(mainGrp, "MainGrp") self.addSupportNode(hipGrp, "HipGrp") # Parent the groups mainGrp.setParent(self) hipGrp.setParent(self) # Parent the hip control self.hipIK.setParent(hipGrp) self.aimHelper.setParent(hipGrp) upVector.setParent(hipGrp) # Parent the group self.mainIK.setParent(mainGrp) aimJoint.setParent(mainGrp)
def buildTwist(self): # Check that that a pv exists if self.pv is None: # Create one self.buildPv() # Create a new meta node. self.twist = core.MovableSystem(part=self.part, side=self.side, endSuffix="TwistGrp") # Match it to the first joint self.twist.snap(self.ikHandle.mNode, True) # Parent the PV Control self.pv.setParent(self.twist) # Rotate the new node 90 on first axis of the rotate order self.twist.pynode.attr("r%s" % self.primary_axis[0]).set(90) # Zero out the transform twistPrnt = core.MovableSystem(part=self.part, side=self.side, endSuffix="TwistPrnt") twistPrnt.snap(self.twist.pynode, rotate=True) self.twist.setParent(twistPrnt) self.twist.addSupportNode(twistPrnt, "Prnt") # Parent the PV control to the ik self.mainIK.addChild(twistPrnt.pynode) # offset the twist handle back self.ikHandle.twist = -90 # Add a new divider libUtilities.addDivAttr(self.mainIK.mNode, "Twist", "twistLbl") # Add a control attibute # TODO Get the name from the second part if more than two joints. Otherwise from the first joint libUtilities.addFloatAttr(self.mainIK.mNode, "Knee", shortName="twist", attrMax=720, attrMin=-720) # Connect the new attribute to the twist offset self.mainIK.pynode.twist >> self.twist.pynode.attr("r%s" % self.primary_axis[0])
def buildSolver(self): jntSystem = self.ikJointSystem # Build the main single degree curve baseCurve = utils.createCurve(jntSystem.positions, degree=1) baseCurve.rename(utils.nameMe(self.side, self.part, "CtrlCurve")) self.controlCurve = core.MovableSystem(baseCurve.name()) self.controlCurve.part = self.part self.transferPropertiesToChild(self.controlCurve, "CtrlCurve") self.controlCurve.resetName() # Build the bspline ik curve curve_name = utils.nameMe(self.side, self.part, "BaseCurve") # Sometimes bSpline might generate less CVs as the source....Investigate ikCurve, fitNode = pm.fitBspline(baseCurve, ch=1, tol=0.01, n=curve_name) if len(ikCurve.getCVs()) != len(jntSystem.positions): pm.delete(ikCurve) ikCurve = utils.createCurve(jntSystem.positions) ikCurve.rename(curve_name) self.bSpline = False self.ikCurve = core.MovableSystem(ikCurve.name()) self.ikCurve.part = self.part self.transferPropertiesToChild(self.ikCurve, "BaseCurve") if self.bSpline: fitNodeMeta = core.MetaRig(fitNode.name()) fitNodeMeta.part = self.part self.ikCurve.addSupportNode(fitNodeMeta, "BaseDriver") self.ikCurve.transferPropertiesToChild(fitNodeMeta, "FitNode") fitNodeMeta.resetName() # Build the spline IK name = utils.nameMe(self.side, self.part, "IkHandle") startJoint = jntSystem.joints[0].shortName() endJoint = jntSystem.joints[-1].shortName() # noinspection PyArgumentList ikHandle = pm.ikHandle(name=name, sj=startJoint, ee=endJoint, sol="ikSplineSolver", curve=ikCurve, createCurve=False, freezeJoints=False, rootOnCurve=True)[0] ikHandleMeta = core.MovableSystem(ikHandle.name(), nodeType="IkHandle") self.transferPropertiesToChild(ikHandleMeta, "IkHandle") ikHandleMeta.part = "IkHandle" ikHandleMeta.v = False ikHandleMeta.addParent() self.ikHandle = ikHandleMeta
def buildAutoCompress(self): autoCompressSys = core.NetSubSystem(part="{}HipCompress".format(self.part), side=self.side) autoCompress = core.DistanceMove(part="{}HipCompress".format(self.part), side=self.side) self.addSupportNode(autoCompressSys, "AutoCompressSys") autoCompressSys.addSupportNode(autoCompress, "DistanceMove") autoCompress.point1.setParent(self.hipIK) autoCompress.point1.v = False autoCompress.point1.snap(self.hipIK) autoCompress.point2.setParent(self.mainIK) autoCompress.point2.snap(self.mainIK) autoCompress.point2.v = False autoCompress.mathNode.relativeMeasure = Red9_CoreUtils.distanceBetween(self.hipIK.mNode, self.secondHipIK.mNode) autoCompress.mathNode.biDirection = False autoCompress.reset() aimCompressGrp = core.MovableSystem(part="{}HipCompress".format(self.part), side=self.side) aimCompressGrp.setParent(self.hipIK.parentDriver) compressAimHelper = core.MovableSystem(part="{}HipCompress".format(self.part), side=self.side, endSuffix="AimHelper") compressAimHelper.setParent(aimCompressGrp) compressAimHelper.snap(self.secondHipIK) self.secondHipIK.addConstraint(compressAimHelper, "point") aimKwargs = {"mo": False, "aimVector": [0, 1, 0], "upVector": [1, 0, 0], "worldUpType": "scene"} pm.delete(pm.aimConstraint(self.hipIK.pynode, compressAimHelper.pynode, **aimKwargs)) compressAimHelper.addZeroPrnt() aimCon = pm.aimConstraint(self.hipIK.pynode, compressAimHelper.pynode, **aimKwargs) self.constraintToMetaConstraint(aimCon, "CompressCon", "CompressAim") autoCompress.connectOutput(compressAimHelper.pynode.ty) self.secondHipIK.addDivAttr("AutoCompress") self.secondHipIK.addFloatAttr("Factor", 10, 0, sn="autoCompressFactor", dv=1) autoCompress.connectDisable(self.secondHipIK.pynode.autoCompressFactor)
def cleanUp(self): # Setup the parent of tjoint super(Generic, self).cleanUp() # parent the main ctrols if self.mainCtrls and self.isDeformable: self.ctrlGrp = core.MovableSystem(side=self.side, part=self.part, endSuffix="MainCtrlGrp") self.ctrlGrp.rotateOrder = self.rotateOrder self.ctrlGrp.setParent(self) for ctrl in self.mainCtrls: ctrl.setParent(self.ctrlGrp)
def buildRoll(self, attr, jointTarget): rollName = "{}Roll".format(attr) roll = core.MovableSystem(part=self.part, side=self.side, endSuffix=rollName) roll.addParent(snap=False, endSuffix="{}Prnt".format(rollName)) roll.snap(self.jointSystem.joints[jointTarget].mNode) self.RollSystem.addSupportNode(roll, rollName) inverseMeta = core.MetaRig(part="{}{}".format(self.part, attr), side=self.side, endSuffix="InverseMD", nodeType="multiplyDivide") self.mainIK.pynode.attr(attr) >> inverseMeta.pynode.input1X inverseMeta.pynode.outputX >> roll.pynode.attr("r{}".format(self.bendAxis.lower())) self.RollSystem.addSupportNode(inverseMeta, "{}MD".format(attr)) return roll
def _build_ik_(metaClass, solver, handleSuffix, startJointNumber, endJointNumber): """A generic function to create a IK solver that is used by the various metaClasses. @param metaClass: The metaclass object @param solver: @param handleSuffix: @param startJointNumber: @param endJointNumber: @return: """ name = utils.nameMe(metaClass.side, metaClass.part, handleSuffix) startJoint = metaClass.jointSystem.joints[startJointNumber].mNode endJoint = metaClass.jointSystem.joints[endJointNumber].mNode ikHandle = pm.ikHandle(name=name, sj=startJoint, ee=endJoint, sol=solver, sticky="sticky")[0] ikHandleMeta = core.MovableSystem(ikHandle.name()) metaClass.transferPropertiesToChild(ikHandleMeta, handleSuffix[0].lower() + handleSuffix[1:]) ikHandleMeta.v = False # IK Handle needs to be in it's own group in case the polevector is not set. Otherwise if you reparent it # the polevector value changes in relation to the parent space # Create the parent meta ikHandleMeta.part = metaClass.part ikHandleMeta.addParent(snap=False, endSuffix="{}Prnt".format(handleSuffix)) # Set the pivot to the endJoint libUtilities.snap_pivot(ikHandleMeta.prnt.mNode, endJoint) return ikHandleMeta
def buildSubControls(self): if self.devSpine: return subCtrls = [] npc = libUtilities.create_npc_node(self.ikDriveCurve) # Initialise the groups that will stay at the base and metaise them subCtrlGrp = None for newGrp in ["subCtrlGrp", "rideOnLocGrp"]: newGrpMeta = core.MovableSystem(side=self.side, part=self.part, endSuffix=newGrp.capitalize()) newGrpMeta.rotateOrder = self.rotateOrder self.addSupportNode(newGrpMeta, newGrp.capitalize()) newGrpMeta.setParent(self.infoGrp) exec("{} = newGrpMeta".format(newGrp)) # Iterate through all the control curve for i in range(self.ikDriveCurve.numCVs()): ikCV = self.ikCurve.pynode.cv[i] # Set the subpart name SubPart = "{}Sub{}".format(self.part, i) # Get the CV position joint = self.jointSystem.joints[i].pynode npc.inPosition.set(libUtilities.get_world_space_pos(joint)) # Create a new control object subCtrl = self.createCtrlObj(SubPart, shape="Ball", createXtra=False, addGimbal=False) subCtrls.append(subCtrl) # Add a ctrl locator subCtrl.addSpaceLocator(parent=True) subCtrl.locator.v = False subCtrl.addZeroPrnt() # Create the point on curve node poc = core.MetaRig(part=SubPart, side=self.side, endSuffix="POC", nodeType="pointOnCurveInfo") subCtrl.addSupportNode(poc, "PointOnCurve") poc.parameter = npc.parameter.get() self.ikDriveCurve.worldSpace >> poc.pynode.inputCurve poc.pynode.position >> subCtrl.zeroPrnt.pynode.translate # Control to the CV subCtrl.zeroPrnt.snap(self.jointSystem.joints[i], True, False) subCtrl.prnt.snap(self.jointSystem.joints[i], False) # # Apply a cheap point constraint # libUtilities.cheap_point_constraint(rideOnloc.pynode, subCtrl.zeroPrnt.pynode) # Connect the space locator to the IK Curve libUtilities.snap(subCtrl.locator.pynode, ikCV, rotate=False) libUtilities.cheap_point_constraint(subCtrl.locator.pynode, ikCV) # Lock the rotate and scale subCtrl.lockRotate() subCtrl.lockScale() # Add to parent subCtrl.setParent(subCtrlGrp) # Delete the nearest point on curve pm.delete(npc) # Append the control self.subCtrls = subCtrls
def buildHipSpaceSwitch(self, aimJoint): # Create a helper joint pm.select(cl=1) self.aimHelper = core.MovableSystem(part=aimJoint.part, side=self.side, endSuffix="AimHelper") # self.aimHelper.jointOrient = firstJoint.jointOrient self.aimHelper.rotateOrder = aimJoint.rotateOrder # Align with the first joint self.aimHelper.snap(aimJoint.pynode) # Figure out the up vector position. second_joint_position = self.jointSystem.positions[self.hipEndJointNumber] hipIkPoleVector = self.hipIKHandle.poleVector if self.hipIkSolver == "RotatePlane" else None default_pole_vector = libVector.vector(list(hipIkPoleVector or self.ikHandle.poleVector)) # noinspection PyTypeChecker aimPosition = list(((default_pole_vector * [30, 30, 30] * ([self.scaleFactor] * 3)) + second_joint_position)) if hipIkPoleVector: upVector = core.Ctrl(part="{}PV".format(aimJoint.part), side=self.side, endSuffix="HipPV", shape="Locator") upVector.build() self.addRigCtrl(upVector, "HipPV") upVector.constrainedNode.pynode.setTranslation(aimPosition) pvCon = pm.poleVectorConstraint(upVector.mNode, self.hipIKHandle.mNode, weight=1) self.constraintToMetaConstraint(pvCon, "HipPVCon", "poleVectorConstraint") self.secondHipIK.addDivAttr("Show", "showPV") self.secondHipIK.addBoolAttr("PoleVector", "pvVis") self.secondHipIK.pynode.pvVis >> upVector.pynode.getShape().visibility upVector.lockRotate() upVector.lockScale() else: upVector = core.MovableSystem(part=aimJoint.part, side=self.side, endSuffix="UpVector") self.aimHelper.addSupportNode(upVector, "UpVector") upVector.constrainedNode.pynode.setTranslation(aimPosition) # Aim Constraint at mainIk Handle aimConArgs = [self.mainIK.pynode, self.aimHelper.pynode] aimConKwgs = {"mo": False, "wut": "object", "wuo": upVector.mNode} pm.delete(pm.aimConstraint(*aimConArgs, **aimConKwgs)) self.aimHelper.addParent(endSuffix="AimHelperPrnt") aimCon = pm.aimConstraint(*aimConArgs, **aimConKwgs) self.constraintToMetaConstraint(aimCon, "HipAimCon", "HipAim") # Setup the space switching constraintType = 'orient' if self.hipIkSolver != "Single": constraintType = "parent" self.aimHelper.prnt.v = False # Orient Constraint the Hip Constraint ikJoint = joints.Joint(part=self.part, side=self.side, endSuffix="HipIkFollow") ikJoint.v = False ikJoint.rotateOrder = self.rotateOrder ikJoint.setParent(aimJoint) ikJoint.snap(aimJoint) libUtilities.freeze_rotation(ikJoint.pynode) ikJoint.setParent(self.aimHelper) self.hipIK.addConstraint(ikJoint.pynode, constraintType, mo=True, weightAlias="IK") # Create a base joint hipIKCon = getattr(self.hipIK, "{}Constraint".format(constraintType)) hipIKCon.pynode.w0.set(0) homeJoint = joints.Joint(part=self.part, side=self.side, endSuffix="HomeJnt") homeJoint.v = False homeJoint.rotateOrder = self.rotateOrder homeJoint.setParent(aimJoint) homeJoint.snap(aimJoint) libUtilities.freeze_rotation(homeJoint.pynode) homeJoint.setParent(self) # Add another contraint self.hipIK.addConstraint(homeJoint, constraintType, mo=True, weightAlias=self.part) # Blend between the two constraint self.inverse = core.MetaRig(side=self.side, part=self.part, endSuffix="Inverse", nodeType="reverse") # Attribute based on the system type libUtilities.addDivAttr(self.hipIK.pynode, "SpaceSwitch") attrName = "IK_Parent" libUtilities.addFloatAttr(self.hipIK.pynode, attrName) blendAttr = self.hipIK.pynode.attr(attrName) # Connect the inverse node blendAttr >> self.inverse.pynode.inputX self.inverse.pynode.outputX >> hipIKCon.pynode.w0 blendAttr >> hipIKCon.pynode.w1 # Point constrain the first joint aimJoint.addConstraint(self.hipIK, 'point') return upVector