コード例 #1
0
def createJntTweak(mesh, jntParent, ctlParent):
    """Create a joint tweak

    Args:
        mesh (mesh): The object to deform with the tweak
        jntParent (dagNode): The parent for the new joint
        ctlParent (dagNode): The parent for the control.
    """
    if not isinstance(mesh, list):
        mesh = [mesh]

    name = "_".join(jntParent.name().split("_")[:3])

    # create joints
    jointBase = primitive.addJoint(jntParent,
                                   name + "_tweak_jnt_lvl",
                                   jntParent.getMatrix(worldSpace=True))
    resetJntLocalSRT(jointBase)
    joint = primitive.addJoint(jointBase,
                               name + "_tweak_jnt",
                               jntParent.getMatrix(worldSpace=True))
    resetJntLocalSRT(joint)

    # hiding joint base by changing the draw mode
    # pm.setAttr(jointBase+".drawStyle", 2)

    try:
        defSet = pm.PyNode("rig_deformers_grp")
    except TypeError:
        pm.sets(n="rig_deformers_grp")
        defSet = pm.PyNode("rig_deformers_grp")
    pm.sets(defSet, add=joint)

    controlType = "circle"
    iconBase = icon.create(ctlParent,
                           name + "_base_tweak_ctl",
                           ctlParent.getMatrix(worldSpace=True),
                           13,
                           controlType,
                           w=.8,
                           ro=datatypes.Vector(0, 0, 1.5708))

    attribute.addAttribute(iconBase, "isCtl", "bool", keyable=False)

    o_icon = icon.create(iconBase, name + "_tweak_ctl",
                         ctlParent.getMatrix(worldSpace=True),
                         17,
                         controlType,
                         w=.5,
                         ro=datatypes.Vector(0, 0, 1.5708))

    attribute.addAttribute(o_icon, "isCtl", "bool", keyable=False)

    for t in [".translate", ".scale", ".rotate"]:
        pm.connectAttr(iconBase + t, jointBase + t)
        pm.connectAttr(o_icon + t, joint + t)

    # magic of doritos connection
    for m in mesh:
        pre_bind_matrix_connect(m, joint, jointBase)
コード例 #2
0
def addJointTransformFromPos(parent, name, pos=datatypes.Vector(0, 0, 0)):
    """Create a transform dagNode.

    Arguments:
        parent (dagNode): The parent for the node.
        name (str): The Node name.
        pos (vector): The vector for the node position (optional).

    Returns:
        dagNode: The newly created node.

    """
    node = primitive.addJoint(parent, name)
    node.setAttr("drawStyle", 2)  # draw none
    for shape in node.getShapes():
        pm.delete(shape)
    node.setTranslation(pos, space="world")

    return node
コード例 #3
0
def addJointTransform(parent, name, m=datatypes.Matrix()):
    """Create a transform dagNode.

    Arguments:
        parent (dagNode): The parent for the node.
        name (str): The Node name.
        m (matrix): The matrix for the node transformation (optional).

    Returns:
        dagNode: The newly created node.

    """
    # node = pm.PyNode(pm.createNode("transform", n=name))
    # node.setTransformation(m)
    node = primitive.addJoint(parent, name, m)
    node.setAttr("drawStyle", 2)  # draw none
    for shape in node.getShapes():
        pm.delete(shape)

    return node
コード例 #4
0
def createRivetTweakLayer(layerMesh,
                          bst,
                          edgePairList,
                          name,
                          parent=None,
                          ctlParent=None,
                          jntParent=None,
                          color=[0, 0, 0],
                          size=.04,
                          defSet=None,
                          ctlSet=None,
                          side=None,
                          mirror=False,
                          mParent=None,
                          mCtlParent=None,
                          mjntParent=None,
                          mColor=None,
                          gearMulMatrix=True,
                          static_jnt=None,
                          attach_rot=False,
                          inputMesh=None):
    """Create a rivet tweak layer setup

    Args:
        layerMesh (mesh): The tweak layer mesh
        bst (mesh): The mesh blendshape target
        edgePairList (list of list): The edge pair list of list
        name (str): The name for the tweak
        parent (None or dagNode, optional): The parent for the tweak
        jntParent (None or dagNode, optional): The parent for the joints
        ctlParent (None or dagNode, optional): The parent for the tweak control
        color (list, optional): The color for the control
        size (float, optional): Size of the control
        defSet (None or set, optional): Deformer set to add the joints
        ctlSet (None or set, optional): the set to add the controls
        side (None, str): String to set the side. Valid values are L, R or C.
            If the side is not set or the value is not valid, the side will be
            set automatically based on the world position
        mirror (bool, optional): Create the mirror tweak on X axis symmetry
        mParent (None, optional): Mirror tweak parent, if None will use
            parent arg
        mjntParent (None, optional): Mirror  parent joint, if None will use
            jntParent arg
        mCtlParent (None, optional): Mirror ctl parent, if None will use
            ctlParent arg
        mColor (None, optional): Mirror controls color, if None will color arg
        gearMulMatrix (bool, optional): If False will use Maya default multiply
            matrix node
        static_jnt (dagNode, optional): Static joint for the setup
    """

    # Apply blendshape from blendshapes layer mesh
    blendShapes.connectWithBlendshape(layerMesh, bst)

    # create static joint

    if not static_jnt:
        if pm.objExists('static_jnt') is not True:
            static_jnt = primitive.addJoint(parent,
                                            "static_jnt",
                                            m=datatypes.Matrix(),
                                            vis=True)
        else:
            static_jnt = pm.PyNode("static_jnt")

    # apply initial skincluster
    pm.skinCluster(static_jnt,
                   layerMesh,
                   tsb=True,
                   nw=2,
                   n='%s_skinCluster' % layerMesh.name())

    # create doritos
    if not mParent:
        mParent = parent
    if not mCtlParent:
        mCtlParent = ctlParent
    if not mColor:
        mColor = color
    if not mjntParent:
        mjntParent = jntParent

    createRivetTweakFromList(layerMesh,
                             edgePairList,
                             name,
                             parent=parent,
                             ctlParent=ctlParent,
                             jntParent=jntParent,
                             color=color,
                             size=size,
                             defSet=defSet,
                             ctlSet=ctlSet,
                             side=side,
                             mirror=mirror,
                             mParent=mParent,
                             mCtlParent=mCtlParent,
                             mjntParent=mjntParent,
                             mColor=mColor,
                             gearMulMatrix=gearMulMatrix,
                             attach_rot=attach_rot,
                             inputMesh=inputMesh)
コード例 #5
0
def createRivetTweak(mesh,
                     edgePair,
                     name,
                     parent=None,
                     ctlParent=None,
                     jntParent=None,
                     color=[0, 0, 0],
                     size=.04,
                     defSet=None,
                     ctlSet=None,
                     side=None,
                     gearMulMatrix=True,
                     attach_rot=False,
                     inputMesh=None):
    """Create a tweak joint attached to the mesh using a rivet

    Args:
        mesh (mesh): The object to add the tweak
        edgePair (pair list): The edge pair to create the rivet
        name (str): The name for the tweak
        parent (None or dagNode, optional): The parent for the tweak
        jntParent (None or dagNode, optional): The parent for the joints
        ctlParent (None or dagNode, optional): The parent for the tweak control
        color (list, optional): The color for the control
        size (float, optional): Size of the control
        defSet (None or set, optional): Deformer set to add the joints
        ctlSet (None or set, optional): the set to add the controls
        side (None, str): String to set the side. Valid values are L, R or C.
            If the side is not set or the value is not valid, the side will be
            set automatically based on the world position
        gearMulMatrix (bool, optional): If False will use Maya default multiply
            matrix node

    Returns:
        PyNode: The tweak control
    """
    blendShape = blendShapes.getBlendShape(mesh)
    if not inputMesh:
        inputMesh = blendShape.listConnections(sh=True, t="shape", d=False)[0]

    oRivet = rivet.rivet()
    base = oRivet.create(inputMesh, edgePair[0], edgePair[1], parent)
    # get side
    if not side or side not in ["L", "R", "C"]:
        if base.getTranslation(space='world')[0] < -0.01:
            side = "R"
        elif base.getTranslation(space='world')[0] > 0.01:
            side = "L"
        else:
            side = "C"

    nameSide = name + "_tweak_" + side
    pm.rename(base, nameSide)

    if not ctlParent:
        ctlParent = base
        ctl_parent_tag = None
    else:
        ctl_parent_tag = ctlParent

    # Joints NPO
    npo = pm.PyNode(pm.createNode("transform",
                                  n=nameSide + "_npo",
                                  p=ctlParent,
                                  ss=True))
    if attach_rot:
        # npo.setTranslation(base.getTranslation(space="world"), space="world")
        pm.parentConstraint(base, npo, mo=False)
    else:
        pm.pointConstraint(base, npo, mo=False)

    # create joints
    if not jntParent:
        jntParent = npo
        matrix_cnx = False
    else:
        # need extra connection to ensure is moving with th npo, even is
        # not child of npo
        matrix_cnx = True

    jointBase = primitive.addJoint(jntParent, nameSide + "_jnt_lvl")
    joint = primitive.addJoint(jointBase, nameSide + "_jnt")

    # reset axis and invert behaviour
    for axis in "XYZ":
        pm.setAttr(jointBase + ".jointOrient" + axis, 0)
        pm.setAttr(npo + ".translate" + axis, 0)
        # pm.setAttr(jointBase + ".translate" + axis, 0)

    pp = npo.getParent()
    pm.parent(npo, w=True)
    for axis in "xyz":
        npo.attr("r" + axis).set(0)
    if side == "R":
        npo.attr("ry").set(180)
        npo.attr("sz").set(-1)
    pm.parent(npo, pp)

    dm_node = None

    if matrix_cnx:
        mulmat_node = applyop.gear_mulmatrix_op(
            npo + ".worldMatrix", jointBase + ".parentInverseMatrix")
        dm_node = node.createDecomposeMatrixNode(
            mulmat_node + ".output")
        m = mulmat_node.attr('output').get()
        pm.connectAttr(dm_node + ".outputTranslate", jointBase + ".t")
        pm.connectAttr(dm_node + ".outputRotate", jointBase + ".r")

        # invert negative scaling in Joints. We only inver Z axis, so is
        # the only axis that we are checking
        print(dm_node.attr("outputScaleZ").get())
        if dm_node.attr("outputScaleZ").get() < 0:
            mul_nod_invert = node.createMulNode(
                dm_node.attr("outputScaleZ"),
                -1)
            out_val = mul_nod_invert.attr("outputX")
        else:
            out_val = dm_node.attr("outputScaleZ")

        pm.connectAttr(dm_node.attr("outputScaleX"), jointBase + ".sx")
        pm.connectAttr(dm_node.attr("outputScaleY"), jointBase + ".sy")
        pm.connectAttr(out_val, jointBase + ".sz")
        pm.connectAttr(dm_node + ".outputShear", jointBase + ".shear")

        # Segment scale compensate Off to avoid issues with the global
        # scale
        jointBase.setAttr("segmentScaleCompensate", 0)
        joint.setAttr("segmentScaleCompensate", 0)

        jointBase.setAttr("jointOrient", 0, 0, 0)

        # setting the joint orient compensation in order to have clean
        # rotation channels
        jointBase.attr("jointOrientX").set(jointBase.attr("rx").get())
        jointBase.attr("jointOrientY").set(jointBase.attr("ry").get())
        jointBase.attr("jointOrientZ").set(jointBase.attr("rz").get())

        im = m.inverse()

        if gearMulMatrix:
            mul_nod = applyop.gear_mulmatrix_op(
                mulmat_node.attr('output'), im, jointBase, 'r')
            dm_node2 = mul_nod.output.listConnections()[0]
        else:
            mul_nod = node.createMultMatrixNode(
                mulmat_node.attr('matrixSum'), im, jointBase, 'r')
            dm_node2 = mul_nod.matrixSum.listConnections()[0]

        if dm_node.attr("outputScaleZ").get() < 0:
            negateTransformConnection(dm_node2.outputRotate, jointBase.rotate)

    else:
        resetJntLocalSRT(jointBase)

    # hidding joint base by changing the draw mode
    pm.setAttr(jointBase + ".drawStyle", 2)
    if not defSet:
        try:
            defSet = pm.PyNode("rig_deformers_grp")
        except TypeError:
            pm.sets(n="rig_deformers_grp", empty=True)
            defSet = pm.PyNode("rig_deformers_grp")
    pm.sets(defSet, add=joint)

    controlType = "sphere"
    o_icon = icon.create(npo,
                         nameSide + "_ctl",
                         datatypes.Matrix(),
                         color,
                         controlType,
                         w=size)

    attribute.addAttribute(o_icon, "isCtl", "bool", keyable=False)

    transform.resetTransform(o_icon)
    if dm_node and dm_node.attr("outputScaleZ").get() < 0:
        pm.connectAttr(o_icon.scale, joint.scale)
        negateTransformConnection(o_icon.rotate, joint.rotate)
        negateTransformConnection(o_icon.translate,
                                  joint.translate,
                                  [1, 1, -1])

    else:
        for t in [".translate", ".scale", ".rotate"]:
            pm.connectAttr(o_icon + t, joint + t)

    # create the attributes to handlde mirror and symetrical pose
    attribute.addAttribute(
        o_icon, "invTx", "bool", 0, keyable=False, niceName="Invert Mirror TX")
    attribute.addAttribute(
        o_icon, "invTy", "bool", 0, keyable=False, niceName="Invert Mirror TY")
    attribute.addAttribute(
        o_icon, "invTz", "bool", 0, keyable=False, niceName="Invert Mirror TZ")
    attribute.addAttribute(
        o_icon, "invRx", "bool", 0, keyable=False, niceName="Invert Mirror RX")
    attribute.addAttribute(
        o_icon, "invRy", "bool", 0, keyable=False, niceName="Invert Mirror RY")
    attribute.addAttribute(
        o_icon, "invRz", "bool", 0, keyable=False, niceName="Invert Mirror RZ")
    attribute.addAttribute(
        o_icon, "invSx", "bool", 0, keyable=False, niceName="Invert Mirror SX")
    attribute.addAttribute(
        o_icon, "invSy", "bool", 0, keyable=False, niceName="Invert Mirror SY")
    attribute.addAttribute(
        o_icon, "invSz", "bool", 0, keyable=False, niceName="Invert Mirror SZ")

    # magic of doritos connection
    pre_bind_matrix_connect(mesh, joint, jointBase)

    # add control tag
    node.add_controller_tag(o_icon, ctl_parent_tag)

    if not ctlSet:
        try:
            ctlSet = pm.PyNode("rig_controllers_grp")
        except TypeError:
            pm.sets(n="rig_controllers_grp", empty=True)
            ctlSet = pm.PyNode("rig_controllers_grp")
    pm.sets(ctlSet, add=o_icon)

    return o_icon
コード例 #6
0
    def addJoint(self,
                 obj,
                 name,
                 newActiveJnt=None,
                 UniScale=False,
                 segComp=0,
                 gearMulMatrix=True):
        """Add joint as child of the active joint or under driver object.

        Args:
            obj (dagNode): The input driver object for the joint.
            name (str): The joint name.
            newActiveJnt (bool or dagNode): If a joint is pass, this joint will
                be the active joint and parent of the newly created joint.
            UniScale (bool): Connects the joint scale with the Z axis for a
                unifor scalin, if set Falsewill connect with each axis
                separated.
            segComp (bool): Set True or False the segment compensation in the
                joint..
            gearMulMatrix (bool): Use the custom gear_multiply matrix node, if
                False will use Maya's default mulMatrix node.

        Returns:
            dagNode: The newly created joint.

        """

        customName = self.getCustomJointName(len(self.jointList))

        if self.options["joint_rig"]:
            if newActiveJnt:
                self.active_jnt = newActiveJnt

            jnt = primitive.addJoint(self.active_jnt, 
                customName or self.getName(str(name) + "_jnt"), 
                transform.getTransform(obj))

            # Disconnect inversScale for better preformance
            if isinstance(self.active_jnt, pm.nodetypes.Joint):
                try:
                    pm.disconnectAttr(self.active_jnt.scale, jnt.inverseScale)

                except RuntimeError:
                    # This handle the situation where we have in between joints
                    # transformation due a negative scaling
                    pm.ungroup(jnt.getParent())
            # All new jnts are the active by default
            self.active_jnt = jnt

            if gearMulMatrix:
                mulmat_node = applyop.gear_mulmatrix_op(
                    obj + ".worldMatrix", jnt + ".parentInverseMatrix")
                dm_node = node.createDecomposeMatrixNode(
                    mulmat_node + ".output")
                m = mulmat_node.attr('output').get()
            else:
                mulmat_node = node.createMultMatrixNode(
                    obj + ".worldMatrix", jnt + ".parentInverseMatrix")
                dm_node = node.createDecomposeMatrixNode(
                    mulmat_node + ".matrixSum")
                m = mulmat_node.attr('matrixSum').get()
            pm.connectAttr(dm_node + ".outputTranslate", jnt + ".t")
            pm.connectAttr(dm_node + ".outputRotate", jnt + ".r")
            # TODO: fix squash stretch solver to scale the joint uniform
            # the next line cheat the uniform scaling only fo X or Y axis
            # oriented joints
            if self.options["force_uniScale"]:
                UniScale = True

            # invert negative scaling in Joints. We only inver Z axis, so is
            # the only axis that we are checking
            if dm_node.attr("outputScaleZ").get() < 0:
                mul_nod_invert = node.createMulNode(
                    dm_node.attr("outputScaleZ"),
                    -1)
                out_val = mul_nod_invert.attr("outputX")
            else:
                out_val = dm_node.attr("outputScaleZ")

            # connect scaling
            if UniScale:
                pm.connectAttr(out_val, jnt + ".sx")
                pm.connectAttr(out_val, jnt + ".sy")
                pm.connectAttr(out_val, jnt + ".sz")
            else:
                pm.connectAttr(dm_node.attr("outputScaleX"), jnt + ".sx")
                pm.connectAttr(dm_node.attr("outputScaleY"), jnt + ".sy")
                pm.connectAttr(out_val, jnt + ".sz")
                pm.connectAttr(dm_node + ".outputShear", jnt + ".shear")

            # Segment scale compensate Off to avoid issues with the global
            # scale
            jnt.setAttr("segmentScaleCompensate", segComp)

            jnt.setAttr("jointOrient", 0, 0, 0)

            # setting the joint orient compensation in order to have clean
            # rotation channels
            jnt.attr("jointOrientX").set(jnt.attr("rx").get())
            jnt.attr("jointOrientY").set(jnt.attr("ry").get())
            jnt.attr("jointOrientZ").set(jnt.attr("rz").get())

            im = m.inverse()

            if gearMulMatrix:
                mul_nod = applyop.gear_mulmatrix_op(
                    mulmat_node.attr('output'), im, jnt, 'r')
                dm_node2 = mul_nod.output.listConnections()[0]
            else:
                mul_nod = node.createMultMatrixNode(
                    mulmat_node.attr('matrixSum'), im, jnt, 'r')
                dm_node2 = mul_nod.matrixSum.listConnections()[0]

            # if jnt.attr("sz").get() < 0:
            if dm_node.attr("outputScaleZ").get() < 0:
                # if negative scaling we have to negate some axis for rotation
                neg_rot_node = pm.createNode("multiplyDivide")
                pm.setAttr(neg_rot_node + ".operation", 1)
                pm.connectAttr(dm_node2.outputRotate,
                               neg_rot_node + ".input1",
                               f=True)
                for v, axis in zip([-1, -1, 1], "XYZ"):
                    pm.setAttr(neg_rot_node + ".input2" + axis, v)
                pm.connectAttr(neg_rot_node + ".output",
                               jnt + ".r",
                               f=True)

            # set not keyable
            attribute.setNotKeyableAttributes(jnt)

        else:
            jnt = primitive.addJoint(obj, 
                customName or self.getName(str(name) + "_jnt"), 
                transform.getTransform(obj))
            pm.connectAttr(self.rig.jntVis_att, jnt.attr("visibility"))
            attribute.lockAttribute(jnt)

        self.addToGroup(jnt, "deformers")

        # This is a workaround due the evaluation problem with compound attr
        # TODO: This workaround, should be removed onces the evaluation issue
        # is fixed
        # github issue: Shifter: Joint connection: Maya evaluation Bug #210
        dm = jnt.r.listConnections(p=True, type="decomposeMatrix")
        if dm:
            at = dm[0]
            dm_node = at.node()
            pm.disconnectAttr(at, jnt.r)
            pm.connectAttr(dm_node.outputRotateX, jnt.rx)
            pm.connectAttr(dm_node.outputRotateY, jnt.ry)
            pm.connectAttr(dm_node.outputRotateZ, jnt.rz)

        dm = jnt.t.listConnections(p=True, type="decomposeMatrix")
        if dm:
            at = dm[0]
            dm_node = at.node()
            pm.disconnectAttr(at, jnt.t)
            pm.connectAttr(dm_node.outputTranslateX, jnt.tx)
            pm.connectAttr(dm_node.outputTranslateY, jnt.ty)
            pm.connectAttr(dm_node.outputTranslateZ, jnt.tz)

        # dm = jnt.s.listConnections(p=True, type="decomposeMatrix")
        # if dm:
        #     at = dm[0]
        #     dm_node = at.node()
        #     pm.disconnectAttr(at, jnt.s)
        #     pm.connectAttr(dm_node.outputScaleX, jnt.sx)
        #     pm.connectAttr(dm_node.outputScaleY, jnt.sy)
        #     pm.connectAttr(dm_node.outputScaleZ, jnt.sz)

        return jnt
コード例 #7
0
    def addObjects(self):
        """Add all the objects needed to create the component."""

        self.setup = primitive.addTransformFromPos(
            self.setupWS, self.getName("WS"))
        attribute.lockAttribute(self.setup)

        self.WIP = self.options["mode"]

        self.normal = self.getNormalFromPos(self.guide.apos)

        self.length0 = vector.getDistance(self.guide.apos[0],
                                          self.guide.apos[1])
        self.length1 = vector.getDistance(self.guide.apos[1],
                                          self.guide.apos[2])
        self.length2 = vector.getDistance(self.guide.apos[2],
                                          self.guide.apos[3])
        self.length3 = vector.getDistance(self.guide.apos[3],
                                          self.guide.apos[4])

        # 3bones chain
        self.chain3bones = primitive.add2DChain(
            self.setup,
            self.getName("chain3bones%s_jnt"),
            self.guide.apos[0:4],
            self.normal,
            False,
            self.WIP)

        # 2bones chain
        self.chain2bones = primitive.add2DChain(
            self.setup,
            self.getName("chain2bones%s_jnt"),
            self.guide.apos[0:3],
            self.normal,
            False,
            self.WIP)

        # Leg chain
        self.legBones = primitive.add2DChain(
            self.root,
            self.getName("legBones%s_jnt"),
            self.guide.apos[0:4],
            self.normal,
            False,
            self.WIP)

        # Leg chain FK ref
        self.legBonesFK = primitive.add2DChain(
            self.root,
            self.getName("legFK%s_jnt"),
            self.guide.apos[0:4],
            self.normal,
            False,
            self.WIP)

        # Leg chain IK ref
        self.legBonesIK = primitive.add2DChain(
            self.root,
            self.getName("legIK%s_jnt"),
            self.guide.apos[0:4],
            self.normal,
            False,
            self.WIP)

        # 1 bone chain for upv ref
        self.legChainUpvRef = primitive.add2DChain(
            self.root,
            self.getName("legUpvRef%s_jnt"),
            [self.guide.apos[0], self.guide.apos[3]],
            self.normal,
            False,
            self.WIP)

        # mid joints
        self.mid1_jnt = primitive.addJoint(
            self.legBones[0],
            self.getName("mid1_jnt"),
            self.legBones[1].getMatrix(worldSpace=True),
            self.WIP)

        self.mid1_jnt.attr("radius").set(3)
        self.mid1_jnt.setAttr("jointOrient", 0, 0, 0)

        self.mid2_jnt = primitive.addJoint(
            self.legBones[1],
            self.getName("mid2_jnt"),
            self.legBones[2].getMatrix(worldSpace=True),
            self.WIP)

        self.mid2_jnt.attr("radius").set(3)
        self.mid2_jnt.setAttr("jointOrient", 0, 0, 0)

        # base Controlers -----------------------------------
        t = transform.getTransformFromPos(self.guide.apos[0])
        self.root_npo = primitive.addTransform(
            self.root, self.getName("root_npo"), t)

        self.root_ctl = self.addCtl(self.root_npo,
                                    "root_ctl",
                                    t,
                                    self.color_fk,
                                    "circle",
                                    w=self.length0 / 6,
                                    tp=self.parentCtlTag)
        attribute.lockAttribute(self.root_ctl, ["sx", "sy", "sz", "v"])

        # FK Controlers -----------------------------------
        t = transform.getTransformLookingAt(self.guide.apos[0],
                                            self.guide.apos[1],
                                            self.normal,
                                            "xz",
                                            self.negate)

        self.fk0_npo = primitive.addTransform(
            self.root_ctl, self.getName("fk0_npo"), t)

        self.fk0_ctl = self.addCtl(
            self.fk0_npo,
            "fk0_ctl",
            t,
            self.color_fk,
            "cube",
            w=self.length0,
            h=self.size * .1,
            d=self.size * .1,
            po=datatypes.Vector(.5 * self.length0 * self.n_factor, 0, 0),
            tp=self.root_ctl)
        attribute.setKeyableAttributes(self.fk0_ctl)

        t = transform.getTransformLookingAt(self.guide.apos[1],
                                            self.guide.apos[2],
                                            self.normal,
                                            "xz",
                                            self.negate)
        self.fk1_npo = primitive.addTransform(
            self.fk0_ctl, self.getName("fk1_npo"), t)
        self.fk1_ctl = self.addCtl(
            self.fk1_npo,
            "fk1_ctl",
            t,
            self.color_fk,
            "cube",
            w=self.length1,
            h=self.size * .1,
            d=self.size * .1,
            po=datatypes.Vector(.5 * self.length1 * self.n_factor, 0, 0),
            tp=self.fk0_ctl)
        attribute.setKeyableAttributes(self.fk1_ctl)

        t = transform.getTransformLookingAt(self.guide.apos[2],
                                            self.guide.apos[3],
                                            self.normal,
                                            "xz",
                                            self.negate)

        self.fk2_npo = primitive.addTransform(
            self.fk1_ctl, self.getName("fk2_npo"), t)

        self.fk2_ctl = self.addCtl(
            self.fk2_npo,
            "fk2_ctl",
            t,
            self.color_fk,
            "cube",
            w=self.length2,
            h=self.size * .1,
            d=self.size * .1,
            po=datatypes.Vector(.5 * self.length2 * self.n_factor, 0, 0),
            tp=self.fk1_ctl)

        attribute.setKeyableAttributes(self.fk2_ctl)

        t = transform.getTransformLookingAt(self.guide.apos[3],
                                            self.guide.apos[4],
                                            self.normal,
                                            "xz",
                                            self.negate)

        self.fk3_npo = primitive.addTransform(
            self.fk2_ctl, self.getName("fk3_npo"), t)

        self.fk3_ctl = self.addCtl(
            self.fk3_npo,
            "fk3_ctl",
            t,
            self.color_fk,
            "cube",
            w=self.length3,
            h=self.size * .1,
            d=self.size * .1,
            po=datatypes.Vector(.5 * self.length3 * self.n_factor, 0, 0),
            tp=self.fk2_ctl)

        attribute.setKeyableAttributes(self.fk3_ctl)

        self.fk_ctl = [self.fk0_ctl, self.fk1_ctl, self.fk2_ctl, self.fk3_ctl]

        for x in self.fk_ctl:
            attribute.setInvertMirror(x, ["tx", "ty", "tz"])

        # Mid Controlers ------------------------------------
        self.knee_lvl = primitive.addTransform(
            self.root,
            self.getName("knee_lvl"),
            transform.getTransform(self.mid1_jnt))

        self.knee_ctl = self.addCtl(
            self.knee_lvl,
            "knee_ctl",
            transform.getTransform(self.mid1_jnt),
            self.color_ik,
            "sphere",
            w=self.size * .2,
            tp=self.root_ctl)

        attribute.setInvertMirror(self.knee_ctl, ["tx", "ty", "tz"])
        attribute.lockAttribute(self.knee_ctl, ["sx", "sy", "sz", "v"])

        self.ankle_lvl = primitive.addTransform(
            self.root,
            self.getName("ankle_lvl"),
            transform.getTransform(self.mid2_jnt))

        self.ankle_ctl = self.addCtl(
            self.ankle_lvl,
            "ankle_ctl",
            transform.getTransform(self.mid2_jnt),
            self.color_ik,
            "sphere",
            w=self.size * .2,
            tp=self.knee_ctl)

        attribute.setInvertMirror(self.ankle_ctl, ["tx", "ty", "tz"])
        attribute.lockAttribute(self.ankle_ctl, ["sx", "sy", "sz", "v"])

        # IK controls --------------------------------------------------------

        # foot IK

        # "z-x",
        t_align = transform.getTransformLookingAt(self.guide.apos[3],
                                                  self.guide.apos[4],
                                                  self.normal,
                                                  "zx",
                                                  False)

        if self.settings["ikOri"]:
            t = transform.getTransformFromPos(self.guide.pos["foot"])
            # t = transform.getTransformLookingAt(self.guide.pos["foot"],
            #                                     self.guide.pos["eff"],
            #                                     self.x_axis,
            #                                     "zx",
            #                                     False)
        else:
            t = t_align

        self.ik_cns = primitive.addTransform(
            self.root_ctl, self.getName("ik_cns"), t)

        self.ikcns_ctl = self.addCtl(self.ik_cns,
                                     "ikcns_ctl",
                                     t,
                                     self.color_ik,
                                     "null",
                                     w=self.size * .12,
                                     tp=self.ankle_ctl)

        attribute.setInvertMirror(self.ikcns_ctl, ["tx"])
        attribute.lockAttribute(self.ikcns_ctl, ["sx", "sy", "sz", "v"])

        self.ik_ctl = self.addCtl(self.ikcns_ctl,
                                  "ik_ctl",
                                  t,
                                  self.color_ik,
                                  "cube",
                                  w=self.size * .12,
                                  h=self.size * .12,
                                  d=self.size * .12,
                                  tp=self.ikcns_ctl)
        attribute.setKeyableAttributes(self.ik_ctl)
        attribute.setRotOrder(self.ik_ctl, "XZY")
        attribute.setInvertMirror(self.ik_ctl, ["tx", "ry", "rz"])
        attribute.lockAttribute(self.ik_ctl, ["sx", "sy", "sz", "v"])

        # 2 bones ik layer
        self.ik2b_ikCtl_ref = primitive.addTransform(
            self.ik_ctl, self.getName("ik2B_A_ref"), t_align)
        self.ik2b_bone_ref = primitive.addTransform(
            self.chain3bones[3], self.getName("ik2B_B_ref"), t_align)
        self.ik2b_blend = primitive.addTransform(
            self.ik_ctl, self.getName("ik2B_blend"), t_align)

        self.roll_ctl = self.addCtl(self.ik2b_blend,
                                    "roll_ctl",
                                    t_align,
                                    self.color_ik,
                                    "crossarrow",
                                    w=self.length2 * .5 * self.n_factor,
                                    tp=self.ik_ctl)

        self.ik2b_ik_npo = primitive.addTransform(
            self.roll_ctl,
            self.getName("ik2B_ik_npo"),
            transform.getTransform(self.chain3bones[-1]))

        self.ik2b_ik_ref = primitive.addTransformFromPos(
            self.ik2b_ik_npo,
            self.getName("ik2B_ik_ref"),
            self.guide.pos["ankle"])

        attribute.lockAttribute(
            self.roll_ctl, ["tx", "ty", "tz", "sx", "sy", "sz", "v"])

        # upv
        v = self.guide.apos[2] - self.guide.apos[0]
        v = self.normal ^ v
        v.normalize()
        v *= self.size * .5
        v += self.guide.apos[1]

        self.upv_lvl = primitive.addTransformFromPos(
            self.root, self.getName("upv_lvl"), v)
        self.upv_cns = primitive.addTransformFromPos(
            self.upv_lvl, self.getName("upv_cns"), v)

        self.upv_ctl = self.addCtl(self.upv_cns,
                                   "upv_ctl",
                                   transform.getTransform(self.upv_cns),
                                   self.color_ik,
                                   "diamond",
                                   w=self.size * .12,
                                   tp=self.ik_ctl)

        attribute.setInvertMirror(self.upv_ctl, ["tx"])
        attribute.setKeyableAttributes(self.upv_ctl, ["tx", "ty", "tz"])

        # Soft IK objects 3 bones chain --------------------------------
        t = transform.getTransformLookingAt(self.guide.pos["root"],
                                            self.guide.pos["foot"],
                                            self.x_axis,
                                            "zx",
                                            False)

        self.aim_tra = primitive.addTransform(
            self.root_ctl, self.getName("aimSoftIK"), t)

        t = transform.getTransformFromPos(self.guide.pos["foot"])
        self.wristSoftIK = primitive.addTransform(
            self.aim_tra, self.getName("wristSoftIK"), t)

        self.softblendLoc = primitive.addTransform(
            self.root, self.getName("softblendLoc"), t)

        # Soft IK objects 2 Bones chain ----------------------------
        t = transform.getTransformLookingAt(self.guide.pos["root"],
                                            self.guide.pos["ankle"],
                                            self.x_axis,
                                            "zx",
                                            False)

        self.aim_tra2 = primitive.addTransform(
            self.root_ctl, self.getName("aimSoftIK2"), t)

        t = transform.getTransformFromPos(self.guide.pos["ankle"])

        self.ankleSoftIK = primitive.addTransform(
            self.aim_tra2, self.getName("ankleSoftIK"), t)

        self.softblendLoc2 = primitive.addTransform(
            self.root, self.getName("softblendLoc2"), t)

        # References --------------------------------------
        self.ik_ref = primitive.addTransform(
            self.ik_ctl,
            self.getName("ik_ref"),
            transform.getTransform(self.ik_ctl))

        self.fk_ref = primitive.addTransform(
            self.fk_ctl[3],
            self.getName("fk_ref"),
            transform.getTransform(self.ik_ctl))

        # twist references --------------------------------------
        self.rollRef = primitive.add2DChain(self.root,
                                            self.getName("rollChain"),
                                            self.guide.apos[:2],
                                            self.normal,
                                            False,
                                            self.WIP)

        self.tws0_loc = primitive.addTransform(
            self.rollRef[0],
            self.getName("tws0_loc"),
            transform.getTransform(self.legBones[0]))

        self.tws0_rot = primitive.addTransform(
            self.tws0_loc,
            self.getName("tws0_rot"),
            transform.getTransform(self.legBones[0]))

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

        self.tws1_loc = primitive.addTransform(
            self.mid1_jnt,
            self.getName("tws1_loc"),
            transform.getTransform(self.mid1_jnt))

        self.tws1_rot = primitive.addTransform(
            self.tws1_loc,
            self.getName("tws1_rot"),
            transform.getTransform(self.mid1_jnt))

        self.tws1_rot.setAttr("sx", .001)

        self.tws2_loc = primitive.addTransform(
            self.mid2_jnt,
            self.getName("tws2_loc"),
            transform.getTransform(self.mid2_jnt))

        self.tws2_rot = primitive.addTransform(
            self.tws2_loc,
            self.getName("tws2_rot"),
            transform.getTransform(self.mid2_jnt))

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

        self.tws3_loc = primitive.addTransform(
            self.legBones[3],
            self.getName("tws3_loc"),
            transform.getTransform(self.legBones[3]))

        self.tws3_rot = primitive.addTransform(
            self.tws3_loc,
            self.getName("tws3_rot"),
            transform.getTransform(self.legBones[3]))

        self.tws3_rot.setAttr("sx", .001)

        # Divisions ----------------------------------------
        # We have at least one division at the start, the end and one for
        # the knee and one ankle
        o_set = self.settings
        self.divisions = o_set["div0"] + o_set["div1"] + o_set["div2"] + 4

        self.div_cns = []
        for i in range(self.divisions):
            div_cns = primitive.addTransform(self.root_ctl,
                                             self.getName("div%s_loc" % i))
            self.div_cns.append(div_cns)
            self.jnt_pos.append([div_cns, i])

        # End reference ------------------------------------
        # To help the deformation on the foot
        self.end_ref = primitive.addTransform(
            self.tws3_rot,
            self.getName("end_ref"),
            transform.getTransform(self.legBones[3]))
        self.jnt_pos.append([self.end_ref, 'end'])

        # match IK FK references
        self.match_fk0_off = primitive.addTransform(
            self.root,
            self.getName("matchFk0_npo"),
            transform.getTransform(self.fk_ctl[1]))

        self.match_fk0 = primitive.addTransform(
            self.match_fk0_off,
            self.getName("fk0_mth"),
            transform.getTransform(self.fk_ctl[0]))

        self.match_fk1_off = primitive.addTransform(
            self.root,
            self.getName("matchFk1_npo"),
            transform.getTransform(self.fk_ctl[2]))

        self.match_fk1 = primitive.addTransform(
            self.match_fk1_off,
            self.getName("fk1_mth"),
            transform.getTransform(self.fk_ctl[1]))

        self.match_fk2_off = primitive.addTransform(
            self.root,
            self.getName("matchFk2_npo"),
            transform.getTransform(self.fk_ctl[3]))

        self.match_fk2 = primitive.addTransform(
            self.match_fk2_off,
            self.getName("fk2_mth"),
            transform.getTransform(self.fk_ctl[2]))

        self.match_fk3 = primitive.addTransform(
            self.ik_ctl,
            self.getName("fk3_mth"),
            transform.getTransform(self.fk_ctl[3]))

        self.match_ik = primitive.addTransform(
            self.fk3_ctl,
            self.getName("ik_mth"),
            transform.getTransform(self.ik_ctl))

        self.match_ikUpv = primitive.addTransform(
            self.fk0_ctl,
            self.getName("upv_mth"),
            transform.getTransform(self.upv_ctl))

        # add visual reference
        self.line_ref = icon.connection_display_curve(
            self.getName("visalRef"), [self.upv_ctl, self.knee_ctl])
コード例 #8
0
def addJnt(obj=False,
           parent=False,
           noReplace=False,
           grp=None,
           jntName=None,
           *args):
    """Create one joint for each selected object.

    Args:
        obj (bool or dagNode, optional): The object to drive the new
            joint. If False will use the current selection.
        parent (bool or dagNode, optional): The parent for the joint.
            If False will try to parent to jnt_org. If jnt_org doesn't
            exist will parent the joint under the obj
        noReplace (bool, optional): If True will add the extension
            "_jnt" to the new joint name
        grp (pyNode or None, optional): The set to add the new joint.
            If none will use "rig_deformers_grp"
        *args: Maya's dummy

    Returns:
        pyNode: The New created joint.

    """
    if not obj:
        oSel = pm.selected()
    else:
        oSel = [obj]

    for obj in oSel:
        if not parent:
            try:
                oParent = pm.PyNode("jnt_org")
            except TypeError:
                oParent = obj
        else:
            oParent = parent
        if not jntName:
            if noReplace:
                jntName = "_".join(obj.name().split("_")) + "_jnt"
            else:
                jntName = "_".join(obj.name().split("_")[:-1]) + "_jnt"
        jnt = primitive.addJoint(oParent, jntName, transform.getTransform(obj))

        if grp:
            grp.add(jnt)
        else:
            try:
                defSet = pm.PyNode("rig_deformers_grp")
                pm.sets(defSet, add=jnt)
            except TypeError:
                pm.sets(n="rig_deformers_grp")
                defSet = pm.PyNode("rig_deformers_grp")
                pm.sets(defSet, add=jnt)

        jnt.setAttr("segmentScaleCompensate", False)
        jnt.setAttr("jointOrient", 0, 0, 0)
        try:
            cns_m = applyop.gear_matrix_cns(obj, jnt)
            # setting the joint orient compensation in order to have clean
            # rotation channels
            m = cns_m.drivenRestMatrix.get()
            tm = datatypes.TransformationMatrix(m)
            r = datatypes.degrees(tm.getRotation())
            jnt.attr("jointOrientX").set(r[0])
            jnt.attr("jointOrientY").set(r[1])
            jnt.attr("jointOrientZ").set(r[2])
        except RuntimeError:
            for axis in ["tx", "ty", "tz", "rx", "ry", "rz"]:
                jnt.attr(axis).set(0.0)

    return jnt
コード例 #9
0
def addJointCtl(self,
                parent,
                name,
                m,
                color,
                iconShape,
                tp=None,
                lp=True,
                mirrorConf=[0, 0, 0, 0, 0, 0, 0, 0, 0],
                guide_loc_ref=None,
                **kwargs):
    """
    Create the control and apply the shape, if this is alrealdy stored
    in the guide controllers grp.

    Args:
        parent (dagNode): The control parent
        name (str): The control name.
        m (matrix): The transfromation matrix for the control.
        color (int or list of float): The color for the control in index or
            RGB.
        iconShape (str): The controls default shape.
        tp (dagNode): Tag Parent Control object to connect as a parent
            controller
        lp (bool): Lock the parent controller channels
        kwargs (variant): Other arguments for the iconShape type variations

    Returns:
        dagNode: The Control.

    """
    if "degree" not in kwargs.keys():
        kwargs["degree"] = 1

    # print name
    # fullName = self.getName(name)

    # remove the _ctl hardcoded in component name
    if name.endswith("_ctl"):
        name = name[:-4]
    # in some situation the name will be only ctl and should be removed
    # for example control_01
    if name.endswith("ctl"):
        name = name[:-3]

    # NOTE: this is a dirty workaround to keep backwards compatibility on
    # control_01 component where the description of the cotrol was just
    # the ctl suffix.
    rule = self.options["ctl_name_rule"]
    if not name:
        """
        if rule == naming.DEFAULT_NAMING_RULE:
            rule = r"{component}_{side}{index}_{extension}"
        else:
            # this ensure we always have name if the naming rule is custom
            name = "control"
        """
        rule = r"{component}_{side}{index}_{extension}"

    fullName = self.getName(
        name,
        rule=rule,
        ext="ctl",
        letter_case=self.options["ctl_description_letter_case"])

    bufferName = fullName + "_controlBuffer"
    if bufferName in self.rig.guide.controllers.keys():
        ctl_ref = self.rig.guide.controllers[bufferName]
    else:
        ctl_ref = icon.create(parent, fullName + "ref", m, color, iconShape,
                              **kwargs)

    ctl = primitive.addJoint(parent, fullName, m)
    ctl.setAttr("drawStyle", 2)  # draw none
    for shape in ctl_ref.getShapes():
        ctl.addChild(shape, shape=True, add=True)
        pm.rename(shape, fullName + "Shape")

    pm.delete(ctl_ref)
    icon.setcolor(ctl, color)

    # add metadata attirbutes.
    attribute.addAttribute(ctl, "isCtl", "bool", keyable=False)
    attribute.addAttribute(ctl, "uiHost", "string", keyable=False)
    ctl.addAttr("uiHost_cnx", at='message', multi=False)
    # set the control Role for complex components. If the component is
    # of type control_01 or world_ctl the control role will default to None
    # since is only one control the role is not needed
    attribute.addAttribute(ctl,
                           "ctl_role",
                           "string",
                           keyable=False,
                           value=name)

    # locator reference for quick guide matching
    # TODO: this is a temporal implementation. We should store the full
    # guide data in future iterations
    if guide_loc_ref:
        attribute.addAttribute(ctl,
                               "guide_loc_ref",
                               "string",
                               keyable=False,
                               value=guide_loc_ref)

    # mgear name. This keep track of the default shifter name. This naming
    # system ensure that each control has a unique id. Tools like mirror or
    # flip pose can use it to track symmetrical controls
    attribute.addAttribute(ctl,
                           "shifter_name",
                           "string",
                           keyable=False,
                           value=self.getName(name) + "_ctl")
    attribute.addAttribute(ctl,
                           "side_label",
                           "string",
                           keyable=False,
                           value=self.side)
    attribute.addAttribute(ctl,
                           "L_custom_side_label",
                           "string",
                           keyable=False,
                           value=self.options["side_left_name"])
    attribute.addAttribute(ctl,
                           "R_custom_side_label",
                           "string",
                           keyable=False,
                           value=self.options["side_right_name"])
    attribute.addAttribute(ctl,
                           "C_custom_side_label",
                           "string",
                           keyable=False,
                           value=self.options["side_center_name"])

    # create the attributes to handlde mirror and symetrical pose
    attribute.add_mirror_config_channels(ctl, mirrorConf)

    if self.settings["ctlGrp"]:
        ctlGrp = self.settings["ctlGrp"]
        self.addToGroup(ctl, ctlGrp, "controllers")
    else:
        ctlGrp = "controllers"
        self.addToGroup(ctl, ctlGrp)

    # lock the control parent attributes if is not a control
    if parent not in self.groups[ctlGrp] and lp:
        self.transform2Lock.append(parent)

    # Set the control shapes isHistoricallyInteresting
    for oShape in ctl.getShapes():
        oShape.isHistoricallyInteresting.set(False)
        # connecting the always draw shapes on top to global attribute
        if versions.current() >= 20220000:
            pm.connectAttr(self.rig.ctlXRay_att,
                           oShape.attr("alwaysDrawOnTop"))

    # set controller tag
    if versions.current() >= 201650:
        try:
            oldTag = pm.PyNode(ctl.name() + "_tag")
            if not oldTag.controllerObject.connections():
                # NOTE:  The next line is comment out. Because this will
                # happend alot since core does't clean
                # controller tags after deleting the control Object of the
                # tag. This have been log to Autodesk.
                # If orphane tags are found, it will be clean in silence.
                # pm.displayWarning("Orphane Tag: %s  will be delete and
                # created new for: %s"%(oldTag.name(), ctl.name()))
                pm.delete(oldTag)

        except TypeError:
            pass

        self.add_controller_tag(ctl, tp)
    self.controlers.append(ctl)

    return ctl