Exemple #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.

        """

        # 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"))
        for shp in self.line_ref.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
Exemple #2
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.

        """
        # Visibilities -------------------------------------

        # ik
        if self.settings["useRollCtl"]:
            for shp in self.roll_ctl.getShapes():
                pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for bk_ctl in self.bk_ctl:
            for shp in bk_ctl.getShapes():
                pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.heel_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.tip_ctl.getShapes():
            pm.connectAttr(self.blend_att, shp.attr("visibility"))

        # Roll / Bank --------------------------------------
        if self.settings["useRollCtl"]:  # Using the controler
            self.roll_att = self.roll_ctl.attr("rz")
            self.bank_att = self.roll_ctl.attr("rx")

        clamp_node = node.createClampNode(
            [self.roll_att, self.bank_att, self.bank_att],
            [0, -180, 0],
            [180, 0, 180])

        inAdd_nod = node.createAddNode(
            clamp_node + ".outputB",
            pm.getAttr(self.in_piv.attr("rx")) * self.n_factor)

        pm.connectAttr(clamp_node + ".outputR", self.heel_loc.attr("rz"))
        pm.connectAttr(clamp_node + ".outputG", self.out_piv.attr("rx"))
        pm.connectAttr(inAdd_nod + ".output", self.in_piv.attr("rx"))

        # Reverse Controler offset -------------------------
        angle_outputs = node.createAddNodeMulti(self.angles_att)
        for i, bk_loc in enumerate(reversed(self.bk_loc)):

            if i == 0:  # First
                input = self.roll_att
                min_input = self.angles_att[i]

            elif i == len(self.angles_att):  # Last
                sub_nod = node.createSubNode(self.roll_att,
                                             angle_outputs[i - 1])
                input = sub_nod + ".output"
                min_input = -360

            else:  # Others
                sub_nod = node.createSubNode(self.roll_att,
                                             angle_outputs[i - 1])
                input = sub_nod + ".output"
                min_input = self.angles_att[i]

            clamp_node = node.createClampNode(input, min_input, 0)

            add_node = node.createAddNode(clamp_node + ".outputR",
                                          bk_loc.getAttr("rz"))

            pm.connectAttr(add_node + ".output", bk_loc.attr("rz"))

        # Reverse compensation -----------------------------
        for i, fk_loc in enumerate(self.fk_loc):
            bk_ctl = self.bk_ctl[-i - 1]
            bk_loc = self.bk_loc[-i - 1]
            fk_ctl = self.fk_ctl[i]

            # Inverse Rotorder
            applyop.gear_inverseRotorder_op(bk_loc, fk_ctl)
            pm.connectAttr(fk_ctl.attr("ro"), fk_loc.attr("ro"))
            attribute.lockAttribute(bk_loc, "ro")

            # Compensate the backward rotation
            # ik
            # addx_node = node.createAddNode(bk_loc.attr("rx"), bk_loc.attr("rx"))
            # addy_node = node.createAddNode(bk_loc.attr("ry"), bk_loc.attr("ry"))
            # addz_node = node.createAddNode(bk_loc.attr("rz"), bk_loc.attr("rz"))
            addz_node = node.createAddNode(
                bk_loc.attr("rz"), -bk_loc.getAttr("rz") - fk_loc.getAttr("rz"))

            neg_node = node.createMulNode([bk_loc.attr("rx"),
                                           bk_loc.attr("ry"),
                                           addz_node + ".output"],
                                          [-1, -1, -1])
            ik_outputs = [neg_node + ".outputX",
                          neg_node + ".outputY",
                          neg_node + ".outputZ"]

            # fk
            fk_outputs = [0, 0, fk_loc.getAttr("rz")]

            # blend
            blend_node = node.createBlendNode(ik_outputs,
                                              fk_outputs,
                                              self.blend_att)
            pm.connectAttr(blend_node + ".output", fk_loc.attr("rotate"))

        return
Exemple #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.

        """

        # 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"))
        for shp in self.line_ref.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.connectAttr(self.mid_ctl.scaleX, self.tws1_loc.scaleX)
        pm.connectAttr(self.mid_ctl.scaleX, self.tws1B_loc.scaleX)
        applyop.oriCns(self.mid_ctl, self.tws1_rot, maintainOffset=False)
        applyop.oriCns(self.mid_ctl, self.tws1B_rot, maintainOffset=False)
        if self.negate:
            axis = "xz"
            axisb = "-xz"
        else:
            axis = "-xz"
            axisb = "xz"
        applyop.aimCns(self.tws1_loc,
                       self.root_ctl,
                       axis=axis,
                       wupType=4,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        applyop.aimCns(self.tws1B_loc,
                       self.eff_loc,
                       axis=axisb,
                       wupType=4,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        pm.pointConstraint(self.thick_ctl,
                           self.tws1B_loc,
                           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"))
        pm.connectAttr(add_node + ".output", self.tws1B_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"

        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
        b_twist = False
        for i, div_cns in enumerate(self.div_cns):
            subdiv = False
            if self.settings["supportJoints"]:
                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):
                    b_twist = True
                    perc = .51
                    subdiv = 45

                else:
                    perc = (.5 + (i - self.settings["div0"] - 3.0) * .5 /
                            (self.settings["div1"] + 1.0))
            else:
                subdiv = 40
                if i < (self.settings["div0"] + 1):
                    perc = i * .5 / (self.settings["div0"] + 1.0)
                elif i < (self.settings["div0"] + 2):
                    b_twist = True
                    perc = .501
                else:
                    perc = .5 + \
                        (i - self.settings["div0"] - 1.0) * .5 / \
                        (self.settings["div1"] + 1.0)

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

            # mid twist distribution
            if b_twist:
                mid_twist = self.tws1B_rot
            else:
                mid_twist = self.tws1_rot

            # Roll
            if self.negate:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, mid_twist, self.tws0_rot],
                    1.0 - perc, subdiv)
            else:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, mid_twist, 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)

        # connect_reader
        pm.parentConstraint(self.bone0, self.readerA, mo=True)
        pm.parentConstraint(self.bone1, self.readerB, mo=True)

        # connect auto thickness
        if self.negate and not self.settings["mirrorMid"]:
            d_val = -180 / self.length1
        else:
            d_val = 180 / self.length1
        div_thick_node = node.createDivNode(self.knee_thickness_att, d_val)
        node.createMulNode(div_thick_node.outputX, self.readerB.rx,
                           self.thick_lvl.tx)

        return
Exemple #4
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"))
        for shp in self.line_ref.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"))
        for shp in self.roll_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)

        # NOTE: Ideally we should not change hierarchy or move object after
        # object generation method. But is much easier this way since every
        # part is in the final and correct position
        # after the  ctrn_loc is in the correct position with the ikfk2bone op

        # point constrain tip reference
        pm.pointConstraint(self.ik_ctl, self.tip_ref, mo=False)

        # interpolate transform  mid point locator
        int_matrix = applyop.gear_intmatrix_op(
            self.armChainUpvRef[0].attr("worldMatrix"),
            self.tip_ref.attr("worldMatrix"), .5)
        applyop.gear_mulmatrix_op(
            int_matrix.attr("output"),
            self.interpolate_lvl.attr("parentInverseMatrix[0]"),
            self.interpolate_lvl)

        # match roll ctl npo to ctrn_loc current transform (so correct orient)
        transform.matchWorldTransform(self.ctrn_loc, self.roll_ctl_npo)

        # match roll ctl npo to interpolate transform current position
        pos = self.interpolate_lvl.getTranslation(space="world")
        self.roll_ctl_npo.setTranslation(pos, space="world")

        # parent constraint roll control npo to interpolate trans
        pm.parentConstraint(self.interpolate_lvl, self.roll_ctl_npo, mo=True)

        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
            rollMulVal = 1
        else:
            mulVal = 1
            rollMulVal = -1
        roll_m_node = node.createMulNode(self.roll_att, mulVal)
        roll_m_node2 = node.createMulNode(self.roll_ctl.attr("rx"), rollMulVal)
        node.createPlusMinusAverage1D(
            [roll_m_node.outputX, roll_m_node2.outputX],
            operation=1,
            output=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.connectAttr(self.mid_ctl.scaleX, self.tws1B_loc.scaleX)
        pm.orientConstraint(self.mid_ctl_twst_ref,
                            self.tws1_npo,
                            maintainOffset=False)
        applyop.oriCns(self.mid_ctl, self.tws1_rot, maintainOffset=False)
        applyop.oriCns(self.mid_ctl, self.tws1B_rot, maintainOffset=False)

        if self.negate:
            axis = "xz"
            axisb = "-xz"
        else:
            axis = "-xz"
            axisb = "xz"
        applyop.aimCns(self.tws1_loc,
                       self.root,
                       axis=axis,
                       wupType=4,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        applyop.aimCns(self.tws1B_loc,
                       self.eff_loc,
                       axis=axisb,
                       wupType=4,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        pm.pointConstraint(self.thick_ctl,
                           self.tws1B_loc,
                           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(add_node + ".output", self.tws1B_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
        b_twist = False
        for i, div_cns in enumerate(self.div_cns):

            if self.settings["supportJoints"]:
                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):
                    b_twist = True
                    perc = .51

                else:
                    perc = .5 + \
                        (i - self.settings["div0"] - 3.0) * .5 / \
                        (self.settings["div1"] + 1.0)
            else:
                if i < (self.settings["div0"] + 1):
                    perc = i * .5 / (self.settings["div0"] + 1.0)
                elif i < (self.settings["div0"] + 2):
                    b_twist = True
                    perc = .501
                else:
                    perc = .5 + \
                        (i - self.settings["div0"] - 1.0) * .5 / \
                        (self.settings["div1"] + 1.0)

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

            # mid twist distribution
            if b_twist:
                mid_twist = self.tws1B_rot
            else:
                mid_twist = self.tws1_rot

            # Roll
            if self.negate:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws2_rot, mid_twist, self.tws0_rot],
                    1.0 - perc, 40)
            else:
                o_node = applyop.gear_rollsplinekine_op(
                    div_cns, [self.tws0_rot, mid_twist, 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)

        # connect_reader
        pm.parentConstraint(self.bone0, self.readerA, mo=True)
        pm.parentConstraint(self.bone1, self.readerB, mo=True)

        # connect auto thickness
        if self.negate and not self.settings["mirrorMid"]:
            d_val = 180 / self.length1
        else:
            d_val = -180 / self.length1
        div_thick_node = node.createDivNode(self.elbow_thickness_att, d_val)
        node.createMulNode(div_thick_node.outputX, self.readerB.ry,
                           self.thick_lvl.tx)

        return
Exemple #5
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("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)
        try:
            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"))
            for shp in self.line_ref.getShapes():
                pm.connectAttr(self.blend_att, shp.attr("visibility"))
        except RuntimeError:
            pm.displayInfo("Visibility already connecte")

        # 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.connectAttr(self.mid_ctl.scaleX, self.tws1_loc.scaleX)
        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)

        if self.settings["div0"]:
            ori_ref = self.rollRef[0]
        else:
            ori_ref = self.bone0

        applyop.oriCns(ori_ref, self.tws0_loc, maintainOffset=True)

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

        add_node = node.createAddNode(self.roundness_att, .0)
        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

        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):
            subdiv = 40
            if i < (self.settings["div0"] + 1):
                perc = i * .5 / (self.settings["div0"] + 1.0)
            elif i < (self.settings["div0"] + 2):
                perc = .501
            else:
                perc = .5 + \
                    (i - self.settings["div0"] - 1.0) * .5 / \
                    (self.settings["div1"] + 1.0)

            perc = max(.0001, 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.0 - 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)

        # 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
Exemple #6
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.

        """

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

            for fk_ctl in self.fk_ctl:
                for shp in fk_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"))

        # FK Chain -----------------------------------------
        if self.isFk:
            for off, ref in zip(self.fk_off[1:], self.fk_ref):
                applyop.gear_mulmatrix_op(ref.worldMatrix,
                                          off.parentInverseMatrix, off, "rt")
        # IK Chain -----------------------------------------
        if self.isIk:
            self.ikh = primitive.addIkHandle(self.root, self.getName("ikh"),
                                             self.chain)
            self.ikh.attr("visibility").set(False)

            # Constraint and up vector
            pm.pointConstraint(self.ik_ctl, self.ikh, maintainOffset=False)
            pm.poleVectorConstraint(self.upv_ctl, self.ikh)

            # TwistTest
            o_list = [round(elem, 4) for elem
                      in transform.getTranslation(self.chain[1])] \
                != [round(elem, 4) for elem in self.guide.apos[1]]

            if o_list:
                add_nodeTwist = node.createAddNode(180.0, self.roll_att)
                pm.connectAttr(add_nodeTwist + ".output",
                               self.ikh.attr("twist"))
            else:
                pm.connectAttr(self.roll_att, self.ikh.attr("twist"))

        # Chain of deformers -------------------------------
        if self.settings["mode"] == 0:  # fk only
            # Loop until the last one and connect aim constraints from index+1
            for i, loc in enumerate(self.loc[0:-1]):
                pm.pointConstraint(self.fk_ctl[i], loc, maintainOffset=False)
                pm.connectAttr(self.fk_ctl[i] + ".scale", loc + ".scale")
                pm.aimConstraint(
                    self.fk_ctl[i + 1],
                    loc,
                    maintainOffset=False,
                    aimVector=(1, 0, 0),
                    upVector=(0, 1, 0),
                    worldUpType='none',
                )
                oRoot = rigbits.addNPO(loc)[0]
                pm.parentConstraint(self.fk_ctl[i], oRoot, mo=True)
                attribute.lockAttribute(oRoot)
            # Then connect the last in the chain as a parent constraint
            pm.parentConstraint(self.fk_ctl[-1],
                                self.loc[-1],
                                maintainOffset=False)
            pm.connectAttr(self.fk_ctl[-1] + ".scale", self.loc[-1] + ".scale")
Exemple #7
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("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"))
        for shp in self.line_ref.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.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")

        # Twist references ---------------------------------
        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"))

        # spline IK for  twist jnts
        self.ikhUpLegTwist, self.uplegTwistCrv = applyop.splineIK(
            self.getName("uplegTwist"),
            self.uplegTwistChain,
            parent=self.root,
            cParent=self.bone0)

        self.ikhLowLegTwist, self.lowlegTwistCrv = applyop.splineIK(
            self.getName("lowlegTwist"),
            self.lowlegTwistChain,
            parent=self.root,
            cParent=self.bone1)

        # references
        self.ikhUpLegRef, self.tmpCrv = applyop.splineIK(
            self.getName("uplegRollRef"),
            self.uplegRollRef,
            parent=self.root,
            cParent=self.bone0)

        self.ikhLowLegRef, self.tmpCrv = applyop.splineIK(
            self.getName("lowlegRollRef"),
            self.lowlegRollRef,
            parent=self.root,
            cParent=self.eff_loc)

        self.ikhAuxTwist, self.tmpCrv = applyop.splineIK(
            self.getName("auxTwist"),
            self.auxTwistChain,
            parent=self.root,
            cParent=self.eff_loc)

        # setting connexions for ikhUpLegTwist
        self.ikhUpLegTwist.attr("dTwistControlEnable").set(True)
        self.ikhUpLegTwist.attr("dWorldUpType").set(4)
        self.ikhUpLegTwist.attr("dWorldUpAxis").set(3)
        self.ikhUpLegTwist.attr("dWorldUpVectorZ").set(1.0)
        self.ikhUpLegTwist.attr("dWorldUpVectorY").set(0.0)
        self.ikhUpLegTwist.attr("dWorldUpVectorEndZ").set(1.0)
        self.ikhUpLegTwist.attr("dWorldUpVectorEndY").set(0.0)
        pm.connectAttr(self.uplegRollRef[0].attr("worldMatrix[0]"),
                       self.ikhUpLegTwist.attr("dWorldUpMatrix"))
        pm.connectAttr(self.bone0.attr("worldMatrix[0]"),
                       self.ikhUpLegTwist.attr("dWorldUpMatrixEnd"))

        # setting connexions for ikhAuxTwist
        self.ikhAuxTwist.attr("dTwistControlEnable").set(True)
        self.ikhAuxTwist.attr("dWorldUpType").set(4)
        self.ikhAuxTwist.attr("dWorldUpAxis").set(3)
        self.ikhAuxTwist.attr("dWorldUpVectorZ").set(1.0)
        self.ikhAuxTwist.attr("dWorldUpVectorY").set(0.0)
        self.ikhAuxTwist.attr("dWorldUpVectorEndZ").set(1.0)
        self.ikhAuxTwist.attr("dWorldUpVectorEndY").set(0.0)
        pm.connectAttr(self.lowlegRollRef[0].attr("worldMatrix[0]"),
                       self.ikhAuxTwist.attr("dWorldUpMatrix"))
        pm.connectAttr(self.tws_ref.attr("worldMatrix[0]"),
                       self.ikhAuxTwist.attr("dWorldUpMatrixEnd"))
        pm.connectAttr(self.auxTwistChain[1].attr("rx"),
                       self.ikhLowLegTwist.attr("twist"))

        pm.parentConstraint(self.bone1, self.aux_npo, maintainOffset=True)

        # scale arm length for twist chain (not the squash and stretch)
        arclen_node = pm.arclen(self.uplegTwistCrv, ch=True)
        alAttrUpLeg = arclen_node.attr("arcLength")
        muldiv_nodeArm = pm.createNode("multiplyDivide")
        pm.connectAttr(arclen_node.attr("arcLength"),
                       muldiv_nodeArm.attr("input1X"))
        muldiv_nodeArm.attr("input2X").set(alAttrUpLeg.get())
        muldiv_nodeArm.attr("operation").set(2)
        for jnt in self.uplegTwistChain:
            pm.connectAttr(muldiv_nodeArm.attr("outputX"), jnt.attr("sx"))

        # scale forearm length for twist chain (not the squash and stretch)
        arclen_node = pm.arclen(self.lowlegTwistCrv, ch=True)
        alAttrLowLeg = arclen_node.attr("arcLength")
        muldiv_nodeLowLeg = pm.createNode("multiplyDivide")
        pm.connectAttr(arclen_node.attr("arcLength"),
                       muldiv_nodeLowLeg.attr("input1X"))
        muldiv_nodeLowLeg.attr("input2X").set(alAttrLowLeg.get())
        muldiv_nodeLowLeg.attr("operation").set(2)
        for jnt in self.lowlegTwistChain:
            pm.connectAttr(muldiv_nodeLowLeg.attr("outputX"), jnt.attr("sx"))

        # scale compensation for the first  twist join
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(self.root.attr("worldMatrix[0]"),
                       dm_node.attr("inputMatrix"))
        pm.connectAttr(dm_node.attr("outputScale"),
                       self.uplegTwistChain[0].attr("inverseScale"))
        pm.connectAttr(dm_node.attr("outputScale"),
                       self.lowlegTwistChain[0].attr("inverseScale"))

        # tangent controls
        muldiv_node = pm.createNode("multiplyDivide")
        muldiv_node.attr("input2X").set(-1)
        pm.connectAttr(self.tws1A_npo.attr("rz"), muldiv_node.attr("input1X"))
        muldiv_nodeBias = pm.createNode("multiplyDivide")
        pm.connectAttr(muldiv_node.attr("outputX"),
                       muldiv_nodeBias.attr("input1X"))
        pm.connectAttr(self.roundness_att, muldiv_nodeBias.attr("input2X"))
        pm.connectAttr(muldiv_nodeBias.attr("outputX"),
                       self.tws1A_loc.attr("rz"))
        if self.negate:
            axis = "xz"
        else:
            axis = "-xz"
        applyop.aimCns(self.tws1A_npo,
                       self.tws0_loc,
                       axis=axis,
                       wupType=2,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        applyop.aimCns(self.lowlegTangentB_loc,
                       self.lowlegTangentA_npo,
                       axis=axis,
                       wupType=2,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        pm.pointConstraint(self.eff_loc, self.lowlegTangentB_loc)

        muldiv_node = pm.createNode("multiplyDivide")
        muldiv_node.attr("input2X").set(-1)
        pm.connectAttr(self.tws1B_npo.attr("rz"), muldiv_node.attr("input1X"))
        muldiv_nodeBias = pm.createNode("multiplyDivide")
        pm.connectAttr(muldiv_node.attr("outputX"),
                       muldiv_nodeBias.attr("input1X"))
        pm.connectAttr(self.roundness_att, muldiv_nodeBias.attr("input2X"))
        pm.connectAttr(muldiv_nodeBias.attr("outputX"),
                       self.tws1B_loc.attr("rz"))
        if self.negate:
            axis = "-xz"
        else:
            axis = "xz"
        applyop.aimCns(self.tws1B_npo,
                       self.tws2_loc,
                       axis=axis,
                       wupType=2,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        applyop.aimCns(self.uplegTangentA_loc,
                       self.uplegTangentB_npo,
                       axis=axis,
                       wupType=2,
                       wupVector=[0, 0, 1],
                       wupObject=self.mid_ctl,
                       maintainOffset=False)

        # 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"

        # connecting tangent scaele compensation after volume to
        # avoid duplicate some nodes
        distA_node = node.createDistNode(self.tws0_loc, self.mid_ctl)
        distB_node = node.createDistNode(self.mid_ctl, self.tws2_loc)

        div_nodeUpLeg = node.createDivNode(distA_node + ".distance",
                                           dm_node.attr("outputScaleX"))

        div_node2 = node.createDivNode(div_nodeUpLeg + ".outputX",
                                       distA_node.attr("distance").get())

        pm.connectAttr(div_node2.attr("outputX"), self.tws1A_loc.attr("sx"))

        pm.connectAttr(div_node2.attr("outputX"),
                       self.uplegTangentA_loc.attr("sx"))

        div_nodeLowLeg = node.createDivNode(distB_node + ".distance",
                                            dm_node.attr("outputScaleX"))
        div_node2 = node.createDivNode(div_nodeLowLeg + ".outputX",
                                       distB_node.attr("distance").get())

        pm.connectAttr(div_node2.attr("outputX"), self.tws1B_loc.attr("sx"))
        pm.connectAttr(div_node2.attr("outputX"),
                       self.lowlegTangentB_loc.attr("sx"))

        # conection curve
        cnts = [
            self.uplegTangentA_loc, self.uplegTangentA_ctl,
            self.uplegTangentB_ctl, self.kneeTangent_ctl
        ]
        applyop.gear_curvecns_op(self.uplegTwistCrv, cnts)

        cnts = [
            self.kneeTangent_ctl, self.lowlegTangentA_ctl,
            self.lowlegTangentB_ctl, self.lowlegTangentB_loc
        ]
        applyop.gear_curvecns_op(self.lowlegTwistCrv, cnts)

        # Tangent controls vis
        for shp in self.uplegTangentA_ctl.getShapes():
            pm.connectAttr(self.tangentVis_att, shp.attr("visibility"))
        for shp in self.uplegTangentB_ctl.getShapes():
            pm.connectAttr(self.tangentVis_att, shp.attr("visibility"))
        for shp in self.lowlegTangentA_ctl.getShapes():
            pm.connectAttr(self.tangentVis_att, shp.attr("visibility"))
        for shp in self.lowlegTangentB_ctl.getShapes():
            pm.connectAttr(self.tangentVis_att, shp.attr("visibility"))
        for shp in self.kneeTangent_ctl.getShapes():
            pm.connectAttr(self.tangentVis_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"] + 2):
                mulmat_node = applyop.gear_mulmatrix_op(
                    self.uplegTwistChain[i] + ".worldMatrix",
                    div_cns + ".parentInverseMatrix")
                lastUpLegDiv = div_cns
            else:
                o_node = self.lowlegTwistChain[i - (self.settings["div0"] + 2)]
                mulmat_node = applyop.gear_mulmatrix_op(
                    o_node + ".worldMatrix", div_cns + ".parentInverseMatrix")
                lastLowLegDiv = div_cns
            dm_node = node.createDecomposeMatrixNode(mulmat_node + ".output")
            pm.connectAttr(dm_node + ".outputTranslate", div_cns + ".t")
            pm.connectAttr(dm_node + ".outputRotate", div_cns + ".r")

            # 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")

        # force translation for last loc arm and foreamr
        applyop.gear_mulmatrix_op(self.kneeTangent_ctl.worldMatrix,
                                  lastUpLegDiv.parentInverseMatrix,
                                  lastUpLegDiv, "t")
        applyop.gear_mulmatrix_op(self.tws2_loc.worldMatrix,
                                  lastLowLegDiv.parentInverseMatrix,
                                  lastLowLegDiv, "t")

        # 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
    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 -------------------------------------
        if self.isFkIk:
            # fk
            fkvis_node = node.createReverseNode(self.blend_att)

            for fk_ctl in self.fk_ctl:
                for shp in fk_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"))

        # FK Chain -----------------------------------------
        if self.isFk:
            for off, ref in zip(self.fk_off[1:], self.fk_ref):
                applyop.gear_mulmatrix_op(
                    ref.worldMatrix, off.parentInverseMatrix, off, "rt")
        # IK Chain -----------------------------------------
        if self.isIk:
            self.ikh = primitive.addIkHandle(
                self.root, self.getName("ikh"), self.chain)
            self.ikh.attr("visibility").set(False)

            # Constraint and up vector
            pm.pointConstraint(self.ik_ctl, self.ikh, maintainOffset=False)
            pm.poleVectorConstraint(self.upv_ctl, self.ikh)

            # TwistTest
            o_list = [round(elem, 4) for elem
                      in transform.getTranslation(self.chain[1])] \
                != [round(elem, 4) for elem in self.guide.apos[1]]

            if o_list:
                add_nodeTwist = node.createAddNode(180.0, self.roll_att)
                pm.connectAttr(add_nodeTwist + ".output",
                               self.ikh.attr("twist"))
            else:
                pm.connectAttr(self.roll_att, self.ikh.attr("twist"))

        # Chain of deformers -------------------------------
        for i, loc in enumerate(self.loc):

            if self.settings["mode"] == 0:  # fk only
                pm.parentConstraint(self.fk_ctl[i], loc, maintainOffset=False)
                pm.connectAttr(self.fk_ctl[i] + ".scale", loc + ".scale")

            elif self.settings["mode"] == 1:  # ik only
                pm.parentConstraint(self.chain[i], loc, maintainOffset=False)

            elif self.settings["mode"] == 2:  # fk/ik

                rev_node = node.createReverseNode(self.blend_att)

                # orientation
                cns = pm.parentConstraint(
                    self.fk_ctl[i], self.chain[i], loc, maintainOffset=False)
                cns.interpType.set(0)
                weight_att = pm.parentConstraint(
                    cns, query=True, weightAliasList=True)
                pm.connectAttr(rev_node + ".outputX", weight_att[0])
                pm.connectAttr(self.blend_att, weight_att[1])

                # scaling
                blend_node = pm.createNode("blendColors")
                pm.connectAttr(self.chain[i].attr("scale"),
                               blend_node + ".color1")
                pm.connectAttr(self.fk_ctl[i].attr("scale"),
                               blend_node + ".color2")
                pm.connectAttr(self.blend_att, blend_node + ".blender")
                pm.connectAttr(blend_node + ".output", loc + ".scale")
    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"))
        for shp in self.line_ref.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 self.settings["supportJoints"]:
                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)
            else:
                if i < (self.settings["div0"] + 1):
                    perc = i * .5 / (self.settings["div0"] + 1.0)
                elif i < (self.settings["div0"] + 2):
                    perc = .501
                else:
                    perc = .5 + \
                        (i - self.settings["div0"] - 1.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.0 - 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
Exemple #10
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, self.upv_ctl, self.line_ref]:
            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")

        # match IK/FK ref
        pm.parentConstraint(self.legBones[0], self.match_fk0_off, mo=True)
        pm.parentConstraint(self.legBones[1], self.match_fk1_off, mo=True)
        pm.parentConstraint(self.legBones[2], self.match_fk2_off, mo=True)

        return