Example #1
0
def _createSoftModTweak(baseCtl, tweakCtl, name, targets):

    sm = pm.softMod(targets, wn=[tweakCtl, tweakCtl])
    pm.rename(sm[0], "{}_softMod".format(name))

    # disconnect default connection
    plugs = sm[0].softModXforms.listConnections(p=True)
    for p in plugs:
        pm.disconnectAttr(p, sm[0].softModXforms)
        pm.delete(p.node())

    dm_node = node.createDecomposeMatrixNode(baseCtl.worldMatrix[0])
    pm.connectAttr(dm_node.outputTranslate, sm[0].falloffCenter)
    mul_node = node.createMulNode(dm_node.outputScaleX,
                                  tweakCtl.attr("falloff"))
    pm.connectAttr(mul_node.outputX, sm[0].falloffRadius)
    mulMatrix_node = applyop.gear_mulmatrix_op(tweakCtl.worldMatrix[0],
                                               tweakCtl.parentInverseMatrix[0])
    pm.connectAttr(mulMatrix_node.output, sm[0].weightedMatrix)
    pm.connectAttr(baseCtl.worldInverseMatrix[0], sm[0].postMatrix)
    pm.connectAttr(baseCtl.worldMatrix[0], sm[0].preMatrix)
    attribute.addAttribute(sm[0], "_isSoftTweak", "bool", False, keyable=False)

    sm[0].addAttr("ctlRoot", at='message', m=False)
    sm[0].addAttr("ctlBase", at='message', m=False)
    sm[0].addAttr("ctlTweak", at='message', m=False)
    pm.connectAttr(baseCtl.getParent().attr("message"), sm[0].attr("ctlRoot"))
    pm.connectAttr(baseCtl.attr("message"), sm[0].attr("ctlBase"))
    pm.connectAttr(tweakCtl.attr("message"), sm[0].attr("ctlTweak"))

    return sm[0]
Example #2
0
def inverseTranslateParent(obj):
    """Invert the parent transformation

    Args:
        obj (dagNode): The source dagNode to inver parent transformation.
    """
    if not isinstance(obj, list):
        obj = [obj]
    for x in obj:
        node.createMulNode(
            [x.attr("tx"), x.attr("ty"),
             x.attr("tz")], [-1, -1, -1], [
                 x.getParent().attr("tx"),
                 x.getParent().attr("ty"),
                 x.getParent().attr("tz")
             ])
Example #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.

        """
        pairs = [[self.top_ctl, self.bottom_npo, 1, 2],
                 [self.bottom_ctl, self.bottom_pivot, 2, 1],
                 [self.ext_ctl, self.int_npo, 3, 4],
                 [self.int_ctl, self.int_pivot, 4, 3]]

        for pair in pairs:
            d = vector.getDistance(self.guide.apos[pair[2]],
                                   self.guide.apos[pair[3]])

            sum_node = node.createPlusMinusAverage1D([d, pair[0].ty])
            mul_node = node.createMulNode(pair[0].ty, self.volume_att)
            sum2_node = node.createPlusMinusAverage1D([d, mul_node.outputX])
            mul2_node = node.createDivNode(
                [sum2_node.output1D, sum_node.output1D, sum2_node.output1D],
                [d, d, d])

            sum3D_node = pm.createNode("plusMinusAverage")
            sum3D_node.attr("operation").set(2)
            sum3D_node.input3D[0].input3Dx.set(2)
            sum3D_node.input3D[0].input3Dz.set(2)
            mul2_node.outputX >> sum3D_node.input3D[1].input3Dx
            mul2_node.outputZ >> sum3D_node.input3D[1].input3Dz
            sum3D_node.output3D.output3Dx >> pair[1].sx
            mul2_node.outputY >> pair[1].sy
            sum3D_node.output3D.output3Dx >> pair[1].sz
Example #4
0
def connectInvertSRT(source, target, srt="srt", axis="xyz"):
    """Connect the locat transformations with inverted values.

    Args:
        source (dagNode): The source driver dagNode
        target (dagNode): The target driven dagNode
        srt (string, optional): String value for the scale(s), rotate(r), translation(t). Default
            value is "srt". Posible values "s", "r", "t" or any combination
        axis (string, optional):  String value for the axis. Default
            value is "xyz". Posible values "x", "y", "z" or any combination
    """
    for t in srt:
        soureList = []
        invList = []
        targetList = []
        for a in axis:
            soureList.append(source.attr(t+a))
            invList.append(-1)
            targetList.append(target.attr(t+a))

        if soureList:
            nod.createMulNode(soureList, invList, targetList)
Example #5
0
    def addOperators(self):
        pairs = [[self.top_ctl, self.bottom_npo, 1, 2],
                 [self.bottom_ctl, self.bottom_pivot, 2, 1],
                 [self.ext_ctl, self.int_npo, 3, 4],
                 [self.int_ctl, self.int_pivot, 4, 3]]

        for pair in pairs:
            d = vec.getDistance(self.guide.apos[pair[2]],
                                self.guide.apos[pair[3]])
            sum_node = nod.createPlusMinusAverage1D([d, pair[0].ty])
            mul_node = nod.createMulNode(pair[0].ty, self.volume_att)
            sum2_node = nod.createPlusMinusAverage1D([d, mul_node.outputX])
            mul2_node = nod.createDivNode(
                [sum2_node.output1D, sum_node.output1D, sum2_node.output1D],
                [d, d, d])
            sum3D_node = pm.createNode("plusMinusAverage")
            sum3D_node.attr("operation").set(2)
            sum3D_node.input3D[0].input3Dx.set(2)
            sum3D_node.input3D[0].input3Dz.set(2)
            mul2_node.outputX >> sum3D_node.input3D[1].input3Dx
            mul2_node.outputZ >> sum3D_node.input3D[1].input3Dz
            sum3D_node.output3D.output3Dx >> pair[1].sx
            mul2_node.outputY >> pair[1].sy
            sum3D_node.output3D.output3Dx >> pair[1].sz
Example #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 -------------------------------------
        # fk
        fkvis_node = node.createReverseNode(self.blend_att)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        """

        # Auto bend ----------------------------
        if self.settings["autoBend"]:
            mul_node = node.createMulNode(
                [self.autoBendChain[0].ry, self.autoBendChain[0].rz],
                [self.sideBend_att, self.frontBend_att])

            mul_node.outputX >> self.ik1autoRot_lvl.rz
            mul_node.outputY >> self.ik1autoRot_lvl.rx

            self.ikHandleAutoBend = primitive.addIkHandle(
                self.autoBend_ctl,
                self.getName("ikHandleAutoBend"),
                self.autoBendChain, "ikSCsolver")

        # Tangent position ---------------------------------
        # common part
        d = vector.getDistance(self.guide.apos[0], self.guide.apos[1])
        dist_node = node.createDistNode(self.ik0_ctl, self.ik1_ctl)

        rootWorld_node = node.createDecomposeMatrixNode(
            self.root.attr("worldMatrix"))

        div_node = node.createDivNode(dist_node + ".distance",
                                      rootWorld_node + ".outputScaleX")

        div_node = node.createDivNode(div_node + ".outputX", d)

        # tan0
        mul_node = node.createMulNode(self.tan0_att,
                                      self.tan0_npo.getAttr("ty"))

        res_node = node.createMulNode(mul_node + ".outputX",
                                      div_node + ".outputX")

        pm.connectAttr(res_node + ".outputX",
                       self.tan0_npo.attr("ty"))

        # tan1
        mul_node = node.createMulNode(self.tan1_att,
                                      self.tan1_npo.getAttr("ty"))

        res_node = node.createMulNode(mul_node + ".outputX",
                                      div_node + ".outputX")

        pm.connectAttr(res_node + ".outputX", self.tan1_npo.attr("ty"))

        # Tangent Mid --------------------------------------
        if self.settings["centralTangent"]:
            tanIntMat = applyop.gear_intmatrix_op(
                self.tan0_npo.attr("worldMatrix"),
                self.tan1_npo.attr("worldMatrix"),
                .5)

            applyop.gear_mulmatrix_op(
                tanIntMat.attr("output"),
                self.tan_npo.attr("parentInverseMatrix[0]"),
                self.tan_npo)

            pm.connectAttr(self.tan_ctl.attr("translate"),
                           self.tan0_off.attr("translate"))

            pm.connectAttr(self.tan_ctl.attr("translate"),
                           self.tan1_off.attr("translate"))

        # Curves -------------------------------------------
        op = applyop.gear_curveslide2_op(
            self.slv_crv, self.mst_crv, 0, 1.5, .5, .5)

        pm.connectAttr(self.position_att, op + ".position")
        pm.connectAttr(self.maxstretch_att, op + ".maxstretch")
        pm.connectAttr(self.maxsquash_att, op + ".maxsquash")
        pm.connectAttr(self.softness_att, op + ".softness")

        # Volume driver ------------------------------------
        crv_node = node.createCurveInfoNode(self.slv_crv)

        # Division -----------------------------------------
        for i in range(self.settings["division"]):

            # References
            u = i / (self.settings["division"] - 1.0)

            cns = applyop.pathCns(
                self.div_cns[i], self.slv_crv, False, u, True)
            cns.setAttr("frontAxis", 1)  # front axis is 'Y'
            cns.setAttr("upAxis", 0)  # front axis is 'X'

            # Roll
            intMatrix = applyop.gear_intmatrix_op(
                self.ik0_ctl + ".worldMatrix",
                self.ik1_ctl + ".worldMatrix",
                u)

            dm_node = node.createDecomposeMatrixNode(intMatrix + ".output")
            pm.connectAttr(dm_node + ".outputRotate",
                           self.twister[i].attr("rotate"))

            pm.parentConstraint(self.twister[i],
                                self.ref_twist[i],
                                maintainOffset=True)

            pm.connectAttr(self.ref_twist[i] + ".translate",
                           cns + ".worldUpVector")

            # compensate scale reference
            div_node = node.createDivNode([1, 1, 1],
                                          [rootWorld_node + ".outputScaleX",
                                           rootWorld_node + ".outputScaleY",
                                           rootWorld_node + ".outputScaleZ"])

            # Squash n Stretch
            op = applyop.gear_squashstretch2_op(
                self.scl_transforms[i],
                self.root,
                pm.arclen(self.slv_crv),
                "y",
                div_node + ".output")

            pm.connectAttr(self.volume_att, op + ".blend")
            pm.connectAttr(crv_node + ".arcLength", op + ".driver")
            pm.connectAttr(self.st_att[i], op + ".stretch")
            pm.connectAttr(self.sq_att[i], op + ".squash")

            # Controlers
            if i == 0:
                mulmat_node = applyop.gear_mulmatrix_op(
                    self.div_cns[i].attr("worldMatrix"),
                    self.root.attr("worldInverseMatrix"))

                dm_node = node.createDecomposeMatrixNode(
                    mulmat_node + ".output")

                pm.connectAttr(dm_node + ".outputTranslate",
                               self.fk_npo[i].attr("t"))

            else:
                mulmat_node = applyop.gear_mulmatrix_op(
                    self.div_cns[i].attr("worldMatrix"),
                    self.div_cns[i - 1].attr("worldInverseMatrix"))

                dm_node = node.createDecomposeMatrixNode(
                    mulmat_node + ".output")

                mul_node = node.createMulNode(div_node + ".output",
                                              dm_node + ".outputTranslate")

                pm.connectAttr(mul_node + ".output",
                               self.fk_npo[i].attr("t"))

            pm.connectAttr(dm_node + ".outputRotate", self.fk_npo[i].attr("r"))

            # Orientation Lock
            if i == 0:
                dm_node = node.createDecomposeMatrixNode(
                    self.ik0_ctl + ".worldMatrix")

                blend_node = node.createBlendNode(
                    [dm_node + ".outputRotate%s" % s for s in "XYZ"],
                    [cns + ".rotate%s" % s for s in "XYZ"],
                    self.lock_ori0_att)

                self.div_cns[i].attr("rotate").disconnect()
                pm.connectAttr(blend_node + ".output",
                               self.div_cns[i] + ".rotate")

            elif i == self.settings["division"] - 1:
                dm_node = node.createDecomposeMatrixNode(
                    self.ik1_ctl + ".worldMatrix")

                blend_node = node.createBlendNode(
                    [dm_node + ".outputRotate%s" % s for s in "XYZ"],
                    [cns + ".rotate%s" % s for s in "XYZ"],
                    self.lock_ori1_att)

                self.div_cns[i].attr("rotate").disconnect()
                pm.connectAttr(blend_node + ".output",
                               self.div_cns[i] + ".rotate")

        # Connections (Hooks) ------------------------------

        pm.parentConstraint(self.scl_transforms[0], self.cnx0)
        pm.scaleConstraint(self.scl_transforms[0], self.cnx0)
        pm.parentConstraint(self.scl_transforms[-1], self.cnx1)
        pm.scaleConstraint(self.scl_transforms[-1], self.cnx1)
Example #8
0
    def addOperators(self):

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

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

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

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

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


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

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

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

            #rotation

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

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


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

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

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


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

        #spline IK for  twist jnts
        self.ikhArmTwist, self.armTwistCrv = aop.splineIK(self.getName("armTwist"), self.armTwistChain, parent=self.root, cParent=self.bone0 )
        self.ikhForearmTwist, self.forearmTwistCrv = aop.splineIK(self.getName("forearmTwist"), self.forearmTwistChain, parent=self.root, cParent=self.bone1 )

        #references
        self.ikhArmRef, self.tmpCrv = aop.splineIK(self.getName("armRollRef"), self.armRollRef, parent=self.root, cParent=self.bone0 )
        self.ikhForearmRef, self.tmpCrv = aop.splineIK(self.getName("forearmRollRef"), self.forearmRollRef, parent=self.root, cParent=self.eff_loc )
        self.ikhAuxTwist, self.tmpCrv = aop.splineIK(self.getName("auxTwist"), self.auxTwistChain, parent=self.root, cParent=self.eff_loc )

        #setting connexions for ikhArmTwist
        self.ikhArmTwist.attr("dTwistControlEnable").set(True)
        self.ikhArmTwist.attr("dWorldUpType").set(4)
        self.ikhArmTwist.attr("dWorldUpAxis").set(3)
        self.ikhArmTwist.attr("dWorldUpVectorZ").set(1.0)
        self.ikhArmTwist.attr("dWorldUpVectorY").set(0.0)
        self.ikhArmTwist.attr("dWorldUpVectorEndZ").set(1.0)
        self.ikhArmTwist.attr("dWorldUpVectorEndY").set(0.0)
        pm.connectAttr(self.armRollRef[0].attr("worldMatrix[0]"), self.ikhArmTwist.attr("dWorldUpMatrix"))
        pm.connectAttr(self.bone0.attr("worldMatrix[0]"), self.ikhArmTwist.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.forearmRollRef[0].attr("worldMatrix[0]"), self.ikhAuxTwist.attr("dWorldUpMatrix"))
        pm.connectAttr(self.eff_loc.attr("worldMatrix[0]"), self.ikhAuxTwist.attr("dWorldUpMatrixEnd"))
        pm.connectAttr(self.auxTwistChain[1].attr("rx"), self.ikhForearmTwist.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.armTwistCrv, ch=True)
        alAttrArm = arclen_node.attr("arcLength")
        muldiv_nodeArm =  pm.createNode("multiplyDivide")
        pm.connectAttr(arclen_node.attr("arcLength"), muldiv_nodeArm.attr("input1X"))
        muldiv_nodeArm.attr("input2X").set(alAttrArm.get())
        muldiv_nodeArm.attr("operation").set(2)
        for jnt in self.armTwistChain:
            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.forearmTwistCrv, ch=True)
        alAttrForearm = arclen_node.attr("arcLength")
        muldiv_nodeForearm =  pm.createNode("multiplyDivide")
        pm.connectAttr(arclen_node.attr("arcLength"), muldiv_nodeForearm.attr("input1X"))
        muldiv_nodeForearm.attr("input2X").set(alAttrForearm.get())
        muldiv_nodeForearm.attr("operation").set(2)
        for jnt in self.forearmTwistChain:
            pm.connectAttr(muldiv_nodeForearm.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.armTwistChain[0].attr("inverseScale"))
        pm.connectAttr(dm_node.attr("outputScale"), self.forearmTwistChain[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"
        aop.aimCns(self.tws1A_npo, self.tws0_loc, axis=axis, wupType=2, wupVector=[0,0,1], wupObject=self.mid_ctl, maintainOffset=False)

        aop.aimCns(self.forearmTangentB_loc, self.forearmTangentA_npo, axis=axis, wupType=2, wupVector=[0,0,1], wupObject=self.mid_ctl, maintainOffset=False)
        pm.pointConstraint(self.eff_loc, self.forearmTangentB_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"
        aop.aimCns(self.tws1B_npo, self.tws2_loc, axis=axis, wupType=2, wupVector=[0,0,1], wupObject=self.mid_ctl, maintainOffset=False)

        aop.aimCns(self.armTangentA_loc, self.armTangentB_npo, axis=axis, wupType=2, wupVector=[0,0,1], wupObject=self.mid_ctl, maintainOffset=False)

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

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

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

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


        div_nodeArm = nod.createDivNode(distA_node+".distance",  dm_node.attr("outputScaleX"))
        div_node2 = nod.createDivNode(div_nodeArm+".outputX", distA_node.attr("distance").get())
        pm.connectAttr(div_node2.attr("outputX"), self.tws1A_loc.attr("sx"))
        pm.connectAttr(div_node2.attr("outputX"), self.armTangentA_loc.attr("sx"))

        div_nodeForearm = nod.createDivNode(distB_node+".distance", dm_node.attr("outputScaleX"))
        div_node2 = nod.createDivNode(div_nodeForearm+".outputX", distB_node.attr("distance").get())
        pm.connectAttr(div_node2.attr("outputX"), self.tws1B_loc.attr("sx"))
        pm.connectAttr(div_node2.attr("outputX"), self.forearmTangentB_loc.attr("sx"))

        #conection curve
        aop.gear_curvecns_op(self.armTwistCrv, [ self.armTangentA_loc, self.armTangentA_ctl, self.armTangentB_ctl,self.elbowTangent_ctl ])
        aop.gear_curvecns_op(self.forearmTwistCrv, [ self.elbowTangent_ctl, self.forearmTangentA_ctl, self.forearmTangentB_ctl,self.forearmTangentB_loc ])

        #Tangent controls vis
        for shp in self.armTangentA_ctl.getShapes():
            pm.connectAttr( self.tangentVis_att, shp.attr("visibility"))
        for shp in self.armTangentB_ctl.getShapes():
            pm.connectAttr( self.tangentVis_att, shp.attr("visibility"))
        for shp in self.forearmTangentA_ctl.getShapes():
            pm.connectAttr( self.tangentVis_att, shp.attr("visibility"))
        for shp in self.forearmTangentB_ctl.getShapes():
            pm.connectAttr( self.tangentVis_att, shp.attr("visibility"))
        for shp in self.elbowTangent_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 = aop.gear_mulmatrix_op(self.armTwistChain[i]+".worldMatrix", div_cns+".parentInverseMatrix")
                lastArmDiv = div_cns
            else:
                mulmat_node = aop.gear_mulmatrix_op(self.forearmTwistChain[i-(self.settings["div0"]+2)]+".worldMatrix", div_cns+".parentInverseMatrix")
                lastForeDiv = div_cns
            dm_node = nod.createDecomposeMatrixNode(mulmat_node+".output")
            pm.connectAttr(dm_node+".outputTranslate", div_cns+".t")
            pm.connectAttr(dm_node+".outputRotate", div_cns+".r")

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

        #force translation for last loc arm and foreamr
        aop.gear_mulmatrix_op(self.elbowTangent_ctl.worldMatrix,lastArmDiv.parentInverseMatrix, lastArmDiv, "t" )
        aop.gear_mulmatrix_op(self.tws2_loc.worldMatrix,lastForeDiv.parentInverseMatrix, lastForeDiv, "t" )

        # return

        # 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
        tra.matchWorldTransform(self.fk_ctl[0], self.match_fk0_off)
        tra.matchWorldTransform(self.fk_ctl[1], self.match_fk1_off)
        tra.matchWorldTransform(self.fk_ctl[0], self.match_fk0)
        tra.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)
        if self.settings["ikTR"]:
            tra.matchWorldTransform(self.ikRot_ctl,self.match_ikRot )
            tra.matchWorldTransform(self.fk_ctl[2], self.match_fk2 )
Example #9
0
def cycleTweak(name,
               edgePair,
               mirrorAxis,
               baseMesh,
               rotMesh,
               transMesh,
               setupParent,
               ctlParent,
               jntOrg=None,
               grp=None,
               iconType="square",
               size=.025,
               color=13,
               ro=datatypes.Vector(1.5708, 0, 1.5708 / 2)):
    """The command to create a cycle tweak.

    A cycle tweak is a tweak that cycles to the parent position but doesn't
    create a cycle of dependency. This type of tweaks
    are very useful to create facial tweakers.

    Args:
        name (string): Name for the cycle tweak
        edgePair (list): List of edge pair to attach the cycle tweak
        mirrorAxis (bool): If true, will mirror the x axis behaviour.
        baseMesh (Mesh): The base mesh for the cycle tweak.
        rotMesh (Mesh): The mesh that will support the rotation transformations
                for the cycle tweak
        transMesh (Mesh): The mesh that will support the translation and scale
                transformations for the cycle tweak
        setupParent (dagNode): The parent for the setup objects
        ctlParent (dagNode): The parent for the control objects
        jntOrg (None or dagNode, optional): The parent for the joints
        grp (None or set, optional): The set to add the controls
        iconType (str, optional): The controls shape
        size (float, optional): The control size
        color (int, optional): The control color
        ro (TYPE, optional): The control shape rotation offset

    Returns:
        multi: the tweak control and the list of related joints.
    """
    # rotation sctructure
    rRivet = rivet.rivet()
    rBase = rRivet.create(baseMesh, edgePair[0], edgePair[1], setupParent,
                          name + "_rRivet_loc")

    pos = rBase.getTranslation(space="world")

    # translation structure
    tRivetParent = pm.createNode("transform",
                                 n=name + "_tRivetBase",
                                 p=ctlParent)
    tRivetParent.setMatrix(datatypes.Matrix(), worldSpace=True)
    tRivet = rivet.rivet()
    tBase = tRivet.create(transMesh, edgePair[0], edgePair[1], tRivetParent,
                          name + "_tRivet_loc")

    # create the control
    tweakBase = pm.createNode("transform", n=name + "_tweakBase", p=ctlParent)
    tweakBase.setMatrix(datatypes.Matrix(), worldSpace=True)
    tweakNpo = pm.createNode("transform", n=name + "_tweakNpo", p=tweakBase)
    tweakBase.setTranslation(pos, space="world")
    tweakCtl = icon.create(tweakNpo,
                           name + "_ctl",
                           tweakNpo.getMatrix(worldSpace=True),
                           color,
                           iconType,
                           w=size,
                           d=size,
                           ro=ro)
    inverseTranslateParent(tweakCtl)
    pm.pointConstraint(tBase, tweakBase)

    # rot
    rotBase = pm.createNode("transform", n=name + "_rotBase", p=setupParent)
    rotBase.setMatrix(datatypes.Matrix(), worldSpace=True)
    rotNPO = pm.createNode("transform", n=name + "_rot_npo", p=rotBase)
    rotJointDriver = pm.createNode("transform",
                                   n=name + "_rotJointDriver",
                                   p=rotNPO)
    rotBase.setTranslation(pos, space="world")

    node.createMulNode(
        [rotNPO.attr("tx"),
         rotNPO.attr("ty"),
         rotNPO.attr("tz")], [-1, -1, -1], [
             rotJointDriver.attr("tx"),
             rotJointDriver.attr("ty"),
             rotJointDriver.attr("tz")
         ])

    pm.pointConstraint(rBase, rotNPO)
    pm.connectAttr(tweakCtl.r, rotNPO.r)
    pm.connectAttr(tweakCtl.s, rotNPO.s)

    # transform
    posNPO = pm.createNode("transform", n=name + "_pos_npo", p=setupParent)
    posJointDriver = pm.createNode("transform",
                                   n=name + "_posJointDriver",
                                   p=posNPO)
    posNPO.setTranslation(pos, space="world")
    pm.connectAttr(tweakCtl.t, posJointDriver.t)

    # mirror behaviour
    if mirrorAxis:
        tweakBase.attr("ry").set(tweakBase.attr("ry").get() + 180)
        rotBase.attr("ry").set(rotBase.attr("ry").get() + 180)
        posNPO.attr("ry").set(posNPO.attr("ry").get() + 180)
        tweakBase.attr("sz").set(-1)
        rotBase.attr("sz").set(-1)
        posNPO.attr("sz").set(-1)

    # create joints
    rJoint = rigbits.addJnt(rotJointDriver, jntOrg, True, grp)
    tJoint = rigbits.addJnt(posJointDriver, jntOrg, True, grp)

    # add to rotation skin
    # TODO: add checker to see if joint is in the skincluster.
    rSK = skin.getSkinCluster(rotMesh)
    pm.skinCluster(rSK, e=True, ai=rJoint, lw=True, wt=0)

    # add to transform skin
    # TODO: add checker to see if joint is in the skincluster.
    tSK = skin.getSkinCluster(transMesh)
    pm.skinCluster(tSK, e=True, ai=tJoint, lw=True, wt=0)

    return tweakCtl, [rJoint, tJoint]
Example #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.

        """

        # 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
Example #11
0
    def addOperators(self):

        # Visibilities -------------------------------------

        # ik
        if self.settings["roll"] == 0:
            for shp in self.roll_ctl.getShapes():
                connectAttr(self.blend_att, shp.attr("visibility"))
        for bk_ctl in self.bk_ctl:
            for shp in bk_ctl.getShapes():
                connectAttr(self.blend_att, shp.attr("visibility"))

        for shp in self.heel_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))
        for shp in self.tip_ctl.getShapes():
            connectAttr(self.blend_att, shp.attr("visibility"))

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

        # heel roll and bank
        if self.negate:
            inpiv_nod = nod.createAddNode(self.bank_att, self.in_piv.getAttr("rx"))
            clamp_node = nod.createClampNode([self.roll_att, self.bank_att, inpiv_nod+".output"], [0, -180, -180], [180,0,0])
        else:
            clamp_node = nod.createClampNode([self.roll_att, self.bank_att, self.bank_att], [0, -180, 0], [180,0,180])
        inAdd_nod = nod.createAddNode(clamp_node+".outputB", getAttr(self.in_piv.attr("rx")) *  self.n_factor) 
           
        connectAttr(clamp_node+".outputR", self.heel_loc.attr("rz"))
        connectAttr(clamp_node+".outputG", self.out_piv.attr("rx"))
        connectAttr(inAdd_nod+".output", self.in_piv.attr("rx"))

        # Reverse Controler offset -------------------------
        angle_outputs = nod.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 = nod.createSubNode(self.roll_att, angle_outputs[i-1])
                input = sub_nod+".output"
                min_input = -360

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

            clamp_node = nod.createClampNode(input, min_input, 0)
            add_node = nod.createAddNode(clamp_node+".outputR", bk_loc.getAttr("rz"))
            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
            node = aop.gear_inverseRotorder_op(bk_ctl, fk_ctl)
            connectAttr(node+".output", bk_loc.attr("ro"))
            connectAttr(fk_ctl.attr("ro"), fk_loc.attr("ro"))


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

            neg_node = nod.createMulNode([addx_node+".output",addy_node+".output",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 = nod.createBlendNode(ik_outputs, fk_outputs, self.blend_att)
            connectAttr(blend_node+".output", fk_loc.attr("rotate"))

        return
Example #12
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.

        """
        dm_node_scl = node.createDecomposeMatrixNode(self.root.worldMatrix)
        if self.settings["keepLength"]:
            arclen_node = pm.arclen(self.mst_crv, ch=True)
            alAttr = pm.getAttr(arclen_node + ".arcLength")
            ration_node = node.createMulNode(self.length_ratio_att, alAttr)

            pm.addAttr(self.mst_crv, ln="length_ratio", k=True, w=True)
            node.createDivNode(arclen_node.arcLength, ration_node.outputX,
                               self.mst_crv.length_ratio)

            div_node_scl = node.createDivNode(self.mst_crv.length_ratio,
                                              dm_node_scl.outputScaleX)

        step = 1.000 / (self.def_number - 1)
        u = 0.000
        for i in range(self.def_number):
            cnsUpv = applyop.pathCns(self.upv_cns[i],
                                     self.upv_crv,
                                     cnsType=False,
                                     u=u,
                                     tangent=False)

            cns = applyop.pathCns(self.div_cns[i], self.mst_crv, False, u,
                                  True)

            # Connectiong the scale for scaling compensation
            for axis, AX in zip("xyz", "XYZ"):
                pm.connectAttr(dm_node_scl.attr("outputScale{}".format(AX)),
                               self.div_cns[i].attr("s{}".format(axis)))

            if self.settings["keepLength"]:

                div_node2 = node.createDivNode(u, div_node_scl.outputX)

                cond_node = node.createConditionNode(div_node2.input1X,
                                                     div_node2.outputX, 4,
                                                     div_node2.input1X,
                                                     div_node2.outputX)

                pm.connectAttr(cond_node + ".outColorR", cnsUpv + ".uValue")
                pm.connectAttr(cond_node + ".outColorR", cns + ".uValue")

            cns.setAttr("worldUpType", 1)
            cns.setAttr("frontAxis", 0)
            cns.setAttr("upAxis", 1)

            pm.connectAttr(self.upv_cns[i].attr("worldMatrix[0]"),
                           cns.attr("worldUpMatrix"))
            u += step

        if self.settings["keepLength"]:
            # add the safty distance offset
            self.tweakTip_npo.attr("tx").set(self.off_dist)
            # connect vis line ref
            for shp in self.line_ref.getShapes():
                pm.connectAttr(self.ikVis_att, shp.attr("visibility"))

        for ctl in self.tweak_ctl:
            for shp in ctl.getShapes():
                pm.connectAttr(self.ikVis_att, shp.attr("visibility"))
        for ctl in self.fk_ctl:
            for shp in ctl.getShapes():
                pm.connectAttr(self.fkVis_att, shp.attr("visibility"))
Example #13
0
    def addOperators(self):

        # Tangent position ---------------------------------
        # common part
        d = vec.getDistance(self.guide.pos["root"], self.guide.pos["neck"])
        dist_node = nod.createDistNode(self.root, self.ik_ctl)
        rootWorld_node = nod.createDecomposeMatrixNode(
            self.root.attr("worldMatrix"))
        div_node = nod.createDivNode(dist_node + ".distance",
                                     rootWorld_node + ".outputScaleX")
        div_node = nod.createDivNode(div_node + ".outputX", d)

        # tan0
        mul_node = nod.createMulNode(self.tan0_att,
                                     self.tan0_loc.getAttr("ty"))
        res_node = nod.createMulNode(mul_node + ".outputX",
                                     div_node + ".outputX")
        connectAttr(res_node + ".outputX", self.tan0_loc + ".ty")

        # tan1
        mul_node = nod.createMulNode(self.tan1_att,
                                     self.tan1_loc.getAttr("ty"))
        res_node = nod.createMulNode(mul_node + ".outputX",
                                     div_node + ".outputX")
        connectAttr(res_node + ".outputX", self.tan1_loc.attr("ty"))

        # Curves -------------------------------------------
        op = aop.gear_curveslide2_op(self.slv_crv, self.mst_crv, 0, 1.5, .5,
                                     .5)
        connectAttr(self.maxstretch_att, op + ".maxstretch")
        connectAttr(self.maxsquash_att, op + ".maxsquash")
        connectAttr(self.softness_att, op + ".softness")

        # Volume driver ------------------------------------
        crv_node = nod.createCurveInfoNode(self.slv_crv)

        # Division -----------------------------------------
        for i in range(self.settings["division"]):

            # References
            u = i / (self.settings["division"] - 1.0)

            cns = aop.pathCns(self.div_cns[i], self.slv_crv, False, u, True)
            cns.setAttr("frontAxis", 1)  # front axis is 'Y'
            cns.setAttr("upAxis", 2)  # front axis is 'Z'

            # Roll
            aop.gear_spinePointAtOp(cns, self.root, self.ik_ctl, u, "Z")

            # Squash n Stretch
            op = aop.gear_squashstretch2_op(self.fk_npo[i], self.root,
                                            arclen(self.slv_crv), "y")
            connectAttr(self.volume_att, op + ".blend")
            connectAttr(crv_node + ".arcLength", op + ".driver")
            connectAttr(self.st_att[i], op + ".stretch")
            connectAttr(self.sq_att[i], op + ".squash")

            # scl compas
            if i != 0:
                div_node = nod.createDivNode([1, 1, 1], [
                    self.fk_npo[i - 1] + ".sx", self.fk_npo[i - 1] + ".sy",
                    self.fk_npo[i - 1] + ".sz"
                ])
                connectAttr(div_node + ".output", self.scl_npo[i] + ".scale")

            # Controlers
            if i == 0:
                mulmat_node = aop.gear_mulmatrix_op(
                    self.div_cns[i].attr("worldMatrix"),
                    self.root.attr("worldInverseMatrix"))
            else:
                mulmat_node = aop.gear_mulmatrix_op(
                    self.div_cns[i].attr("worldMatrix"),
                    self.div_cns[i - 1].attr("worldInverseMatrix"))

            dm_node = nod.createDecomposeMatrixNode(mulmat_node + ".output")
            connectAttr(dm_node + ".outputTranslate", self.fk_npo[i].attr("t"))
            connectAttr(dm_node + ".outputRotate", self.fk_npo[i].attr("r"))
            #connectAttr(dm_node+".outputScale", self.fk_npo[i].attr("s"))

            # Orientation Lock
            if i == self.settings["division"] - 1:
                dm_node = nod.createDecomposeMatrixNode(self.ik_ctl +
                                                        ".worldMatrix")
                blend_node = nod.createBlendNode(
                    [dm_node + ".outputRotate%s" % s for s in "XYZ"],
                    [cns + ".rotate%s" % s for s in "XYZ"], self.lock_ori_att)
                self.div_cns[i].attr("rotate").disconnect()
                connectAttr(blend_node + ".output",
                            self.div_cns[i] + ".rotate")

        # Head ---------------------------------------------
        self.fk_ctl[-1].addChild(self.head_cns)
Example #14
0
def _createSoftModTweak(baseCtl,
                        tweakCtl,
                        name,
                        targets,
                        nameExt="softMod",
                        is_asset=False):

    sm = pm.softMod(targets, wn=[tweakCtl, tweakCtl])
    pm.rename(sm[0], "{}_{}".format(name, nameExt))

    # disconnect default connection
    plugs = sm[0].softModXforms.listConnections(p=True)
    for p in plugs:
        pm.disconnectAttr(p, sm[0].softModXforms)
        pm.delete(p.node())

    dm_node = node.createDecomposeMatrixNode(baseCtl.worldMatrix[0])
    pm.connectAttr(dm_node.outputTranslate, sm[0].falloffCenter)
    mul_node = node.createMulNode(dm_node.outputScaleX,
                                  tweakCtl.attr("falloff"))
    pm.connectAttr(mul_node.outputX, sm[0].falloffRadius)
    mulMatrix_node = applyop.gear_mulmatrix_op(tweakCtl.worldMatrix[0],
                                               tweakCtl.parentInverseMatrix[0])
    pm.connectAttr(mulMatrix_node.output, sm[0].weightedMatrix)
    pm.connectAttr(baseCtl.worldInverseMatrix[0], sm[0].postMatrix)
    pm.connectAttr(baseCtl.worldMatrix[0], sm[0].preMatrix)
    if is_asset:
        tag_name = ASSET_TAG
    else:
        tag_name = SHOT_TAG

    attribute.addAttribute(sm[0], tag_name, "bool", False, keyable=False)

    sm[0].addAttr("ctlRoot", at='message', m=False)
    sm[0].addAttr("ctlBase", at='message', m=False)
    sm[0].addAttr("ctlTweak", at='message', m=False)
    pm.connectAttr(baseCtl.getParent().attr("message"), sm[0].attr("ctlRoot"))
    pm.connectAttr(baseCtl.attr("message"), sm[0].attr("ctlBase"))
    pm.connectAttr(tweakCtl.attr("message"), sm[0].attr("ctlTweak"))

    # This connection allow the softTweak to work if we apply the  skin
    # precision fix.
    # TODO: By default only apply to a non asset tweaks.
    if skin.getSkinCluster(targets[0]) and not is_asset:

        skin_cls = skin.getSkinCluster(targets[0])
        cnxs = skin_cls.matrix[0].listConnections()
        if (cnxs and cnxs[0].type() == "mgear_mulMatrix"
                and not sm[0].hasAttr("_fixedSkinFix")):

            # tag the softmod as fixed
            attribute.addAttribute(sm[0], "_fixedSkinFix", "bool")

            # original connections
            matrix_cnx = sm[0].matrix.listConnections(p=True)[0]
            preMatrix_cnx = sm[0].preMatrix.listConnections(p=True)[0]
            wgtMatrix_cnx = sm[0].weightedMatrix.listConnections(p=True)[0]
            postMatrix_cnx = sm[0].postMatrix.listConnections(p=True)[0]

            # pre existing node operators
            mulMtx_node = wgtMatrix_cnx.node()
            dcMtx_node = sm[0].falloffCenter.listConnections(p=True)[0].node()

            # geo offset connnections
            geo_root = targets[0].getParent()
            gr_W = geo_root.worldMatrix[0]
            gr_WI = geo_root.worldInverseMatrix[0]

            # new offset operators
            mmm1 = applyop.gear_mulmatrix_op(preMatrix_cnx, gr_WI)
            mmm2 = applyop.gear_mulmatrix_op(matrix_cnx, gr_WI)
            mmm3 = applyop.gear_mulmatrix_op(gr_W, postMatrix_cnx)

            # re-wire connections
            pm.connectAttr(mmm1.output, dcMtx_node.inputMatrix, f=True)
            pm.connectAttr(mmm1.output, sm[0].preMatrix, f=True)

            pm.connectAttr(mmm2.output, sm[0].matrix, f=True)
            pm.connectAttr(mmm2.output, mulMtx_node.matrixA, f=True)

            pm.connectAttr(mmm3.output, mulMtx_node.matrixB, f=True)
            pm.connectAttr(mmm3.output, sm[0].postMatrix, f=True)

            _neutra_geomMatrix(sm[0])

    return sm[0]
Example #15
0
    def addOperators(self):

        # Tangent position ---------------------------------
        # common part
        d = vec.getDistance(self.guide.apos[0], self.guide.apos[1])
        dist_node = nod.createDistNode(self.ik0_ctl, self.ik1_ctl)
        rootWorld_node = nod.createDecomposeMatrixNode(self.root.attr("worldMatrix"))
        div_node = nod.createDivNode(dist_node+".distance", rootWorld_node+".outputScaleX")
        div_node = nod.createDivNode(div_node+".outputX", d)

        # tan0
        mul_node = nod.createMulNode(self.tan0_att, self.tan0_npo.getAttr("ty"))
        res_node = nod.createMulNode(mul_node+".outputX", div_node+".outputX")
        pm.connectAttr( res_node+".outputX", self.tan0_npo.attr("ty"))

        # tan1
        mul_node = nod.createMulNode(self.tan1_att, self.tan1_npo.getAttr("ty"))
        res_node = nod.createMulNode(mul_node+".outputX", div_node+".outputX")
        pm.connectAttr( res_node+".outputX", self.tan1_npo.attr("ty"))

        # Curves -------------------------------------------
        op = aop.gear_curveslide2_op(self.slv_crv, self.mst_crv, 0, 1.5, .5, .5)

        pm.connectAttr(self.position_att, op+".position")
        pm.connectAttr(self.maxstretch_att, op+".maxstretch")
        pm.connectAttr(self.maxsquash_att, op+".maxsquash")
        pm.connectAttr(self.softness_att, op+".softness")

        # Volume driver ------------------------------------
        crv_node = nod.createCurveInfoNode(self.slv_crv)

        # Division -----------------------------------------
        for i in range(self.settings["division"]):

            # References
            u = i / (self.settings["division"] - 1.0)

            cns = aop.pathCns(self.div_cns[i], self.slv_crv, False, u, True)
            cns.setAttr("frontAxis", 1)# front axis is 'Y'
            cns.setAttr("upAxis", 0)# front axis is 'X'

            # Roll
            intMatrix = aop.gear_intmatrix_op(self.ik0_ctl+".worldMatrix", self.ik1_ctl+".worldMatrix", u)
            dm_node = nod.createDecomposeMatrixNode(intMatrix+".output")
            pm.connectAttr(dm_node+".outputRotate", self.twister[i].attr("rotate"))


            pm.parentConstraint(self.twister[i], self.ref_twist[i], maintainOffset=True)


            pm.connectAttr(self.ref_twist[i]+".translate", cns+".worldUpVector")

            # Squash n Stretch
            op = aop.gear_squashstretch2_op(self.fk_npo[i], self.root, pm.arclen(self.slv_crv), "y")
            pm.connectAttr(self.volume_att, op+".blend")
            pm.connectAttr(crv_node+".arcLength", op+".driver")
            pm.connectAttr(self.st_att[i], op+".stretch")
            pm.connectAttr(self.sq_att[i], op+".squash")

            # scl compensation

            if i == 0:
                dm_node = nod.createDecomposeMatrixNode(self.root+".worldMatrix")
                div_node = nod.createDivNode([1,1,1], [dm_node+".outputScaleX", dm_node+".outputScaleY", dm_node+".outputScaleZ"])
                pm.connectAttr(div_node+".output", self.scl_npo[i]+".scale")

            elif i == 1:
                div_node = nod.createDivNode([1,1,1], [self.fk_npo[i-1]+".sx", self.fk_npo[i-1]+".sy", self.fk_npo[i-1]+".sz"])
                pm.connectAttr(div_node+".output", self.scl_npo[i]+".scale")


            else:
                div_node = nod.createDivNode([1,1,1], [self.fk_npo[i-1]+".sx", self.fk_npo[i-1]+".sy", self.fk_npo[i-1]+".sz"])
                pm.connectAttr(div_node+".output", self.scl_npo[i]+".scale")


            # Controlers
            if i == 0:
                mulmat_node = aop.gear_mulmatrix_op(self.div_cns[i].attr("worldMatrix"),
                                                    self.scl_npo[0].attr("worldInverseMatrix"))
            else:
                mulmat_node = aop.gear_mulmatrix_op(self.div_cns[i].attr("worldMatrix"),
                                                    self.div_cns[i - 1].attr("worldInverseMatrix"))
            dm_node = nod.createDecomposeMatrixNode(mulmat_node+".output")
            pm.connectAttr(dm_node+".outputTranslate", self.fk_npo[i].attr("t"))
            pm.connectAttr(dm_node+".outputRotate", self.fk_npo[i].attr("r"))

            # Orientation Lock
            if i == 0 :
                dm_node = nod.createDecomposeMatrixNode(self.ik0_ctl+".worldMatrix")
                blend_node = nod.createBlendNode([dm_node+".outputRotate%s"%s for s in "XYZ"], [cns+".rotate%s"%s for s in "XYZ"], self.lock_ori0_att)
                self.div_cns[i].attr("rotate").disconnect()
                pm.connectAttr(blend_node+".output", self.div_cns[i]+".rotate")
            elif i == self.settings["division"] - 1 :
                dm_node = nod.createDecomposeMatrixNode(self.ik1_ctl+".worldMatrix")
                blend_node = nod.createBlendNode([dm_node+".outputRotate%s"%s for s in "XYZ"], [cns+".rotate%s"%s for s in "XYZ"], self.lock_ori1_att)
                self.div_cns[i].attr("rotate").disconnect()
                pm.connectAttr(blend_node+".output", self.div_cns[i]+".rotate")

        # Connections (Hooks) ------------------------------
        pm.pointConstraint(self.div_cns[0], self.cnx0)
        pm.orientConstraint(self.div_cns[0], self.cnx0)
        pm.pointConstraint(self.fk_ctl[-1], self.cnx1)
        pm.orientConstraint(self.fk_ctl[-1], self.cnx1)
Example #16
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"))

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

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

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

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

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

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

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

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

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

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

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

        self.volDriver_att = div_node2 + ".outputX"

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

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

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

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

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

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

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

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

        # match IK/FK ref
        pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True)
        pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True)
        return
Example #17
0
    def addOperators(self):
        """Create operators and set the relations for the component rig

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # IK/FK connections

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

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

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

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

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

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

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

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

        initRound = .001
        multVal = 1

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

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

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

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

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

        self.volDriver_att = div_node2 + ".outputX"

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

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

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

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

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

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

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

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

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

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

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

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

        return
Example #18
0
def eyeRig(eyeMesh,
           edgeLoop,
           blinkH,
           namePrefix,
           offset,
           rigidLoops,
           falloffLoops,
           headJnt,
           doSkin,
           parent=None,
           ctlName="ctl",
           sideRange=False,
           customCorner=False,
           intCorner=None,
           extCorner=None,
           ctlGrp=None,
           defGrp=None):

    """Create eyelid and eye rig

    Args:
        eyeMesh (TYPE): Description
        edgeLoop (TYPE): Description
        blinkH (TYPE): Description
        namePrefix (TYPE): Description
        offset (TYPE): Description
        rigidLoops (TYPE): Description
        falloffLoops (TYPE): Description
        headJnt (TYPE): Description
        doSkin (TYPE): Description
        parent (None, optional): Description
        ctlName (str, optional): Description
        sideRange (bool, optional): Description
        customCorner (bool, optional): Description
        intCorner (None, optional): Description
        extCorner (None, optional): Description
        ctlGrp (None, optional): Description
        defGrp (None, optional): Description

    Returns:
        TYPE: Description
    """
    # Checkers
    if edgeLoop:
        edgeLoopList = [pm.PyNode(e) for e in edgeLoop.split(",")]
    else:
        pm.displayWarning("Please set the edge loop first")
        return

    if eyeMesh:
        try:
            eyeMesh = pm.PyNode(eyeMesh)
        except pm.MayaNodeError:
            pm.displayWarning("The object %s can not be found in the "
                              "scene" % (eyeMesh))
            return
    else:
        pm.displayWarning("Please set the eye mesh first")

    if doSkin:
        if not headJnt:
            pm.displayWarning("Please set the Head Jnt or unCheck "
                              "Compute Topological Autoskin")
            return

    # Initial Data
    bboxCenter = meshNavigation.bboxCenter(eyeMesh)

    extr_v = meshNavigation.getExtremeVertexFromLoop(edgeLoopList, sideRange)
    upPos = extr_v[0]
    lowPos = extr_v[1]
    inPos = extr_v[2]
    outPos = extr_v[3]
    edgeList = extr_v[4]
    vertexList = extr_v[5]

    # Detect the side L or R from the x value
    if inPos.getPosition(space='world')[0] < 0.0:
        side = "R"
        inPos = extr_v[3]
        outPos = extr_v[2]
        normalPos = outPos
        npw = normalPos.getPosition(space='world')
        normalVec = npw - bboxCenter
    else:
        side = "L"
        normalPos = outPos
        npw = normalPos.getPosition(space='world')
        normalVec = bboxCenter - npw
    # Manual Vertex corners
    if customCorner:
        if intCorner:
            try:
                if side == "R":
                    inPos = pm.PyNode(extCorner)
                else:
                    inPos = pm.PyNode(intCorner)
            except pm.MayaNodeError:
                pm.displayWarning("%s can not be found" % intCorner)
                return
        else:
            pm.displayWarning("Please set the internal eyelid corner")
            return

        if extCorner:
            try:
                normalPos = pm.PyNode(extCorner)
                npw = normalPos.getPosition(space='world')
                if side == "R":
                    outPos = pm.PyNode(intCorner)
                    normalVec = npw - bboxCenter
                else:
                    outPos = pm.PyNode(extCorner)
                    normalVec = bboxCenter - npw
            except pm.MayaNodeError:
                pm.displayWarning("%s can not be found" % extCorner)
                return
        else:
            pm.displayWarning("Please set the external eyelid corner")
            return

    # Check if we have prefix:
    if namePrefix:
        namePrefix = string.removeInvalidCharacter(namePrefix)
    else:
        pm.displayWarning("Prefix is needed")
        return

    def setName(name, ind=None):
        namesList = [namePrefix, side, name]
        if ind is not None:
            namesList[1] = side + str(ind)
        name = "_".join(namesList)
        return name

    if pm.ls(setName("root")):
        pm.displayWarning("The object %s already exist in the scene. Please "
                          "choose another name prefix" % setName("root"))
        return

    # Eye root
    eye_root = primitive.addTransform(None, setName("root"))
    eyeCrv_root = primitive.addTransform(eye_root, setName("crvs"))

    # Eyelid Main crvs
    try:
        upEyelid = meshNavigation.edgeRangeInLoopFromMid(
            edgeList, upPos, inPos, outPos)
        upCrv = curve.createCurveFromOrderedEdges(
            upEyelid, inPos, setName("upperEyelid"), parent=eyeCrv_root)
        upCrv_ctl = curve.createCurveFromOrderedEdges(
            upEyelid, inPos, setName("upCrv_%s" % ctlName), parent=eyeCrv_root)
        pm.rebuildCurve(upCrv_ctl, s=2, rt=0, rpo=True, ch=False)

        lowEyelid = meshNavigation.edgeRangeInLoopFromMid(
            edgeList, lowPos, inPos, outPos)
        lowCrv = curve.createCurveFromOrderedEdges(
            lowEyelid, inPos, setName("lowerEyelid"), parent=eyeCrv_root)
        lowCrv_ctl = curve.createCurveFromOrderedEdges(
            lowEyelid,
            inPos,
            setName("lowCrv_%s" % ctlName),
            parent=eyeCrv_root)

        pm.rebuildCurve(lowCrv_ctl, s=2, rt=0, rpo=True, ch=False)

    except UnboundLocalError:
        if customCorner:
            pm.displayWarning("This error is maybe caused because the custom "
                              "Corner vertex is not part of the edge loop")
        pm.displayError(traceback.format_exc())
        return

    upBlink = curve.createCurveFromCurve(
        upCrv, setName("upblink_crv"), nbPoints=30, parent=eyeCrv_root)
    lowBlink = curve.createCurveFromCurve(
        lowCrv, setName("lowBlink_crv"), nbPoints=30, parent=eyeCrv_root)

    upTarget = curve.createCurveFromCurve(
        upCrv, setName("upblink_target"), nbPoints=30, parent=eyeCrv_root)
    lowTarget = curve.createCurveFromCurve(
        lowCrv, setName("lowBlink_target"), nbPoints=30, parent=eyeCrv_root)
    midTarget = curve.createCurveFromCurve(
        lowCrv, setName("midBlink_target"), nbPoints=30, parent=eyeCrv_root)

    rigCrvs = [upCrv,
               lowCrv,
               upCrv_ctl,
               lowCrv_ctl,
               upBlink,
               lowBlink,
               upTarget,
               lowTarget,
               midTarget]

    for crv in rigCrvs:
        crv.attr("visibility").set(False)

    # localBBOX
    localBBox = eyeMesh.getBoundingBox(invisible=True, space='world')
    wRadius = abs((localBBox[0][0] - localBBox[1][0]))
    dRadius = abs((localBBox[0][1] - localBBox[1][1]) / 1.7)

    # Groups
    if not ctlGrp:
        ctlGrp = "rig_controllers_grp"
    try:
        ctlSet = pm.PyNode(ctlGrp)
    except pm.MayaNodeError:
        pm.sets(n=ctlGrp, em=True)
        ctlSet = pm.PyNode(ctlGrp)
    if not defGrp:
        defGrp = "rig_deformers_grp"
    try:
        defset = pm.PyNode(defGrp)
    except pm.MayaNodeError:
        pm.sets(n=defGrp, em=True)
        defset = pm.PyNode(defGrp)

    # Calculate center looking at
    averagePosition = ((upPos.getPosition(space='world')
                        + lowPos.getPosition(space='world')
                        + inPos.getPosition(space='world')
                        + outPos.getPosition(space='world'))
                       / 4)
    if side == "R":
        negate = False
        offset = offset
        over_offset = dRadius
    else:
        negate = False
        over_offset = dRadius

    if side == "R" and sideRange or side == "R" and customCorner:
        axis = "z-x"
        # axis = "zx"
    else:
        axis = "z-x"

    t = transform.getTransformLookingAt(
        bboxCenter,
        averagePosition,
        normalVec,
        axis=axis,
        negate=negate)

    over_npo = primitive.addTransform(
        eye_root, setName("center_lookatRoot"), t)

    over_ctl = icon.create(over_npo,
                           setName("over_%s" % ctlName),
                           t,
                           icon="square",
                           w=wRadius,
                           d=dRadius,
                           ro=datatypes.Vector(1.57079633, 0, 0),
                           po=datatypes.Vector(0, 0, over_offset),
                           color=4)
    node.add_controller_tag(over_ctl)
    attribute.add_mirror_config_channels(over_ctl)
    attribute.setKeyableAttributes(
        over_ctl,
        params=["tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz"])

    if side == "R":
        over_npo.attr("rx").set(over_npo.attr("rx").get() * -1)
        over_npo.attr("ry").set(over_npo.attr("ry").get() + 180)
        over_npo.attr("sz").set(-1)

    if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost":
        pass
    else:
        pm.sets(ctlSet, add=over_ctl)

    center_lookat = primitive.addTransform(
        over_ctl, setName("center_lookat"), t)

    # Tracking
    # Eye aim control
    t_arrow = transform.getTransformLookingAt(bboxCenter,
                                              averagePosition,
                                              upPos.getPosition(space='world'),
                                              axis="zy", negate=False)

    radius = abs((localBBox[0][0] - localBBox[1][0]) / 1.7)
    arrow_npo = primitive.addTransform(eye_root, setName("aim_npo"), t_arrow)
    arrow_ctl = icon.create(arrow_npo,
                            setName("aim_%s" % ctlName),
                            t_arrow,
                            icon="arrow",
                            w=1,
                            po=datatypes.Vector(0, 0, radius),
                            color=4)
    if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost":
        pass
    else:
        pm.sets(ctlSet, add=arrow_ctl)
    attribute.setKeyableAttributes(arrow_ctl, params=["rx", "ry", "rz"])

    # tracking custom trigger
    if side == "R":
        tt = t_arrow
    else:
        tt = t
    aimTrigger_root = primitive.addTransform(
        center_lookat, setName("aimTrigger_root"), tt)
    aimTrigger_lvl = primitive.addTransform(
        aimTrigger_root, setName("aimTrigger_lvl"), tt)
    aimTrigger_lvl.attr("tz").set(1.0)
    aimTrigger_ref = primitive.addTransform(
        aimTrigger_lvl, setName("aimTrigger_ref"), tt)
    aimTrigger_ref.attr("tz").set(0.0)
    # connect  trigger with arrow_ctl
    pm.parentConstraint(arrow_ctl, aimTrigger_ref, mo=True)

    # Controls lists
    upControls = []
    trackLvl = []

    # upper eyelid controls
    upperCtlNames = ["inCorner", "upInMid", "upMid", "upOutMid", "outCorner"]
    cvs = upCrv_ctl.getCVs(space="world")
    if side == "R" and not sideRange:
        # if side == "R":
        cvs = [cv for cv in reversed(cvs)]
    for i, cv in enumerate(cvs):
        if utils.is_odd(i):
            color = 14
            wd = .5
            icon_shape = "circle"
            params = ["tx", "ty", "tz"]
        else:
            color = 4
            wd = .7
            icon_shape = "square"
            params = ["tx",
                      "ty",
                      "tz",
                      "ro",
                      "rx",
                      "ry",
                      "rz",
                      "sx",
                      "sy",
                      "sz"]

        t = transform.setMatrixPosition(t, cvs[i])
        npo = primitive.addTransform(center_lookat,
                                     setName("%s_npo" % upperCtlNames[i]),
                                     t)
        npoBase = npo
        if i == 2:
            # we add an extra level to input the tracking ofset values
            npo = primitive.addTransform(npo,
                                         setName("%s_trk" % upperCtlNames[i]),
                                         t)
            trackLvl.append(npo)

        ctl = icon.create(npo,
                          setName("%s_%s" % (upperCtlNames[i], ctlName)),
                          t,
                          icon=icon_shape,
                          w=wd,
                          d=wd,
                          ro=datatypes.Vector(1.57079633, 0, 0),
                          po=datatypes.Vector(0, 0, offset),
                          color=color)
        attribute.add_mirror_config_channels(ctl)
        node.add_controller_tag(ctl, over_ctl)
        upControls.append(ctl)
        if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost":
            pass
        else:
            pm.sets(ctlSet, add=ctl)
        attribute.setKeyableAttributes(ctl, params)
        if side == "R":
            npoBase.attr("ry").set(180)
            npoBase.attr("sz").set(-1)

    # adding parent average contrains to odd controls
    for i, ctl in enumerate(upControls):
        if utils.is_odd(i):
            pm.parentConstraint(upControls[i - 1],
                                upControls[i + 1],
                                ctl.getParent(),
                                mo=True)

    # lower eyelid controls
    lowControls = [upControls[0]]
    lowerCtlNames = ["inCorner",
                     "lowInMid",
                     "lowMid",
                     "lowOutMid",
                     "outCorner"]

    cvs = lowCrv_ctl.getCVs(space="world")
    if side == "R" and not sideRange:
        cvs = [cv for cv in reversed(cvs)]
    for i, cv in enumerate(cvs):
        # we skip the first and last point since is already in the uper eyelid
        if i in [0, 4]:
            continue
        if utils.is_odd(i):
            color = 14
            wd = .5
            icon_shape = "circle"
            params = ["tx", "ty", "tz"]
        else:
            color = 4
            wd = .7
            icon_shape = "square"
            params = ["tx",
                      "ty",
                      "tz",
                      "ro",
                      "rx",
                      "ry",
                      "rz",
                      "sx",
                      "sy",
                      "sz"]

        t = transform.setMatrixPosition(t, cvs[i])
        npo = primitive.addTransform(center_lookat,
                                     setName("%s_npo" % lowerCtlNames[i]),
                                     t)
        npoBase = npo
        if i == 2:
            # we add an extra level to input the tracking ofset values
            npo = primitive.addTransform(npo,
                                         setName("%s_trk" % lowerCtlNames[i]),
                                         t)
            trackLvl.append(npo)
        ctl = icon.create(npo,
                          setName("%s_%s" % (lowerCtlNames[i], ctlName)),
                          t,
                          icon=icon_shape,
                          w=wd,
                          d=wd,
                          ro=datatypes.Vector(1.57079633, 0, 0),
                          po=datatypes.Vector(0, 0, offset),
                          color=color)
        attribute.add_mirror_config_channels(ctl)

        lowControls.append(ctl)
        if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost":
            pass
        else:
            pm.sets(ctlSet, add=ctl)
        attribute.setKeyableAttributes(ctl, params)
        # mirror behaviout on R side controls
        if side == "R":
            npoBase.attr("ry").set(180)
            npoBase.attr("sz").set(-1)
    for lctl in reversed(lowControls[1:]):
        node.add_controller_tag(lctl, over_ctl)
    lowControls.append(upControls[-1])

    # adding parent average contrains to odd controls
    for i, ctl in enumerate(lowControls):
        if utils.is_odd(i):
            pm.parentConstraint(lowControls[i - 1],
                                lowControls[i + 1],
                                ctl.getParent(),
                                mo=True)

    # Connecting control crvs with controls
    applyop.gear_curvecns_op(upCrv_ctl, upControls)
    applyop.gear_curvecns_op(lowCrv_ctl, lowControls)

    # adding wires
    w1 = pm.wire(upCrv, w=upBlink)[0]
    w2 = pm.wire(lowCrv, w=lowBlink)[0]

    w3 = pm.wire(upTarget, w=upCrv_ctl)[0]
    w4 = pm.wire(lowTarget, w=lowCrv_ctl)[0]

    # adding blendshapes
    bs_upBlink = pm.blendShape(upTarget,
                               midTarget,
                               upBlink,
                               n="blendShapeUpBlink")
    bs_lowBlink = pm.blendShape(lowTarget,
                                midTarget,
                                lowBlink,
                                n="blendShapeLowBlink")
    bs_mid = pm.blendShape(lowTarget,
                           upTarget,
                           midTarget,
                           n="blendShapeLowBlink")

    # setting blendshape reverse connections
    rev_node = pm.createNode("reverse")
    pm.connectAttr(bs_upBlink[0].attr(midTarget.name()), rev_node + ".inputX")
    pm.connectAttr(rev_node + ".outputX", bs_upBlink[0].attr(upTarget.name()))
    rev_node = pm.createNode("reverse")
    pm.connectAttr(bs_lowBlink[0].attr(midTarget.name()), rev_node + ".inputX")
    pm.connectAttr(rev_node + ".outputX",
                   bs_lowBlink[0].attr(lowTarget.name()))
    rev_node = pm.createNode("reverse")
    pm.connectAttr(bs_mid[0].attr(upTarget.name()), rev_node + ".inputX")
    pm.connectAttr(rev_node + ".outputX", bs_mid[0].attr(lowTarget.name()))

    # setting default values
    bs_mid[0].attr(upTarget.name()).set(blinkH)

    # joints root
    jnt_root = primitive.addTransformFromPos(
        eye_root, setName("joints"), pos=bboxCenter)

    # head joint
    if headJnt:
        try:
            headJnt = pm.PyNode(headJnt)
            jnt_base = headJnt
        except pm.MayaNodeError:
            pm.displayWarning(
                "Aborted can not find %s " % headJnt)
            return
    else:
        # Eye root
        jnt_base = jnt_root

    eyeTargets_root = primitive.addTransform(eye_root,
                                             setName("targets"))

    eyeCenter_jnt = rigbits.addJnt(arrow_ctl,
                                   jnt_base,
                                   grp=defset,
                                   jntName=setName("center_jnt"))

    # Upper Eyelid joints ##################################################

    cvs = upCrv.getCVs(space="world")
    upCrv_info = node.createCurveInfoNode(upCrv)

    # aim constrain targets and joints
    upperEyelid_aimTargets = []
    upperEyelid_jnt = []
    upperEyelid_jntRoot = []

    for i, cv in enumerate(cvs):

        # aim targets
        trn = primitive.addTransformFromPos(eyeTargets_root,
                                            setName("upEyelid_aimTarget", i),
                                            pos=cv)
        upperEyelid_aimTargets.append(trn)
        # connecting positions with crv
        pm.connectAttr(upCrv_info + ".controlPoints[%s]" % str(i),
                       trn.attr("translate"))

        # joints
        jntRoot = primitive.addJointFromPos(jnt_root,
                                            setName("upEyelid_jnt_base", i),
                                            pos=bboxCenter)
        jntRoot.attr("radius").set(.08)
        jntRoot.attr("visibility").set(False)
        upperEyelid_jntRoot.append(jntRoot)
        applyop.aimCns(jntRoot, trn, axis="zy", wupObject=jnt_root)

        jnt_ref = primitive.addJointFromPos(jntRoot,
                                            setName("upEyelid_jnt_ref", i),
                                            pos=cv)
        jnt_ref.attr("radius").set(.08)
        jnt_ref.attr("visibility").set(False)

        jnt = rigbits.addJnt(jnt_ref,
                             jnt_base,
                             grp=defset,
                             jntName=setName("upEyelid_jnt", i))
        upperEyelid_jnt.append(jnt)

    # Lower Eyelid joints ##################################################

    cvs = lowCrv.getCVs(space="world")
    lowCrv_info = node.createCurveInfoNode(lowCrv)

    # aim constrain targets and joints
    lowerEyelid_aimTargets = []
    lowerEyelid_jnt = []
    lowerEyelid_jntRoot = []

    for i, cv in enumerate(cvs):
        if i in [0, len(cvs) - 1]:
            continue

        # aim targets
        trn = primitive.addTransformFromPos(eyeTargets_root,
                                            setName("lowEyelid_aimTarget", i),
                                            pos=cv)
        lowerEyelid_aimTargets.append(trn)
        # connecting positions with crv
        pm.connectAttr(lowCrv_info + ".controlPoints[%s]" % str(i),
                       trn.attr("translate"))

        # joints
        jntRoot = primitive.addJointFromPos(jnt_root,
                                            setName("lowEyelid_base", i),
                                            pos=bboxCenter)
        jntRoot.attr("radius").set(.08)
        jntRoot.attr("visibility").set(False)
        lowerEyelid_jntRoot.append(jntRoot)
        applyop.aimCns(jntRoot, trn, axis="zy", wupObject=jnt_root)

        jnt_ref = primitive.addJointFromPos(jntRoot,
                                            setName("lowEyelid_jnt_ref", i),
                                            pos=cv)
        jnt_ref.attr("radius").set(.08)
        jnt_ref.attr("visibility").set(False)

        jnt = rigbits.addJnt(jnt_ref,
                             jnt_base,
                             grp=defset,
                             jntName=setName("lowEyelid_jnt", i))
        lowerEyelid_jnt.append(jnt)

    # Channels
    # Adding and connecting attributes for the blink
    up_ctl = upControls[2]
    blink_att = attribute.addAttribute(
        over_ctl, "blink", "float", 0, minValue=0, maxValue=1)
    blinkMult_att = attribute.addAttribute(
        over_ctl, "blinkMult", "float", 1, minValue=1, maxValue=2)
    midBlinkH_att = attribute.addAttribute(
        over_ctl, "blinkHeight", "float", blinkH, minValue=0, maxValue=1)
    mult_node = node.createMulNode(blink_att, blinkMult_att)
    pm.connectAttr(mult_node + ".outputX",
                   bs_upBlink[0].attr(midTarget.name()))
    pm.connectAttr(mult_node + ".outputX",
                   bs_lowBlink[0].attr(midTarget.name()))
    pm.connectAttr(midBlinkH_att, bs_mid[0].attr(upTarget.name()))

    low_ctl = lowControls[2]

    # Adding channels for eye tracking
    upVTracking_att = attribute.addAttribute(up_ctl,
                                             "vTracking",
                                             "float",
                                             .02,
                                             minValue=0,
                                             maxValue=1,
                                             keyable=False,
                                             channelBox=True)
    upHTracking_att = attribute.addAttribute(up_ctl,
                                             "hTracking",
                                             "float",
                                             .01,
                                             minValue=0,
                                             maxValue=1,
                                             keyable=False,
                                             channelBox=True)

    lowVTracking_att = attribute.addAttribute(low_ctl,
                                              "vTracking",
                                              "float",
                                              .01,
                                              minValue=0,
                                              maxValue=1,
                                              keyable=False,
                                              channelBox=True)
    lowHTracking_att = attribute.addAttribute(low_ctl,
                                              "hTracking",
                                              "float",
                                              .01,
                                              minValue=0,
                                              maxValue=1,
                                              keyable=False,
                                              channelBox=True)

    mult_node = node.createMulNode(upVTracking_att, aimTrigger_ref.attr("ty"))
    pm.connectAttr(mult_node + ".outputX", trackLvl[0].attr("ty"))
    mult_node = node.createMulNode(upHTracking_att, aimTrigger_ref.attr("tx"))
    pm.connectAttr(mult_node + ".outputX", trackLvl[0].attr("tx"))

    mult_node = node.createMulNode(lowVTracking_att, aimTrigger_ref.attr("ty"))
    pm.connectAttr(mult_node + ".outputX", trackLvl[1].attr("ty"))
    mult_node = node.createMulNode(lowHTracking_att, aimTrigger_ref.attr("tx"))
    pm.connectAttr(mult_node + ".outputX", trackLvl[1].attr("tx"))

    # Tension on blink
    node.createReverseNode(blink_att, w1.scale[0])
    node.createReverseNode(blink_att, w3.scale[0])
    node.createReverseNode(blink_att, w2.scale[0])
    node.createReverseNode(blink_att, w4.scale[0])

    ###########################################
    # Reparenting
    ###########################################
    if parent:
        try:
            if isinstance(parent, basestring):
                parent = pm.PyNode(parent)
            parent.addChild(eye_root)
        except pm.MayaNodeError:
            pm.displayWarning("The eye rig can not be parent to: %s. Maybe "
                              "this object doesn't exist." % parent)

    ###########################################
    # Auto Skinning
    ###########################################
    if doSkin:
        # eyelid vertex rows
        totalLoops = rigidLoops + falloffLoops
        vertexLoopList = meshNavigation.getConcentricVertexLoop(vertexList,
                                                                totalLoops)
        vertexRowList = meshNavigation.getVertexRowsFromLoops(vertexLoopList)

        # we set the first value 100% for the first initial loop
        skinPercList = [1.0]
        # we expect to have a regular grid topology
        for r in range(rigidLoops):
            for rr in range(2):
                skinPercList.append(1.0)
        increment = 1.0 / float(falloffLoops)
        # we invert to smooth out from 100 to 0
        inv = 1.0 - increment
        for r in range(falloffLoops):
            for rr in range(2):
                if inv < 0.0:
                    inv = 0.0
                skinPercList.append(inv)
            inv -= increment

        # this loop add an extra 0.0 indices to avoid errors
        for r in range(10):
            for rr in range(2):
                skinPercList.append(0.0)

        # base skin
        geo = pm.listRelatives(edgeLoopList[0], parent=True)[0]
        # Check if the object has a skinCluster
        objName = pm.listRelatives(geo, parent=True)[0]

        skinCluster = skin.getSkinCluster(objName)
        if not skinCluster:
            skinCluster = pm.skinCluster(headJnt,
                                         geo,
                                         tsb=True,
                                         nw=2,
                                         n='skinClsEyelid')

        eyelidJoints = upperEyelid_jnt + lowerEyelid_jnt
        pm.progressWindow(title='Auto skinning process',
                          progress=0,
                          max=len(eyelidJoints))
        firstBoundary = False
        for jnt in eyelidJoints:
            pm.progressWindow(e=True, step=1, status='\nSkinning %s' % jnt)
            skinCluster.addInfluence(jnt, weight=0)
            v = meshNavigation.getClosestVertexFromTransform(geo, jnt)

            for row in vertexRowList:

                if v in row:
                    it = 0  # iterator
                    inc = 1  # increment
                    for i, rv in enumerate(row):
                        try:
                            perc = skinPercList[it]
                            t_val = [(jnt, perc), (headJnt, 1.0 - perc)]
                            pm.skinPercent(skinCluster,
                                           rv,
                                           transformValue=t_val)
                            if rv.isOnBoundary():
                                # we need to compare with the first boundary
                                # to check if the row have inverted direction
                                # and offset the value
                                if not firstBoundary:
                                    firstBoundary = True
                                    firstBoundaryValue = it

                                else:
                                    if it < firstBoundaryValue:
                                        it -= 1
                                    elif it > firstBoundaryValue:
                                        it += 1
                                inc = 2
                        except IndexError:
                            continue

                        it = it + inc
        pm.progressWindow(e=True, endProgress=True)

        # Eye Mesh skinning
        skinCluster = skin.getSkinCluster(eyeMesh)
        if not skinCluster:
            skinCluster = pm.skinCluster(eyeCenter_jnt,
                                         eyeMesh,
                                         tsb=True,
                                         nw=1,
                                         n='skinClsEye')
Example #19
0
    def addOperators(self):
        """Create operators and set the relations for the component rig

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return
Example #20
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
            o_node = applyop.gear_inverseRotorder_op(bk_ctl, fk_ctl)
            pm.connectAttr(o_node + ".output", bk_loc.attr("ro"))
            pm.connectAttr(fk_ctl.attr("ro"), fk_loc.attr("ro"))
            attribute.lockAttribute(bk_ctl, "ro")

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

            neg_node = node.createMulNode([addx_node + ".output",
                                          addy_node + ".output",
                                          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
Example #21
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.

        """
        # Tangent position ---------------------------------
        # common part
        d = vector.getDistance(self.guide.pos["root"], self.guide.pos["neck"])
        dist_node = node.createDistNode(self.root, self.ik_ctl)
        rootWorld_node = node.createDecomposeMatrixNode(
            self.root.attr("worldMatrix"))
        div_node = node.createDivNode(dist_node + ".distance",
                                      rootWorld_node + ".outputScaleX")
        div_node = node.createDivNode(div_node + ".outputX", d)

        # tan0
        mul_node = node.createMulNode(self.tan0_att,
                                      self.tan0_loc.getAttr("ty"))
        res_node = node.createMulNode(mul_node + ".outputX",
                                      div_node + ".outputX")
        pm.connectAttr(res_node + ".outputX", self.tan0_loc + ".ty")

        # tan1
        mul_node = node.createMulNode(self.tan1_att,
                                      self.tan1_loc.getAttr("ty"))
        res_node = node.createMulNode(mul_node + ".outputX",
                                      div_node + ".outputX")
        pm.connectAttr(res_node + ".outputX", self.tan1_loc.attr("ty"))

        # Curves -------------------------------------------
        op = applyop.gear_curveslide2_op(self.slv_crv, self.mst_crv, 0, 1.5,
                                         .5, .5)
        pm.connectAttr(self.maxstretch_att, op + ".maxstretch")
        pm.connectAttr(self.maxsquash_att, op + ".maxsquash")
        pm.connectAttr(self.softness_att, op + ".softness")

        # Volume driver ------------------------------------
        crv_node = node.createCurveInfoNode(self.slv_crv)

        # Division -----------------------------------------
        for i in range(self.settings["division"]):

            # References
            u = i / (self.settings["division"] - 1.0)

            cns = applyop.pathCns(self.div_cns[i], self.slv_crv, False, u,
                                  True)
            cns.setAttr("frontAxis", 1)  # front axis is 'Y'
            cns.setAttr("upAxis", 2)  # front axis is 'Z'

            # Roll
            intMatrix = applyop.gear_intmatrix_op(
                self.intMRef + ".worldMatrix", self.ik_ctl + ".worldMatrix", u)
            dm_node = node.createDecomposeMatrixNode(intMatrix + ".output")
            pm.connectAttr(dm_node + ".outputRotate",
                           self.twister[i].attr("rotate"))

            pm.parentConstraint(self.twister[i],
                                self.ref_twist[i],
                                maintainOffset=True)

            pm.connectAttr(self.ref_twist[i] + ".translate",
                           cns + ".worldUpVector")

            # Squash n Stretch
            op = applyop.gear_squashstretch2_op(self.fk_npo[i], self.root,
                                                pm.arclen(self.slv_crv), "y")

            pm.connectAttr(self.volume_att, op + ".blend")
            pm.connectAttr(crv_node + ".arcLength", op + ".driver")
            pm.connectAttr(self.st_att[i], op + ".stretch")
            pm.connectAttr(self.sq_att[i], op + ".squash")
            op.setAttr("driver_min", .1)

            # scl compas
            if i != 0:
                div_node = node.createDivNode([1, 1, 1], [
                    self.fk_npo[i - 1] + ".sx", self.fk_npo[i - 1] + ".sy",
                    self.fk_npo[i - 1] + ".sz"
                ])

                pm.connectAttr(div_node + ".output",
                               self.scl_npo[i] + ".scale")

            # Controlers
            if i == 0:
                mulmat_node = applyop.gear_mulmatrix_op(
                    self.div_cns[i].attr("worldMatrix"),
                    self.root.attr("worldInverseMatrix"))
            else:
                mulmat_node = applyop.gear_mulmatrix_op(
                    self.div_cns[i].attr("worldMatrix"),
                    self.div_cns[i - 1].attr("worldInverseMatrix"))

            dm_node = node.createDecomposeMatrixNode(mulmat_node + ".output")
            pm.connectAttr(dm_node + ".outputTranslate",
                           self.fk_npo[i].attr("t"))
            pm.connectAttr(dm_node + ".outputRotate", self.fk_npo[i].attr("r"))

            # Orientation Lock
            if i == self.settings["division"] - 1:
                dm_node = node.createDecomposeMatrixNode(self.ik_ctl +
                                                         ".worldMatrix")
                blend_node = node.createBlendNode(
                    [dm_node + ".outputRotate%s" % s for s in "XYZ"],
                    [cns + ".rotate%s" % s for s in "XYZ"], self.lock_ori_att)
                self.div_cns[i].attr("rotate").disconnect()

                pm.connectAttr(blend_node + ".output",
                               self.div_cns[i] + ".rotate")

        # Head ---------------------------------------------
        self.fk_ctl[-1].addChild(self.head_cns)

        # scale compensation
        dm_node = node.createDecomposeMatrixNode(self.scl_npo[0] +
                                                 ".parentInverseMatrix")

        pm.connectAttr(dm_node + ".outputScale", self.scl_npo[0] + ".scale")
Example #22
0
    def addOperators(self):

        # Tangent position ---------------------------------
        # common part
        d = vec.getDistance(self.guide.pos["root"], self.guide.pos["neck"])
        dist_node = nod.createDistNode(self.root, self.ik_ctl)
        rootWorld_node = nod.createDecomposeMatrixNode(self.root.attr("worldMatrix"))
        div_node = nod.createDivNode(dist_node+".distance", rootWorld_node+".outputScaleX")
        div_node = nod.createDivNode(div_node+".outputX", d)

        # tan0
        mul_node = nod.createMulNode(self.tan0_att, self.tan0_loc.getAttr("ty"))
        res_node = nod.createMulNode(mul_node+".outputX", div_node+".outputX")
        connectAttr( res_node+".outputX", self.tan0_loc+".ty")

        # tan1
        mul_node = nod.createMulNode(self.tan1_att, self.tan1_loc.getAttr("ty"))
        res_node = nod.createMulNode(mul_node+".outputX", div_node+".outputX")
        connectAttr( res_node+".outputX", self.tan1_loc.attr("ty"))

        # Curves -------------------------------------------
        op = aop.gear_curveslide2_op(self.slv_crv, self.mst_crv, 0, 1.5, .5, .5)
        connectAttr(self.maxstretch_att, op+".maxstretch")
        connectAttr(self.maxsquash_att, op+".maxsquash")
        connectAttr(self.softness_att, op+".softness")

        # Volume driver ------------------------------------
        crv_node = nod.createCurveInfoNode(self.slv_crv)

        # Division -----------------------------------------
        for i in range(self.settings["division"]):

            # References
            u = i / (self.settings["division"] - 1.0)

            cns = aop.pathCns(self.div_cns[i], self.slv_crv, False, u, True)
            cns.setAttr("frontAxis", 1)# front axis is 'Y'
            cns.setAttr("upAxis", 2)# front axis is 'Z'

            # Roll
            aop.gear_spinePointAtOp(cns, self.root, self.ik_ctl, u, "Z")

            # Squash n Stretch
            op = aop.gear_squashstretch2_op(self.fk_npo[i], self.root, arclen(self.slv_crv), "y")
            connectAttr(self.volume_att, op+".blend")
            connectAttr(crv_node+".arcLength", op+".driver")
            connectAttr(self.st_att[i], op+".stretch")
            connectAttr(self.sq_att[i], op+".squash")

            # scl compas
            if i != 0:
                div_node = nod.createDivNode([1,1,1], [self.fk_npo[i-1]+".sx", self.fk_npo[i-1]+".sy", self.fk_npo[i-1]+".sz"])
                connectAttr(div_node+".output", self.scl_npo[i]+".scale")

            # Controlers
            if i == 0:
                mulmat_node = aop.gear_mulmatrix_op(self.div_cns[i].attr("worldMatrix"), self.root.attr("worldInverseMatrix"))
            else:
                mulmat_node = aop.gear_mulmatrix_op(self.div_cns[i].attr("worldMatrix"), self.div_cns[i-1].attr("worldInverseMatrix"))

            dm_node = nod.createDecomposeMatrixNode(mulmat_node+".output")
            connectAttr(dm_node+".outputTranslate", self.fk_npo[i].attr("t"))
            connectAttr(dm_node+".outputRotate", self.fk_npo[i].attr("r"))
            #connectAttr(dm_node+".outputScale", self.fk_npo[i].attr("s"))

            # Orientation Lock
            if i == self.settings["division"] - 1 :
                dm_node = nod.createDecomposeMatrixNode(self.ik_ctl+".worldMatrix")
                blend_node = nod.createBlendNode([dm_node+".outputRotate%s"%s for s in "XYZ"], [cns+".rotate%s"%s for s in "XYZ"], self.lock_ori_att)
                self.div_cns[i].attr("rotate").disconnect()
                connectAttr(blend_node+".output", self.div_cns[i]+".rotate")


        # Head ---------------------------------------------
        self.fk_ctl[-1].addChild(self.head_cns)