示例#1
0
    def addOperators(self):
        """Create operators and set the relations for the component rig

        Apply operators, constraints, expressions to the hierarchy.
        In order to keep the code clean and easier to debug,
        we shouldn't create any new object in this method.

        """
        # 1 bone chain Upv ref ==============================================
        self.ikHandleUpvRef = primitive.addIkHandle(
            self.root,
            self.getName("ikHandleArmChainUpvRef"),
            self.armChainUpvRef,
            "ikSCsolver")
        pm.pointConstraint(self.ik_ctl,
                           self.ikHandleUpvRef)
        pm.parentConstraint(self.armChainUpvRef[0],
                            self.upv_cns,
                            mo=True)

        # Visibilities -------------------------------------
        # fk
        fkvis_node = node.createReverseNode(self.blend_att)

        for shp in self.fk0_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk2_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        if self.settings["ikTR"]:
            for shp in self.ikRot_ctl.getShapes():
                pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # Controls ROT order -----------------------------------
        attribute.setRotOrder(self.fk0_ctl, "XZY")
        attribute.setRotOrder(self.fk1_ctl, "XYZ")
        attribute.setRotOrder(self.fk2_ctl, "YZX")
        attribute.setRotOrder(self.ik_ctl, "XYZ")

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc]
        o_node = applyop.gear_ikfk2bone_op(out,
                                           self.root,
                                           self.ik_ref,
                                           self.upv_ctl,
                                           self.fk_ctl[0],
                                           self.fk_ctl[1],
                                           self.fk_ref,
                                           self.length0,
                                           self.length1,
                                           self.negate)

        if self.settings["ikTR"]:
            # connect the control inputs
            outEff_dm = o_node.listConnections(c=True)[-1][1]

            inAttr = self.ikRot_npo.attr("translate")
            outEff_dm.attr("outputTranslate") >> inAttr

            outEff_dm.attr("outputScale") >> self.ikRot_npo.attr("scale")
            dm_node = node.createDecomposeMatrixNode(o_node.attr("outB"))
            dm_node.attr("outputRotate") >> self.ikRot_npo.attr("rotate")

            # rotation
            mulM_node = applyop.gear_mulmatrix_op(
                self.ikRot_ctl.attr("worldMatrix"),
                self.eff_loc.attr("parentInverseMatrix"))
            intM_node = applyop.gear_intmatrix_op(o_node.attr("outEff"),
                                                  mulM_node.attr("output"),
                                                  o_node.attr("blend"))
            dm_node = node.createDecomposeMatrixNode(intM_node.attr("output"))
            dm_node.attr("outputRotate") >> self.eff_loc.attr("rotate")
            transform.matchWorldTransform(self.fk2_ctl, self.ikRot_cns)

        # scale: this fix the scalin popping issue
        intM_node = applyop.gear_intmatrix_op(
            self.fk2_ctl.attr("worldMatrix"),
            self.ik_ctl_ref.attr("worldMatrix"),
            o_node.attr("blend"))
        mulM_node = applyop.gear_mulmatrix_op(
            intM_node.attr("output"),
            self.eff_loc.attr("parentInverseMatrix"))
        dm_node = node.createDecomposeMatrixNode(mulM_node.attr("output"))
        dm_node.attr("outputScale") >> self.eff_loc.attr("scale")

        pm.connectAttr(self.blend_att, o_node + ".blend")
        if self.negate:
            mulVal = -1
        else:
            mulVal = 1
        node.createMulNode(self.roll_att, mulVal, o_node + ".roll")
        pm.connectAttr(self.scale_att, o_node + ".scaleA")
        pm.connectAttr(self.scale_att, o_node + ".scaleB")
        pm.connectAttr(self.maxstretch_att, o_node + ".maxstretch")
        pm.connectAttr(self.slide_att, o_node + ".slide")
        pm.connectAttr(self.softness_att, o_node + ".softness")
        pm.connectAttr(self.reverse_att, o_node + ".reverse")

        # Twist references ---------------------------------

        pm.pointConstraint(self.mid_ctl_twst_ref,
                           self.tws1_npo, maintainOffset=False)
        pm.connectAttr(self.mid_ctl.scaleX, self.tws1_loc.scaleX)
        pm.orientConstraint(self.mid_ctl_twst_ref,
                            self.tws1_npo, maintainOffset=False)

        o_node = applyop.gear_mulmatrix_op(self.eff_loc.attr(
            "worldMatrix"), self.root.attr("worldInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.tws2_npo.attr("translate"))

        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", self.tws2_npo.attr("rotate"))

        o_node = applyop.gear_mulmatrix_op(
            self.eff_loc.attr("worldMatrix"),
            self.tws2_rot.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        attribute.setRotOrder(self.tws2_rot, "XYZ")
        pm.connectAttr(dm_node + ".outputRotate", self.tws2_rot + ".rotate")

        self.tws0_rot.setAttr("sx", .001)
        self.tws2_rot.setAttr("sx", .001)

        add_node = node.createAddNode(self.roundness_att, .001)
        pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))

        pm.connectAttr(self.armpit_roll_att, self.tws0_rot + ".rotateX")

        # Roll Shoulder
        applyop.splineIK(self.getName("rollRef"), self.rollRef,
                         parent=self.root, cParent=self.bone0)

        # Volume -------------------------------------------
        distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc)
        add_node = node.createAddNode(distA_node + ".distance",
                                      distB_node + ".distance")
        div_node = node.createDivNode(add_node + ".output",
                                      self.root.attr("sx"))

        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix")

        div_node2 = node.createDivNode(div_node + ".outputX",
                                       dm_node + ".outputScaleX")
        self.volDriver_att = div_node2 + ".outputX"

        if self.settings["extraTweak"]:
            for tweak_ctl in self.tweak_ctl:
                for shp in tweak_ctl.getShapes():
                    pm.connectAttr(self.tweakVis_att, shp.attr("visibility"))

        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the
        # controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):

            if i < (self.settings["div0"] + 1):
                perc = i * .5 / (self.settings["div0"] + 1.0)
            elif i < (self.settings["div0"] + 2):
                perc = .49
            elif i < (self.settings["div0"] + 3):
                perc = .50
            elif i < (self.settings["div0"] + 4):
                perc = .51

            else:
                perc = .5 + \
                    (i - self.settings["div0"] - 3.0) * .5 / \
                    (self.settings["div1"] + 1.0)

            perc = max(.001, min(.990, perc))

            # Roll
            if self.negate:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot],
                    1 - perc, 40)
            else:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot],
                    perc, 40)

            pm.connectAttr(self.resample_att, o_node + ".resample")
            pm.connectAttr(self.absolute_att, o_node + ".absolute")

            # Squash n Stretch
            o_node = applyop.gear_squashstretch2_op(
                div_cns, None, pm.getAttr(self.volDriver_att), "x")
            pm.connectAttr(self.volume_att, o_node + ".blend")
            pm.connectAttr(self.volDriver_att, o_node + ".driver")
            pm.connectAttr(self.st_att[i], o_node + ".stretch")
            pm.connectAttr(self.sq_att[i], o_node + ".squash")

        # match IK/FK ref
        pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True)
        pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True)
        if self.settings["ikTR"]:
            transform.matchWorldTransform(self.ikRot_ctl, self.match_ikRot)
            transform.matchWorldTransform(self.fk_ctl[2], self.match_fk2)

        return
示例#2
0
    def addOperators(self):

        # Visibilities -------------------------------------
        # fk
        fkvis_node = nod.createReverseNode(self.blend_att)

        for shp in self.fk0_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk0_roll_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))

        fkvis2_node = nod.createReverseNode(self.blend2_att)
        for shp in self.fk2_ctl.getShapes():
            pm.connectAttr(fkvis2_node + ".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # Controls ROT order -----------------------------------
        att.setRotOrder(self.fk0_ctl, "YZX")
        att.setRotOrder(self.fk0_roll_ctl, "YZX")
        att.setRotOrder(self.fk1_ctl, "XYZ")
        att.setRotOrder(self.fk2_ctl, "YZX")
        # att.setRotOrder(self.ik_ctl, "ZYX")
        att.setRotOrder(self.ik_ctl, "XYZ")

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_npo]

        #self.fk_ctl = [self.fk0_roll_ctl, self.fk1_ctl, self.fk2_mtx]
        node = aop.gear_ikfk2bone_op(out, self.root, self.ik_ref, self.upv_ctl,
                                     self.fk_ctl[0], self.fk_ctl[1],
                                     self.fk2_mtx, self.length0, self.length1,
                                     self.negate)

        pm.connectAttr(self.blend_att, node + ".blend")
        pm.connectAttr(self.roll_att, node + ".roll")
        pm.connectAttr(self.scale_att, node + ".scaleA")
        pm.connectAttr(self.scale_att, node + ".scaleB")
        pm.connectAttr(self.maxstretch_att, node + ".maxstretch")
        pm.connectAttr(self.slide_att, node + ".slide")
        pm.connectAttr(self.softness_att, node + ".softness")
        pm.connectAttr(self.reverse_att, node + ".reverse")

        # auto upvector -------------------------------------

        if self.negate:
            node = aop.aimCns(self.upv_auv,
                              self.ik_ctl,
                              axis="-xy",
                              wupType=4,
                              wupVector=[0, 1, 0],
                              wupObject=self.upv_auv,
                              maintainOffset=False)
        else:
            node = aop.aimCns(self.upv_auv,
                              self.ik_ctl,
                              axis="xy",
                              wupType=4,
                              wupVector=[0, 1, 0],
                              wupObject=self.upv_auv,
                              maintainOffset=False)
        pb_node = pm.createNode("pairBlend")
        pb_node.attr("rotInterpolation").set(1)

        pm.connectAttr(self.upv_auv.attr("rotate"), pb_node + ".inRotate2")
        pm.connectAttr(pb_node + ".outRotate", self.upv_mtx.attr("rotate"))
        pm.connectAttr(self.auv_att, pb_node + ".weight")

        # fk2_npo position constraint to effector------------------------
        node = aop.gear_mulmatrix_op(self.eff_npo.attr("worldMatrix"),
                                     self.fk2_npo.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.fk2_npo.attr("translate"))
        # fk2_npo rotation constraint to bone1 (bugfixed) ------------------------
        node = aop.gear_mulmatrix_op(self.bone1.attr("worldMatrix"),
                                     self.fk2_npo.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", self.fk2_npo.attr("rotate"))

        # hand ikfk blending from fk ref to ik ref (serious bugfix)--------------------------------
        node = aop.gear_mulmatrix_op(self.fk_ref.attr("worldMatrix"),
                                     self.eff_loc.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pb_node = pm.createNode("pairBlend")
        pb_node.attr("rotInterpolation").set(1)
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", pb_node + ".inRotate1")
        pm.connectAttr(self.blend2_att, pb_node + ".weight")
        pm.connectAttr(pb_node + ".outRotate", self.eff_loc.attr("rotate"))
        node = aop.gear_mulmatrix_op(self.ik_ref.attr("worldMatrix"),
                                     self.eff_loc.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", pb_node + ".inRotate2")

        # Twist references ---------------------------------
        node = aop.gear_mulmatrix_op(self.mid_ctl.attr("worldMatrix"),
                                     self.tws1_npo.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.tws1_npo.attr("translate"))
        pm.connectAttr(dm_node + ".outputRotate", self.tws1_npo.attr("rotate"))
        pm.connectAttr(dm_node + ".outputScale", self.tws1_npo.attr("scale"))

        node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"),
                                     self.tws2_npo.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.tws2_npo.attr("translate"))
        pm.connectAttr(dm_node + ".outputRotate", self.tws2_npo.attr("rotate"))

        # orientConstraint(self.eff_loc, self.tws2_rot, maintainOffset=False)
        node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"),
                                     self.tws2_rot.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        att.setRotOrder(self.tws2_rot, "XYZ")
        pm.connectAttr(dm_node + ".outputRotate", self.tws2_rot + ".rotate")

        self.tws0_rot.setAttr("sx", .001)
        self.tws2_rot.setAttr("sx", .001)

        add_node = nod.createAddNode(self.roundness_att, .001)
        pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))

        pm.connectAttr(self.armpit_roll_att, self.tws0_rot + ".rotateX")

        #Roll Shoulder--use aimconstraint withour uovwctor to solve the stable twist

        if self.negate:
            node = aop.aimCns(self.tws0_loc,
                              self.mid_ctl,
                              axis="-xy",
                              wupType=4,
                              wupVector=[0, 1, 0],
                              wupObject=self.tws0_npo,
                              maintainOffset=False)
        else:
            node = aop.aimCns(self.tws0_loc,
                              self.mid_ctl,
                              axis="xy",
                              wupType=4,
                              wupVector=[0, 1, 0],
                              wupObject=self.tws0_npo,
                              maintainOffset=False)

        # Volume -------------------------------------------
        distA_node = nod.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = nod.createDistNode(self.tws1_loc, self.tws2_loc)
        add_node = nod.createAddNode(distA_node + ".distance",
                                     distB_node + ".distance")
        div_node = nod.createDivNode(add_node + ".output",
                                     self.root.attr("sx"))

        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix")

        div_node2 = nod.createDivNode(div_node + ".outputX",
                                      dm_node + ".outputScaleX")
        self.volDriver_att = div_node2 + ".outputX"

        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):

            if i < (self.settings["div0"] + 1):
                perc = i * .5 / (self.settings["div0"] + 1.0)
            elif i < (self.settings["div0"] + 2):
                perc = .49
            elif i < (self.settings["div0"] + 3):
                perc = .50
            elif i < (self.settings["div0"] + 4):
                perc = .51

            else:
                perc = .5 + (i - self.settings["div0"] -
                             3.0) * .5 / (self.settings["div1"] + 1.0)

            perc = max(.001, min(.990, perc))

            # Roll
            if self.negate:
                node = aop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot],
                    1 - perc, 40)
            else:
                node = aop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot],
                    perc, 40)

            pm.connectAttr(self.resample_att, node + ".resample")
            pm.connectAttr(self.absolute_att, node + ".absolute")

            # Squash n Stretch
            node = aop.gear_squashstretch2_op(div_cns, None,
                                              pm.getAttr(self.volDriver_att),
                                              "x")
            pm.connectAttr(self.volume_att, node + ".blend")
            pm.connectAttr(self.volDriver_att, node + ".driver")
            pm.connectAttr(self.st_att[i], node + ".stretch")
            pm.connectAttr(self.sq_att[i], node + ".squash")

        # match IK/FK ref
        pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True)
        pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True)

        return
示例#3
0
    def addOperators(self):
        """Create operators and set the relations for the component rig

        Apply operators, constraints, expressions to the hierarchy.
        In order to keep the code clean and easier to debug,
        we shouldn't create any new object in this method.

        """
        # Soft condition
        soft_cond_node = node.createConditionNode(self.soft_attr, 0.0001, 4,
                                                  0.0001, self.soft_attr)
        self.soft_attr_cond = soft_cond_node.outColorR

        if self.settings["ikSolver"]:
            self.ikSolver = "ikRPsolver"
        else:
            pm.mel.eval("ikSpringSolver;")
            self.ikSolver = "ikSpringSolver"

        # 1 bone chain Upv ref ===============================
        self.ikHandleUpvRef = primitive.addIkHandle(
            self.root, self.getName("ikHandleLegChainUpvRef"),
            self.legChainUpvRef, "ikSCsolver")
        pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef)
        pm.parentConstraint(self.legChainUpvRef[0], self.upv_cns, mo=True)

        # mid joints ================================================
        for xjnt, midJ in zip(self.legBones[1:3],
                              [self.mid1_jnt, self.mid2_jnt]):
            node.createPairBlend(None, xjnt, .5, 1, midJ)
            pm.connectAttr(xjnt + ".translate", midJ + ".translate", f=True)

        pm.parentConstraint(self.mid1_jnt, self.knee_lvl)
        pm.parentConstraint(self.mid2_jnt, self.ankle_lvl)

        # joint length multiply
        multJnt1_node = node.createMulNode(self.boneALenght_attr,
                                           self.boneALenghtMult_attr)
        multJnt2_node = node.createMulNode(self.boneBLenght_attr,
                                           self.boneBLenghtMult_attr)
        multJnt3_node = node.createMulNode(self.boneCLenght_attr,
                                           self.boneCLenghtMult_attr)

        # # IK 3 bones ===============================================

        self.ikHandle = primitive.addIkHandle(self.softblendLoc,
                                              self.getName("ik3BonesHandle"),
                                              self.chain3bones, self.ikSolver,
                                              self.upv_ctl)

        # TwistTest
        if [round(elem, 4)
                for elem in transform.getTranslation(self.chain3bones[1])] \
                != [round(elem, 4) for elem in self.guide.apos[1]]:
            add_nodeTwist = node.createAddNode(180.0, self.roll_att)
        else:
            add_nodeTwist = node.createAddNode(0, self.roll_att)
        if self.negate:
            mulVal = 1
        else:
            mulVal = -1
        node.createMulNode(add_nodeTwist + ".output", mulVal,
                           self.ikHandle.attr("twist"))

        # stable spring solver doble rotation
        pm.pointConstraint(self.root_ctl, self.chain3bones[0])

        # softIK 3 bones operators
        applyop.aimCns(self.aim_tra,
                       self.ik_ref,
                       axis="zx",
                       wupType=4,
                       wupVector=[1, 0, 0],
                       wupObject=self.root_ctl,
                       maintainOffset=False)

        plusTotalLength_node = node.createPlusMinusAverage1D([
            multJnt1_node.attr("outputX"),
            multJnt2_node.attr("outputX"),
            multJnt3_node.attr("outputX")
        ])

        subtract1_node = node.createPlusMinusAverage1D(
            [plusTotalLength_node.attr("output1D"), self.soft_attr_cond], 2)

        distance1_node = node.createDistNode(self.ik_ref, self.aim_tra)
        div1_node = node.createDivNode(1.0, self.rig.global_ctl + ".sx")
        mult1_node = node.createMulNode(distance1_node + ".distance",
                                        div1_node + ".outputX")
        subtract2_node = node.createPlusMinusAverage1D(
            [mult1_node.attr("outputX"),
             subtract1_node.attr("output1D")], 2)
        div2_node = node.createDivNode(subtract2_node + ".output1D",
                                       self.soft_attr_cond)
        mult2_node = node.createMulNode(-1, div2_node + ".outputX")
        power_node = node.createPowNode(self.softSpeed_attr,
                                        mult2_node + ".outputX")
        mult3_node = node.createMulNode(self.soft_attr_cond,
                                        power_node + ".outputX")
        subtract3_node = node.createPlusMinusAverage1D([
            plusTotalLength_node.attr("output1D"),
            mult3_node.attr("outputX")
        ], 2)

        cond1_node = node.createConditionNode(
            self.soft_attr_cond, 0, 2, subtract3_node + ".output1D",
            plusTotalLength_node + ".output1D")

        cond2_node = node.createConditionNode(mult1_node + ".outputX",
                                              subtract1_node + ".output1D", 2,
                                              cond1_node + ".outColorR",
                                              mult1_node + ".outputX")

        pm.connectAttr(cond2_node + ".outColorR", self.wristSoftIK + ".tz")

        # soft blend
        pc_node = pm.pointConstraint(self.wristSoftIK, self.ik_ref,
                                     self.softblendLoc)
        node.createReverseNode(self.stretch_attr,
                               pc_node + ".target[0].targetWeight")
        pm.connectAttr(self.stretch_attr,
                       pc_node + ".target[1].targetWeight",
                       f=True)

        # Stretch
        distance2_node = node.createDistNode(self.softblendLoc,
                                             self.wristSoftIK)
        mult4_node = node.createMulNode(distance2_node + ".distance",
                                        div1_node + ".outputX")

        # bones
        for i, mulNode in enumerate(
            [multJnt1_node, multJnt2_node, multJnt3_node]):

            div3_node = node.createDivNode(mulNode + ".outputX",
                                           plusTotalLength_node + ".output1D")

            mult5_node = node.createMulNode(mult4_node + ".outputX",
                                            div3_node + ".outputX")

            mult6_node = node.createMulNode(self.stretch_attr,
                                            mult5_node + ".outputX")

            node.createPlusMinusAverage1D(
                [mulNode.attr("outputX"),
                 mult6_node.attr("outputX")], 1,
                self.chain3bones[i + 1] + ".tx")

        # IK 2 bones ===============================================

        self.ikHandle2 = primitive.addIkHandle(self.softblendLoc2,
                                               self.getName("ik2BonesHandle"),
                                               self.chain2bones, self.ikSolver,
                                               self.upv_ctl)

        node.createMulNode(self.roll_att, mulVal, self.ikHandle2.attr("twist"))

        # stable spring solver doble rotation
        pm.pointConstraint(self.root_ctl, self.chain2bones[0])

        parentc_node = pm.parentConstraint(self.ik2b_ikCtl_ref,
                                           self.ik2b_bone_ref, self.ik2b_blend)

        node.createReverseNode(self.fullIK_attr,
                               parentc_node + ".target[0].targetWeight")

        pm.connectAttr(self.fullIK_attr,
                       parentc_node + ".target[1].targetWeight",
                       f=True)

        # softIK 2 bones operators
        applyop.aimCns(self.aim_tra2,
                       self.ik2b_ik_ref,
                       axis="zx",
                       wupType=4,
                       wupVector=[1, 0, 0],
                       wupObject=self.root_ctl,
                       maintainOffset=False)

        plusTotalLength_node = node.createPlusMinusAverage1D(
            [multJnt1_node.attr("outputX"),
             multJnt2_node.attr("outputX")])

        subtract1_node = node.createPlusMinusAverage1D(
            [plusTotalLength_node.attr("output1D"), self.soft_attr_cond], 2)

        distance1_node = node.createDistNode(self.ik2b_ik_ref, self.aim_tra2)
        div1_node = node.createDivNode(1, self.rig.global_ctl + ".sx")

        mult1_node = node.createMulNode(distance1_node + ".distance",
                                        div1_node + ".outputX")

        subtract2_node = node.createPlusMinusAverage1D(
            [mult1_node.attr("outputX"),
             subtract1_node.attr("output1D")], 2)

        div2_node = node.createDivNode(subtract2_node + ".output1D",
                                       self.soft_attr_cond)

        mult2_node = node.createMulNode(-1, div2_node + ".outputX")

        power_node = node.createPowNode(self.softSpeed_attr,
                                        mult2_node + ".outputX")

        mult3_node = node.createMulNode(self.soft_attr_cond,
                                        power_node + ".outputX")

        subtract3_node = node.createPlusMinusAverage1D([
            plusTotalLength_node.attr("output1D"),
            mult3_node.attr("outputX")
        ], 2)

        cond1_node = node.createConditionNode(
            self.soft_attr_cond, 0, 2, subtract3_node + ".output1D",
            plusTotalLength_node + ".output1D")

        cond2_node = node.createConditionNode(mult1_node + ".outputX",
                                              subtract1_node + ".output1D", 2,
                                              cond1_node + ".outColorR",
                                              mult1_node + ".outputX")

        pm.connectAttr(cond2_node + ".outColorR", self.ankleSoftIK + ".tz")

        # soft blend
        pc_node = pm.pointConstraint(self.ankleSoftIK, self.ik2b_ik_ref,
                                     self.softblendLoc2)
        node.createReverseNode(self.stretch_attr,
                               pc_node + ".target[0].targetWeight")
        pm.connectAttr(self.stretch_attr,
                       pc_node + ".target[1].targetWeight",
                       f=True)

        # Stretch
        distance2_node = node.createDistNode(self.softblendLoc2,
                                             self.ankleSoftIK)

        mult4_node = node.createMulNode(distance2_node + ".distance",
                                        div1_node + ".outputX")

        for i, mulNode in enumerate([multJnt1_node, multJnt2_node]):
            div3_node = node.createDivNode(mulNode + ".outputX",
                                           plusTotalLength_node + ".output1D")

            mult5_node = node.createMulNode(mult4_node + ".outputX",
                                            div3_node + ".outputX")

            mult6_node = node.createMulNode(self.stretch_attr,
                                            mult5_node + ".outputX")

            node.createPlusMinusAverage1D(
                [mulNode.attr("outputX"),
                 mult6_node.attr("outputX")], 1,
                self.chain2bones[i + 1] + ".tx")

        # IK/FK connections

        for i, x in enumerate(self.fk_ctl):
            pm.parentConstraint(x, self.legBonesFK[i], mo=True)

        for i, x in enumerate([self.chain2bones[0], self.chain2bones[1]]):
            pm.parentConstraint(x, self.legBonesIK[i], mo=True)

        pm.pointConstraint(self.ik2b_ik_ref, self.legBonesIK[2])
        applyop.aimCns(self.legBonesIK[2],
                       self.roll_ctl,
                       axis="xy",
                       wupType=4,
                       wupVector=[0, 1, 0],
                       wupObject=self.legBonesIK[1],
                       maintainOffset=False)

        pm.connectAttr(self.chain3bones[-1].attr("tx"),
                       self.legBonesIK[-1].attr("tx"))
        # foot twist roll
        pm.orientConstraint(self.ik_ref, self.legBonesIK[-1], mo=True)

        node.createMulNode(-1, self.chain3bones[-1].attr("tx"),
                           self.ik2b_ik_ref.attr("tx"))

        for i, x in enumerate(self.legBones):
            node.createPairBlend(self.legBonesFK[i], self.legBonesIK[i],
                                 self.blend_att, 1, x)

        # Twist references ----------------------------------------

        self.ikhArmRef, self.tmpCrv = applyop.splineIK(
            self.getName("legRollRef"),
            self.rollRef,
            parent=self.root,
            cParent=self.legBones[0])

        initRound = .001
        multVal = 1

        multTangent_node = node.createMulNode(self.roundnessKnee_att, multVal)
        add_node = node.createAddNode(multTangent_node + ".outputX", initRound)
        pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))
        for x in ["translate"]:
            pm.connectAttr(self.knee_ctl.attr(x), self.tws1_loc.attr(x))
        for x in "xy":
            pm.connectAttr(self.knee_ctl.attr("r" + x),
                           self.tws1_loc.attr("r" + x))

        multTangent_node = node.createMulNode(self.roundnessAnkle_att, multVal)
        add_node = node.createAddNode(multTangent_node + ".outputX", initRound)
        pm.connectAttr(add_node + ".output", self.tws2_rot.attr("sx"))
        for x in ["translate"]:
            pm.connectAttr(self.ankle_ctl.attr(x), self.tws2_loc.attr(x))
        for x in "xy":
            pm.connectAttr(self.ankle_ctl.attr("r" + x),
                           self.tws2_loc.attr("r" + x))

        # Volume -------------------------------------------
        distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc)
        distC_node = node.createDistNode(self.tws2_loc, self.tws3_loc)
        add_node = node.createAddNode(distA_node + ".distance",
                                      distB_node + ".distance")
        add_node2 = node.createAddNode(distC_node + ".distance",
                                       add_node + ".output")
        div_node = node.createDivNode(add_node2 + ".output",
                                      self.root_ctl.attr("sx"))

        # comp scaling
        dm_node = node.createDecomposeMatrixNode(self.root.attr("worldMatrix"))

        div_node2 = node.createDivNode(div_node + ".outputX",
                                       dm_node + ".outputScaleX")

        self.volDriver_att = div_node2 + ".outputX"

        # Flip Offset ----------------------------------------
        pm.connectAttr(self.ankleFlipOffset_att, self.tws2_loc.attr("rz"))
        pm.connectAttr(self.kneeFlipOffset_att, self.tws1_loc.attr("rz"))
        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the
        # controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):
            subdiv = False
            if i == len(self.div_cns) - 1 or i == 0:
                subdiv = 45
            else:
                subdiv = 45

            if i < (self.settings["div0"] + 1):
                perc = i * .333 / (self.settings["div0"] + 1.0)

            elif i < (self.settings["div0"] + self.settings["div1"] + 2):
                perc = i * .333 / (self.settings["div0"] + 1.0)
            else:
                perc = (.5 + (i - self.settings["div0"] - 3.0) * .5 /
                        (self.settings["div1"] + 1.0))

            if i < (self.settings["div0"] + 2):
                perc = i * .333 / (self.settings["div0"] + 1.0)

            elif i < (self.settings["div0"] + self.settings["div1"] + 3):
                perc = (.333 + (i - self.settings["div0"] - 1) * .333 /
                        (self.settings["div1"] + 1.0))
            else:
                perc = (
                    .666 +
                    (i - self.settings["div1"] - self.settings["div0"] - 2.0) *
                    .333 / (self.settings["div2"] + 1.0))

            # we neet to offset the ankle and knee point to force the bone
            # orientation to the nex bone span
            if perc == .333:
                perc = .3338
            elif perc == .666:
                perc = .6669

            perc = max(.001, min(.999, perc))

            # Roll
            cts = [self.tws0_rot, self.tws1_rot, self.tws2_rot, self.tws3_rot]
            o_node = applyop.gear_rollsplinekine_op(div_cns, cts, perc, subdiv)

            pm.connectAttr(self.resample_att, o_node + ".resample")
            pm.connectAttr(self.absolute_att, o_node + ".absolute")

            # Squash n Stretch
            o_node = applyop.gear_squashstretch2_op(
                div_cns, None, pm.getAttr(self.volDriver_att), "x")
            pm.connectAttr(self.volume_att, o_node + ".blend")
            pm.connectAttr(self.volDriver_att, o_node + ".driver")
            pm.connectAttr(self.st_att[i], o_node + ".stretch")
            pm.connectAttr(self.sq_att[i], o_node + ".squash")

        # Visibilities -------------------------------------
        # fk
        fkvis_node = node.createReverseNode(self.blend_att)
        for ctrl in self.fk_ctl:
            for shp in ctrl.getShapes():
                pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        # ik
        for ctrl in [self.ik_ctl, self.roll_ctl]:
            for shp in ctrl.getShapes():
                pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # setup leg o_node scale compensate
        pm.connectAttr(self.rig.global_ctl + ".scale", self.setup + ".scale")

        return
示例#4
0
文件: __init__.py 项目: Gotetz/mgear
    def addOperators(self):
        """Create operators and set the relations for the component rig

        Apply operators, constraints, expressions to the hierarchy.
        In order to keep the code clean and easier to debug,
        we shouldn't create any new object in this method.

        """

        # 1 bone chain Upv ref ===========================
        self.ikHandleUpvRef = primitive.addIkHandle(
            self.root, self.getName("ikHandleLegChainUpvRef"),
            self.legChainUpvRef, "ikSCsolver")
        pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef)
        pm.parentConstraint(self.legChainUpvRef[0],
                            self.ik_ctl,
                            self.upv_cns,
                            mo=True)

        # Visibilities -------------------------------------
        # shape.dispGeometry
        # fk
        fkvis_node = node.createReverseNode(self.blend_att)

        for shp in self.fk0_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk2_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc]
        o_node = applyop.gear_ikfk2bone_op(out, self.root_ctl, self.ik_ref,
                                           self.upv_ctl, self.fk_ctl[0],
                                           self.fk_ctl[1], self.fk_ref,
                                           self.length0, self.length1,
                                           self.negate)

        pm.connectAttr(self.blend_att, o_node + ".blend")
        if self.negate:
            mulVal = -1
        else:
            mulVal = 1
        node.createMulNode(self.roll_att, mulVal, o_node + ".roll")
        pm.connectAttr(self.scale_att, o_node + ".scaleA")
        pm.connectAttr(self.scale_att, o_node + ".scaleB")
        pm.connectAttr(self.maxstretch_att, o_node + ".maxstretch")
        pm.connectAttr(self.slide_att, o_node + ".slide")
        pm.connectAttr(self.softness_att, o_node + ".softness")
        pm.connectAttr(self.reverse_att, o_node + ".reverse")

        # Twist references ---------------------------------
        self.ikhArmRef, self.tmpCrv = applyop.splineIK(
            self.getName("legRollRef"),
            self.rollRef,
            parent=self.root,
            cParent=self.bone0)

        pm.pointConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False)
        pm.scaleConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False)
        applyop.oriCns(self.mid_ctl, self.tws1_rot, maintainOffset=False)

        pm.pointConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False)
        pm.scaleConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False)
        applyop.oriCns(self.bone1, self.tws2_loc, maintainOffset=False)

        applyop.oriCns(self.tws_ref, self.tws2_rot)

        self.tws0_loc.setAttr("sx", .001)
        self.tws2_loc.setAttr("sx", .001)

        add_node = node.createAddNode(self.roundness_att, .001)
        pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))

        # Volume -------------------------------------------
        distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc)
        add_node = node.createAddNode(distA_node + ".distance",
                                      distB_node + ".distance")
        div_node = node.createDivNode(add_node + ".output",
                                      self.root_ctl.attr("sx"))

        # comp scaling issue
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix")

        div_node2 = node.createDivNode(div_node + ".outputX",
                                       dm_node + ".outputScaleX")

        self.volDriver_att = div_node2 + ".outputX"

        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the
        # controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):
            subdiv = False
            if i == len(self.div_cns) - 1 or i == 0:
                subdiv = 45
            else:
                subdiv = 10

            if i < (self.settings["div0"] + 1):
                perc = i * .5 / (self.settings["div0"] + 1.0)
            elif i < (self.settings["div0"] + 2):
                perc = .49
                subdiv = 45
            elif i < (self.settings["div0"] + 3):
                perc = .50
                subdiv = 45
            elif i < (self.settings["div0"] + 4):
                perc = .51
                subdiv = 45

            else:
                perc = (.5 + (i - self.settings["div0"] - 3.0) * .5 /
                        (self.settings["div1"] + 1.0))

            perc = max(.001, min(.999, perc))

            # Roll
            if self.negate:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot],
                    1 - perc, subdiv)
            else:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot],
                    perc, subdiv)

            pm.connectAttr(self.resample_att, o_node + ".resample")
            pm.connectAttr(self.absolute_att, o_node + ".absolute")

            # Squash n Stretch
            o_node = applyop.gear_squashstretch2_op(
                div_cns, None, pm.getAttr(self.volDriver_att), "x")
            pm.connectAttr(self.volume_att, o_node + ".blend")
            pm.connectAttr(self.volDriver_att, o_node + ".driver")
            pm.connectAttr(self.st_att[i], o_node + ".stretch")
            pm.connectAttr(self.sq_att[i], o_node + ".squash")

        # NOTE: next line fix the issue on meters.
        # This is special case becasuse the IK solver from mGear use
        # the scale as lenght and we have shear
        # TODO: check for a more clean and elegant solution instead of
        # re-match the world matrix again
        # transform.matchWorldTransform(self.fk_ctl[0], self.match_fk0_off)
        # transform.matchWorldTransform(self.fk_ctl[1], self.match_fk1_off)
        # transform.matchWorldTransform(self.fk_ctl[0], self.match_fk0)
        # transform.matchWorldTransform(self.fk_ctl[1], self.match_fk1)

        # match IK/FK ref
        pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True)
        pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True)
        return
示例#5
0
文件: __init__.py 项目: Gotetz/mgear
    def addOperators(self):
        """Create operators and set the relations for the component rig

        Apply operators, constraints, expressions to the hierarchy.
        In order to keep the code clean and easier to debug,
        we shouldn't create any new object in this method.

        """

        # Visibilities -------------------------------------
        # fk
        fkvis_node = node.createReverseNode(self.blend_att)

        for shp in self.fk0_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk0_roll_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_roll_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))

        fkvis2_node = node.createReverseNode(self.blend2_att)
        for shp in self.fk2_ctl.getShapes():
            pm.connectAttr(fkvis2_node + ".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # jnt ctl
        for ctl in (self.div_ctls):
            for shp in ctl.getShapes():
                pm.connectAttr(self.jntctl_vis_att, shp.attr("visibility"))

        # Controls ROT order -----------------------------------
        attribute.setRotOrder(self.fk0_ctl, "YZX")
        attribute.setRotOrder(self.fk1_ctl, "XYZ")
        attribute.setRotOrder(self.fk2_ctl, "YZX")
        attribute.setRotOrder(self.ik_ctl, "XYZ")

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_npo]

        o_node = applyop.gear_ikfk2bone_op(out, self.root, self.ik_ref,
                                           self.upv_ctl, self.fk0_mtx,
                                           self.fk1_mtx, self.fk2_mtx,
                                           self.length0, self.length1,
                                           self.negate)

        pm.connectAttr(self.blend_att, o_node + ".blend")
        pm.connectAttr(self.roll_att, o_node + ".roll")
        pm.connectAttr(self.scale_att, o_node + ".scaleA")
        pm.connectAttr(self.scale_att, o_node + ".scaleB")
        pm.connectAttr(self.maxstretch_att, o_node + ".maxstretch")
        pm.connectAttr(self.slide_att, o_node + ".slide")
        pm.connectAttr(self.softness_att, o_node + ".softness")
        pm.connectAttr(self.reverse_att, o_node + ".reverse")
        # update issue on effector scale interpol, disconnect for stability
        pm.disconnectAttr(self.eff_npo.scale)
        # auto upvector -------------------------------------

        if self.negate:
            o_node = applyop.aimCns(self.upv_auv,
                                    self.ik_ctl,
                                    axis="-xy",
                                    wupType=4,
                                    wupVector=[0, 1, 0],
                                    wupObject=self.upv_auv,
                                    maintainOffset=False)
        else:
            o_node = applyop.aimCns(self.upv_auv,
                                    self.ik_ctl,
                                    axis="xy",
                                    wupType=4,
                                    wupVector=[0, 1, 0],
                                    wupObject=self.upv_auv,
                                    maintainOffset=False)

        o_node = applyop.gear_mulmatrix_op(
            self.upv_auv.attr("worldMatrix"),
            self.upv_mtx.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pb_node = pm.createNode("pairBlend")
        pb_node.attr("rotInterpolation").set(1)
        pm.connectAttr(dm_node + ".outputTranslate", pb_node + ".inTranslate2")
        pm.connectAttr(dm_node + ".outputRotate", pb_node + ".inRotate2")
        pm.connectAttr(pb_node + ".outRotate", self.upv_mtx.attr("rotate"))
        pm.connectAttr(pb_node + ".outTranslate",
                       self.upv_mtx.attr("translate"))
        pm.connectAttr(self.auv_att, pb_node + ".weight")

        # fk0 mtx connection
        o_node = applyop.gear_mulmatrix_op(
            self.fk0_roll_ctl.attr("worldMatrix"),
            self.fk0_mtx.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.fk0_mtx.attr("translate"))
        pm.connectAttr(dm_node + ".outputRotate", self.fk0_mtx.attr("rotate"))
        # fk1 loc connect to fk1 ref @ pos and rot, not scl to avoid shearing
        o_node = applyop.gear_mulmatrix_op(
            self.fk1_ref.attr("worldMatrix"),
            self.fk1_loc.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.fk1_loc.attr("translate"))
        pm.connectAttr(dm_node + ".outputRotate", self.fk1_loc.attr("rotate"))
        # fk1 mtx orient cns to fk1 roll
        pm.connectAttr(self.fk1_roll_ctl.attr("rotate"),
                       self.fk1_mtx.attr("rotate"))
        # fk2_loc position constraint to effector------------------------
        o_node = applyop.gear_mulmatrix_op(
            self.eff_npo.attr("worldMatrix"),
            self.fk2_loc.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.fk2_loc.attr("translate"))
        # fk2_loc rotation constraint to bone1 (bugfixed) --------------
        o_node = applyop.gear_mulmatrix_op(
            self.bone1.attr("worldMatrix"),
            self.fk2_loc.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", self.fk2_loc.attr("rotate"))

        # hand ikfk blending from fk ref to ik ref (serious bugfix)--------
        o_node = applyop.gear_mulmatrix_op(
            self.fk_ref.attr("worldMatrix"),
            self.eff_loc.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pb_node = pm.createNode("pairBlend")
        pb_node.attr("rotInterpolation").set(1)
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", pb_node + ".inRotate1")
        pm.connectAttr(self.blend2_att, pb_node + ".weight")
        pm.connectAttr(pb_node + ".outRotate", self.eff_loc.attr("rotate"))
        o_node = applyop.gear_mulmatrix_op(
            self.ik_ref.attr("worldMatrix"),
            self.eff_loc.attr("parentInverseMatrix"))
        dm_node1 = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node1 + ".inputMatrix")
        pm.connectAttr(dm_node1 + ".outputRotate", pb_node + ".inRotate2")
        # use blendcolors to blend scale
        bc_node = pm.createNode("blendColors")
        pm.connectAttr(self.blend_att, bc_node + ".blender")
        pm.connectAttr(dm_node + ".outputScale", bc_node + ".color2")
        pm.connectAttr(dm_node1 + ".outputScale", bc_node + ".color1")
        pm.connectAttr(bc_node + ".output", self.eff_loc.attr("scale"))

        # Twist references ---------------------------------
        pm.connectAttr(self.mid_ctl.attr("translate"),
                       self.tws1_npo.attr("translate"))
        pm.connectAttr(self.mid_ctl.attr("rotate"),
                       self.tws1_npo.attr("rotate"))
        pm.connectAttr(self.mid_ctl.attr("scale"), self.tws1_npo.attr("scale"))

        o_node = applyop.gear_mulmatrix_op(
            self.eff_loc.attr("worldMatrix"),
            self.tws3_npo.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")

        pm.connectAttr(dm_node + ".outputTranslate",
                       self.tws3_npo.attr("translate"))

        pm.connectAttr(dm_node + ".outputRotate", self.tws3_npo.attr("rotate"))

        attribute.setRotOrder(self.tws3_rot, "XYZ")

        # elbow thickness connection
        if self.negate:
            o_node = node.createMulNode(
                [self.elbow_thickness_att, self.elbow_thickness_att],
                [0.5, -0.5, 0],
                [self.tws1_loc + ".translateX", self.tws2_loc + ".translateX"])
        else:
            o_node = node.createMulNode(
                [self.elbow_thickness_att, self.elbow_thickness_att],
                [-0.5, 0.5, 0],
                [self.tws1_loc + ".translateX", self.tws2_loc + ".translateX"])

        # connect both tws1 and tws2  (mid tws)
        self.tws0_rot.setAttr("sx", .001)
        self.tws3_rot.setAttr("sx", .001)

        add_node = node.createAddNode(self.roundness0_att, .001)
        pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))

        add_node = node.createAddNode(self.roundness1_att, .001)
        pm.connectAttr(add_node + ".output", self.tws2_rot.attr("sx"))

        pm.connectAttr(self.armpit_roll_att, self.tws0_rot + ".rotateX")

        # Roll Shoulder--use aimconstraint withour uovwctor to solve
        # the stable twist

        if self.negate:
            o_node = applyop.aimCns(self.tws0_loc,
                                    self.mid_ctl,
                                    axis="-xy",
                                    wupType=4,
                                    wupVector=[0, 1, 0],
                                    wupObject=self.tws0_npo,
                                    maintainOffset=False)
        else:
            o_node = applyop.aimCns(self.tws0_loc,
                                    self.mid_ctl,
                                    axis="xy",
                                    wupType=4,
                                    wupVector=[0, 1, 0],
                                    wupObject=self.tws0_npo,
                                    maintainOffset=False)

        # Volume -------------------------------------------
        distA_node = node.createDistNode(self.tws0_loc, self.tws1_npo)
        distB_node = node.createDistNode(self.tws1_npo, self.tws3_loc)
        add_node = node.createAddNode(distA_node + ".distance",
                                      distB_node + ".distance")
        div_node = node.createDivNode(add_node + ".output",
                                      self.root.attr("sx"))

        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix")

        div_node2 = node.createDivNode(div_node + ".outputX",
                                       dm_node + ".outputScaleX")
        self.volDriver_att = div_node2 + ".outputX"

        # Divisions ----------------------------------------
        # div mid constraint to mid ctl
        o_node = applyop.gear_mulmatrix_op(
            self.mid_ctl.attr("worldMatrix"),
            self.div_mid.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.div_mid.attr("translate"))
        pm.connectAttr(dm_node + ".outputRotate", self.div_mid.attr("rotate"))

        # at 0 or 1 the division will follow exactly the rotation of the
        # controler.. and we wont have this nice tangent + roll
        # linear scaling percentage (1) to effector (2) to elbow
        scl_1_perc = []
        scl_2_perc = []

        for i, div_cnsUp in enumerate(self.div_cnsUp):

            if i < (self.settings["div0"] + 1):
                perc = i / (self.settings["div0"] + 1.0)
            elif i < (self.settings["div0"] + 2):
                perc = .95

            perc = max(.001, min(.99, perc))

            # Roll
            if self.negate:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cnsUp, [self.tws1_rot, self.tws0_rot], 1 - perc, 20)

            else:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cnsUp, [self.tws0_rot, self.tws1_rot], perc, 20)

            pm.connectAttr(self.resample_att, o_node + ".resample")
            pm.connectAttr(self.absolute_att, o_node + ".absolute")

            scl_1_perc.append(perc / 2)
            scl_2_perc.append(perc)
        scl_1_perc.append(0.5)
        scl_2_perc.append(1)
        for i, div_cnsDn in enumerate(self.div_cnsDn):

            if i == (0):
                perc = .05
            elif i < (self.settings["div1"] + 1):
                perc = i / (self.settings["div1"] + 1.0)
            elif i < (self.settings["div1"] + 2):
                perc = .95

            perc = max(.001, min(.990, perc))

            # Roll
            if self.negate:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cnsDn, [self.tws3_rot, self.tws2_rot], 1 - perc, 20)

            else:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cnsDn, [self.tws2_rot, self.tws3_rot], perc, 20)
            pm.connectAttr(self.resample_att, o_node + ".resample")
            pm.connectAttr(self.absolute_att, o_node + ".absolute")

            scl_1_perc.append(perc / 2 + 0.5)
            scl_2_perc.append(1 - perc)
        # Squash n Stretch
        for i, div_cns in enumerate(self.div_cns):
            o_node = applyop.gear_squashstretch2_op(
                div_cns, None, pm.getAttr(self.volDriver_att), "x")
            pm.connectAttr(self.volume_att, o_node + ".blend")
            pm.connectAttr(self.volDriver_att, o_node + ".driver")
            pm.connectAttr(self.st_att[i], o_node + ".stretch")
            pm.connectAttr(self.sq_att[i], o_node + ".squash")
            # get the first mult_node after sq op
            mult_node = pm.listHistory(o_node, future=True)[1]
            # linear blend effector scale
            bc_node = pm.createNode("blendColors")
            bc_node.setAttr("color2R", 1)
            bc_node.setAttr("color2G", 1)
            bc_node.setAttr("blender", scl_1_perc[i])
            pm.connectAttr(self.eff_loc.attr("scale"), bc_node + ".color1")
            # linear blend mid scale
            bc_node2 = pm.createNode("blendColors")
            bc_node2.setAttr("color2R", 1)
            bc_node2.setAttr("color2G", 1)
            bc_node2.setAttr("blender", scl_2_perc[i])
            pm.connectAttr(self.mid_ctl.attr("scale"), bc_node2 + ".color1")
            # mid_ctl scale * effector scale
            mult_node2 = pm.createNode("multiplyDivide")
            pm.connectAttr(bc_node2 + ".output", mult_node2 + ".input1")
            pm.connectAttr(bc_node + ".output", mult_node2 + ".input2")
            # plug to sq scale
            pm.connectAttr(mult_node2 + ".output", mult_node + ".input2")

        # match IK/FK ref
        pm.connectAttr(self.bone0.attr("rotate"),
                       self.match_fk0.attr("rotate"))
        pm.connectAttr(self.bone0.attr("translate"),
                       self.match_fk0.attr("translate"))
        pm.connectAttr(self.bone1.attr("rotate"),
                       self.match_fk1.attr("rotate"))
        pm.connectAttr(self.bone1.attr("translate"),
                       self.match_fk1.attr("translate"))

        return
示例#6
0
    def addOperators(self):

        # 1 bone chain Upv ref =====================================================================================
        self.ikHandleUpvRef = pri.addIkHandle(
            self.root, self.getName("ikHandleLegChainUpvRef"),
            self.armChainUpvRef, "ikSCsolver")
        pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef)
        pm.parentConstraint(self.armChainUpvRef[0], self.upv_cns, mo=True)

        # Visibilities -------------------------------------
        # fk
        fkvis_node = nod.createReverseNode(self.blend_att)

        for shp in self.fk0_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk2_ctl.getShapes():
            pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        if self.settings["ikTR"]:
            for shp in self.ikRot_ctl.getShapes():
                pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # Controls ROT order -----------------------------------
        att.setRotOrder(self.fk0_ctl, "XZY")
        att.setRotOrder(self.fk1_ctl, "XYZ")
        att.setRotOrder(self.fk2_ctl, "YZX")
        # att.setRotOrder(self.ik_ctl, "ZYX")
        att.setRotOrder(self.ik_ctl, "XYZ")

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc]
        node = aop.gear_ikfk2bone_op(out, self.root, self.ik_ref, self.upv_ctl,
                                     self.fk_ctl[0], self.fk_ctl[1],
                                     self.fk_ref, self.length0, self.length1,
                                     self.negate)

        if self.settings["ikTR"]:
            #connect the control inputs
            outEff_dm = node.listConnections(c=True)[-1][1]

            outEff_dm.attr("outputTranslate") >> self.ikRot_npo.attr(
                "translate")
            outEff_dm.attr("outputScale") >> self.ikRot_npo.attr("scale")
            dm_node = nod.createDecomposeMatrixNode(node.attr("outB"))
            dm_node.attr("outputRotate") >> self.ikRot_npo.attr("rotate")

            #rotation

            # intM_node = aop.gear_intmatrix_op(node.attr("outEff"), self.ikRot_ctl.attr("worldMatrix"), node.attr("blend"))
            # mulM_node = aop.gear_mulmatrix_op(intM_node.attr("output"), self.eff_loc.attr("parentInverseMatrix"))
            # dm_node = nod.createDecomposeMatrixNode(mulM_node.attr("output"))
            mulM_node = aop.gear_mulmatrix_op(
                self.ikRot_ctl.attr("worldMatrix"),
                self.eff_loc.attr("parentInverseMatrix"))
            intM_node = aop.gear_intmatrix_op(node.attr("outEff"),
                                              mulM_node.attr("output"),
                                              node.attr("blend"))
            dm_node = nod.createDecomposeMatrixNode(intM_node.attr("output"))
            dm_node.attr("outputRotate") >> self.eff_loc.attr("rotate")

        #scale: this fix the scalin popping issue
        intM_node = aop.gear_intmatrix_op(self.fk2_ctl.attr("worldMatrix"),
                                          self.ik_ctl.attr("worldMatrix"),
                                          node.attr("blend"))
        mulM_node = aop.gear_mulmatrix_op(
            intM_node.attr("output"), self.eff_loc.attr("parentInverseMatrix"))
        dm_node = nod.createDecomposeMatrixNode(mulM_node.attr("output"))
        dm_node.attr("outputScale") >> self.eff_loc.attr("scale")

        pm.connectAttr(self.blend_att, node + ".blend")
        pm.connectAttr(self.roll_att, node + ".roll")
        pm.connectAttr(self.scale_att, node + ".scaleA")
        pm.connectAttr(self.scale_att, node + ".scaleB")
        pm.connectAttr(self.maxstretch_att, node + ".maxstretch")
        pm.connectAttr(self.slide_att, node + ".slide")
        pm.connectAttr(self.softness_att, node + ".softness")
        pm.connectAttr(self.reverse_att, node + ".reverse")

        # Twist references ---------------------------------

        pm.pointConstraint(self.mid_ctl, self.tws1_npo, maintainOffset=False)
        pm.scaleConstraint(self.mid_ctl, self.tws1_npo, maintainOffset=False)
        pm.orientConstraint(self.mid_ctl, self.tws1_npo, maintainOffset=False)

        node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"),
                                     self.root.attr("worldInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputTranslate",
                       self.tws2_npo.attr("translate"))

        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        pm.connectAttr(dm_node + ".outputRotate", self.tws2_npo.attr("rotate"))

        node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"),
                                     self.tws2_rot.attr("parentInverseMatrix"))
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".output", dm_node + ".inputMatrix")
        att.setRotOrder(self.tws2_rot, "XYZ")
        pm.connectAttr(dm_node + ".outputRotate", self.tws2_rot + ".rotate")

        self.tws0_rot.setAttr("sx", .001)
        self.tws2_rot.setAttr("sx", .001)

        add_node = nod.createAddNode(self.roundness_att, .001)
        pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))

        pm.connectAttr(self.armpit_roll_att, self.tws0_rot + ".rotateX")

        #Roll Shoulder
        aop.splineIK(self.getName("rollRef"),
                     self.rollRef,
                     parent=self.root,
                     cParent=self.bone0)

        # Volume -------------------------------------------
        distA_node = nod.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = nod.createDistNode(self.tws1_loc, self.tws2_loc)
        add_node = nod.createAddNode(distA_node + ".distance",
                                     distB_node + ".distance")
        div_node = nod.createDivNode(add_node + ".output",
                                     self.root.attr("sx"))

        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix")

        div_node2 = nod.createDivNode(div_node + ".outputX",
                                      dm_node + ".outputScaleX")
        self.volDriver_att = div_node2 + ".outputX"

        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):

            if i < (self.settings["div0"] + 1):
                perc = i * .5 / (self.settings["div0"] + 1.0)
            elif i < (self.settings["div0"] + 2):
                perc = .49
            elif i < (self.settings["div0"] + 3):
                perc = .50
            elif i < (self.settings["div0"] + 4):
                perc = .51

            else:
                perc = .5 + (i - self.settings["div0"] -
                             3.0) * .5 / (self.settings["div1"] + 1.0)

            perc = max(.001, min(.990, perc))

            # Roll
            if self.negate:
                node = aop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot],
                    1 - perc, 40)
            else:
                node = aop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot],
                    perc, 40)

            pm.connectAttr(self.resample_att, node + ".resample")
            pm.connectAttr(self.absolute_att, node + ".absolute")

            # Squash n Stretch
            node = aop.gear_squashstretch2_op(div_cns, None,
                                              pm.getAttr(self.volDriver_att),
                                              "x")
            pm.connectAttr(self.volume_att, node + ".blend")
            pm.connectAttr(self.volDriver_att, node + ".driver")
            pm.connectAttr(self.st_att[i], node + ".stretch")
            pm.connectAttr(self.sq_att[i], node + ".squash")

        # match IK/FK ref
        pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True)
        pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True)

        return
示例#7
0
    def addOperators(self):

        # Visibilities -------------------------------------
        # fk
        fkvis_node = nod.createReverseNode(self.blend_att)

        for shp in self.fk0_ctl.getShapes():
            connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))
        for shp in self.fk2_ctl.getShapes():
            connectAttr(fkvis_node + ".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc]
        node = aop.gear_ikfk2bone_op(out, self.root, self.ik_ref, self.upv_ctl,
                                     self.fk_ctl[0], self.fk_ctl[1],
                                     self.fk_ref, self.length0, self.length1,
                                     self.negate)

        connectAttr(self.blend_att, node + ".blend")
        connectAttr(self.roll_att, node + ".roll")
        connectAttr(self.scale_att, node + ".scaleA")
        connectAttr(self.scale_att, node + ".scaleB")
        connectAttr(self.maxstretch_att, node + ".maxstretch")
        connectAttr(self.slide_att, node + ".slide")
        connectAttr(self.softness_att, node + ".softness")
        connectAttr(self.reverse_att, node + ".reverse")

        # Twist references ---------------------------------
        pointConstraint(self.root, self.tws0_loc, maintainOffset=True)
        aop.aimCns(self.tws0_loc, self.mid_ctl, self.n_sign + "xz", 2,
                   [0, 1, 0], self.root, False)

        pointConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False)
        scaleConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False)
        orientConstraint(self.mid_ctl, self.tws1_rot, maintainOffset=False)

        pointConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False)
        scaleConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False)
        orientConstraint(self.bone1, self.tws2_loc, maintainOffset=False)
        # orientConstraint(self.eff_loc, self.tws2_rot, maintainOffset=False)
        node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"),
                                     self.tws2_rot.attr("parentInverseMatrix"))
        dm_node = createNode("decomposeMatrix")
        connectAttr(node + ".output", dm_node + ".inputMatrix")
        connectAttr(dm_node + ".outputRotate", self.tws2_rot + ".rotate")
        # att.setRotOrder(self.tws2_rot, "YZX")

        self.tws0_loc.setAttr("sx", .001)
        self.tws2_loc.setAttr("sx", .001)

        add_node = nod.createAddNode(self.roundness_att, .001)
        connectAttr(add_node + ".output", self.tws1_rot.attr("sx"))

        # Volume -------------------------------------------
        distA_node = nod.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = nod.createDistNode(self.tws1_loc, self.tws2_loc)
        add_node = nod.createAddNode(distA_node + ".distance",
                                     distB_node + ".distance")
        div_node = nod.createDivNode(add_node + ".output",
                                     self.root.attr("sx"))
        self.volDriver_att = div_node + ".outputX"

        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):

            if i < (self.settings["div0"] + 1):
                perc = i * .5 / (self.settings["div0"] + 1.0)
            else:
                perc = .5 + (i - self.settings["div0"] -
                             1.0) * .5 / (self.settings["div1"] + 1.0)

            perc = max(.001, min(.999, perc))

            # Roll
            if self.negate:
                node = aop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot],
                    1 - perc)
            else:
                node = aop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot],
                    perc)

            connectAttr(self.resample_att, node + ".resample")
            connectAttr(self.absolute_att, node + ".absolute")

            # Squash n Stretch
            node = aop.gear_squashstretch2_op(div_cns, None,
                                              getAttr(self.volDriver_att), "x")
            connectAttr(self.volume_att, node + ".blend")
            connectAttr(self.volDriver_att, node + ".driver")
            connectAttr(self.st_att[i], node + ".stretch")
            connectAttr(self.sq_att[i], node + ".squash")

        return
示例#8
0
    def addOperators(self):

        # Visibilities -------------------------------------
        # fk
        fkvis_node = nod.createReverseNode(self.blend_att)
        
        for shp in self.fk0_ctl.getShapes():
            connectAttr(fkvis_node+".outputX", shp.attr("visibility"))
        for shp in self.fk1_ctl.getShapes():
            connectAttr(fkvis_node+".outputX", shp.attr("visibility"))
        for shp in self.fk2_ctl.getShapes():
            connectAttr(fkvis_node+".outputX", shp.attr("visibility"))

        # ik
        for shp in self.upv_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ikcns_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.ik_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))

        # IK Solver -----------------------------------------
        out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc]
        node = aop.gear_ikfk2bone_op(out, self.root, self.ik_ref, self.upv_ctl, self.fk_ctl[0], self.fk_ctl[1], self.fk_ref, self.length0, self.length1, self.negate)

        connectAttr(self.blend_att, node+".blend")
        connectAttr(self.roll_att, node+".roll")
        connectAttr(self.scale_att, node+".scaleA")
        connectAttr(self.scale_att, node+".scaleB")
        connectAttr(self.maxstretch_att, node+".maxstretch")
        connectAttr(self.slide_att, node+".slide")
        connectAttr(self.softness_att, node+".softness")
        connectAttr(self.reverse_att, node+".reverse")

        # Twist references ---------------------------------
        pointConstraint(self.root, self.tws0_loc, maintainOffset=True)
        aop.aimCns(self.tws0_loc, self.mid_ctl, self.n_sign+"xz", 2, [0,1,0], self.root, False)

        pointConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False)
        scaleConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False)
        orientConstraint(self.mid_ctl, self.tws1_rot, maintainOffset=False)

        pointConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False)
        scaleConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False)
        orientConstraint(self.bone1, self.tws2_loc, maintainOffset=False) 
        # orientConstraint(self.eff_loc, self.tws2_rot, maintainOffset=False)
        node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"), self.tws2_rot.attr("parentInverseMatrix"))
        dm_node = createNode("decomposeMatrix")
        connectAttr(node+".output", dm_node+".inputMatrix")
        connectAttr(dm_node+".outputRotate", self.tws2_rot+".rotate")
        # att.setRotOrder(self.tws2_rot, "YZX")

        self.tws0_loc.setAttr("sx", .001)
        self.tws2_loc.setAttr("sx", .001)

        add_node = nod.createAddNode(self.roundness_att, .001)
        connectAttr(add_node+".output", self.tws1_rot.attr("sx"))

        # Volume -------------------------------------------
        distA_node = nod.createDistNode(self.tws0_loc, self.tws1_loc)
        distB_node = nod.createDistNode(self.tws1_loc, self.tws2_loc)
        add_node = nod.createAddNode(distA_node+".distance", distB_node+".distance")
        div_node = nod.createDivNode(add_node+".output", self.root.attr("sx"))
        self.volDriver_att = div_node+".outputX"

        # Divisions ----------------------------------------
        # at 0 or 1 the division will follow exactly the rotation of the controler.. and we wont have this nice tangent + roll
        for i, div_cns in enumerate(self.div_cns):

            if i < (self.settings["div0"]+1):
                perc = i*.5 / (self.settings["div0"]+1.0)
            else:
                perc = .5 + (i-self.settings["div0"]-1.0)*.5 / (self.settings["div1"]+1.0)

            perc = max(.001, min(.999, perc))

            # Roll
            if self.negate:
                node = aop.gear_rollsplinekine_op(div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot], 1-perc)
            else:
                node = aop.gear_rollsplinekine_op(div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot], perc)

            connectAttr(self.resample_att, node+".resample")
            connectAttr(self.absolute_att, node+".absolute")

            # Squash n Stretch
            node = aop.gear_squashstretch2_op(div_cns, None, getAttr(self.volDriver_att), "x")
            connectAttr(self.volume_att, node+".blend")
            connectAttr(self.volDriver_att, node+".driver")
            connectAttr(self.st_att[i], node+".stretch")
            connectAttr(self.sq_att[i], node+".squash")

        return