Example #1
0
    def addEyeTrackingAttributes(self):

        up_ctl = self.upControls[2]
        low_ctl = self.lowControls[3]

        # Adding channels for eye tracking
        upVTracking_att  = attribute.addAttribute(up_ctl,  "vTracking", "float", self.upperVTrack, minValue=0, keyable=False, channelBox=True)
        upHTracking_att  = attribute.addAttribute(up_ctl,  "hTracking", "float", self.upperHTrack, minValue=0, keyable=False, channelBox=True)

        lowVTracking_att = attribute.addAttribute(low_ctl, "vTracking", "float", self.lowerVTrack, minValue=0, keyable=False, channelBox=True)
        lowHTracking_att = attribute.addAttribute(low_ctl, "hTracking", "float", self.lowerHTrack, minValue=0, keyable=False, channelBox=True)

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

        # Correct right side horizontal tracking
        if self.negate:
            pass
            # mult_node = node.createMulNode(mult_node.attr("outputX"), -1)

        pm.connectAttr(mult_node + ".outputX", self.trackLvl[0].attr("tx"))

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

        # Correct right side horizontal tracking
        if self.negate:
            pass
            # mult_node = node.createMulNode(mult_node.attr("outputX"), -1)

        pm.connectAttr(mult_node + ".outputX", self.trackLvl[1].attr("tx"))
Example #2
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)
    def addAttributes(self):
        # Ref
        if self.settings["ikrefarray"]:
            ref_names = self.get_valid_alias_list(
                self.settings["ikrefarray"].split(","))
            if len(ref_names) > 1:
                self.ikref_att = self.addAnimEnumParam("ikref", "Ik Ref", 0,
                                                       ref_names)

        # Identifiers
        # SDK Box -----------------------
        self.SDK_att = attribute.addAttribute(node=self.SDKctl,
                                              longName="is_SDK",
                                              attributeType="bool",
                                              value=True,
                                              keyable=False)

        self.SDKroot_att = attribute.addAttribute(node=self.SDKctl,
                                                  longName="ctl",
                                                  attributeType="string",
                                                  value="",
                                                  keyable=False)

        # Anim ctl -----------------------
        self.ctl_att = attribute.addAttribute(node=self.ctl,
                                              longName="is_tweak",
                                              attributeType="bool",
                                              value=True,
                                              keyable=False)

        self.ctlroot_att = attribute.addAttribute(node=self.ctl,
                                                  longName="sdk",
                                                  attributeType="string",
                                                  value="",
                                                  keyable=False)
Example #4
0
def source_nodes():
    cmds.file(new=True, force=True)

    pcs = pm.polyCube(name="armUI_R0_ctl")
    pcs2 = pm.polyCube(name="armUI_R1_ctl")
    attribute.addAttribute(pcs[0],
                           "shoulder_ik",
                           "double",
                           0,
                           minValue=0,
                           maxValue=1)
    ch2 = attribute.addAttribute(pcs[0],
                                 "shoulder_rotRef",
                                 "double",
                                 0,
                                 minValue=0,
                                 maxValue=1)
    ch3 = attribute.addAttribute(pcs2[0],
                                 "shoulder_rotRef",
                                 "double",
                                 0,
                                 minValue=0,
                                 maxValue=1)
    pm.connectAttr(ch2, pcs[0].ty)
    pm.connectAttr(ch3, pcs2[0].ty)
Example #5
0
def createCTL(type="square", child=False, *args):
    """Create a control for each selected object.

    The newly create control can be parent or child of the object.

    Args:
        type (str): The shape of the control.
        child (bool): if True, the control will be created as a
            child of the object.

    """
    iconList = []
    if child:
        if len(pm.selected()) > 0:
            for x in pm.selected():
                oChilds = [
                    item for item in x.listRelatives(ad=True, type="transform")
                    if item.longName().split("|")[-2] == x.name()
                ]

                o_icon = icon.create(None,
                                     x.name() + "_ctl", None, [1, 0, 0], type)
                iconList.append(o_icon)
                o_icon.setTransformation(x.getMatrix(worldSpace=True))
                pm.parent(o_icon, x)
                for child in oChilds:

                    pm.parent(child, o_icon)
        else:

            o_icon = icon.create(None, type + "_ctl", datatypes.Matrix(),
                                 [1, 0, 0], type)
            iconList.append(o_icon)
    else:
        if len(pm.selected()) > 0:
            for x in pm.selected():
                oParent = x.getParent()
                o_icon = icon.create(oParent,
                                     x.name() + "_ctl", x.getMatrix(),
                                     [1, 0, 0], type)
                iconList.append(o_icon)
                o_icon.setTransformation(x.getMatrix())
                pm.parent(x, o_icon)
        else:

            o_icon = icon.create(None, type + "_ctl", datatypes.Matrix(),
                                 [1, 0, 0], type)
            iconList.append(o_icon)

    for ico in iconList:
        attribute.addAttribute(ico, "isCtl", "bool", keyable=False)

    try:
        defSet = pm.PyNode("rig_controllers_grp")
        for ico in iconList:
            pm.sets(defSet, add=ico)
    except TypeError:
        print("No rig_controllers_grp found")
        pass
Example #6
0
    def run(self, stepDict):

        root = stepDict["mgearRun"].model
        geo_root = stepDict["init_base"].geo_root

        attribute.addAttribute(root, "geoUnselectable", "bool", True)

        pm.connectAttr(root.geoUnselectable, geo_root.attr("overrideEnabled"))
        geo_root.attr("overrideDisplayType").set(2)
Example #7
0
    def addBlade(self, name, parentPos, parentDir):
        """Add a blade object to the guide.

        This mehod can initialize the object or draw it.
        Blade object is a 3points curve to define a plan in the guide.

        Args:
            name (str): Local name of the element.
            parentPos (dagNode): The parent of the element.
            parentDir (dagNode): The direction constraint of the element.

        Returns:
            dagNode:  The created blade curve.

        """
        if name not in self.blades.keys():
            self.blades[name] = vector.Blade(
                transform.getTransformFromPos(datatypes.Vector(0, 0, 0)))
            offset = False
        else:
            offset = True

        blade = icon.guideBladeIcon(parent=parentPos,
                                    name=self.getName(name),
                                    lenX=.5,
                                    color=[0, 0, 1],
                                    m=self.blades[name].transform)
        aim_cns = applyop.aimCns(blade,
                                 parentDir,
                                 axis="xy",
                                 wupType=2,
                                 wupVector=[0, 1, 0],
                                 wupObject=self.root,
                                 maintainOffset=offset)
        pnt_cns = pm.pointConstraint(parentPos, blade)

        aim_cns.isHistoricallyInteresting.set(False)
        pnt_cns.isHistoricallyInteresting.set(False)

        offsetAttr = attribute.addAttribute(blade, "bladeRollOffset", "float",
                                            aim_cns.attr("offsetX").get())
        pm.connectAttr(offsetAttr, aim_cns.attr("offsetX"))
        scaleAttr = attribute.addAttribute(blade,
                                           "bladeScale",
                                           "float",
                                           1,
                                           minValue=0.1,
                                           maxValue=100)
        for axis in "xyz":
            pm.connectAttr(scaleAttr, blade.attr("s{}".format(axis)))
        attribute.lockAttribute(blade,
                                attributes=[
                                    "tx", "ty", "tz", "rx", "ry", "rz", "sx",
                                    "sy", "sz", "v", "ro"
                                ])

        return blade
Example #8
0
    def set_ui_host_components_controls(self):
        """Set a list of all controls that are common to the ui host"""

        # creates a usable string list
        controls_string = ""
        for ctl in self.controlers:
            controls_string += "{},".format(ctl.name())

        # adds the attribute
        attribute.addAttribute(node=self.uihost, longName="{}_{}{}_ctl"
                               .format(self.name, self.side, self.index),
                               attributeType="string", keyable=False,
                               value=controls_string)
Example #9
0
 def add_collected_data_to_root_jnt(self):
     """Add collected data to root joint
     Root joint is the first joint generated in the rig.
     """
     root_jnt = None
     for c in self.componentsIndex:
         comp = self.customStepDic["mgearRun"].components[c]
         if not root_jnt and comp.jointList:
             root_jnt = comp.jointList[0]
             attribute.addAttribute(root_jnt,
                                    "collected_data",
                                    "string",
                                    str(json.dumps(self.build_data)))
             break
Example #10
0
    def addCtl(self, parent, name, m, color, iconShape, **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.
            kwargs (variant): Other arguments for the iconShape type variations

        Returns:
            dagNode: The Control.

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

        bufferName = name + "_controlBuffer"
        if bufferName in self.guide.controllers.keys():
            ctl_ref = self.guide.controllers[bufferName]
            ctl = primitive.addTransform(parent, name, m)
            for shape in ctl_ref.getShapes():
                ctl.addChild(shape, shape=True, add=True)
                pm.rename(shape, name + "Shape")
        else:
            ctl = icon.create(parent, name, m, color, iconShape, **kwargs)

        self.addToGroup(ctl, "controllers")

        # 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.ctlXRay_att, oShape.attr("alwaysDrawOnTop")
                )

        # set controller tag
        if versions.current() >= 201650:
            pm.controller(ctl)
            self.add_controller_tag(ctl, None)

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

        return ctl
Example #11
0
    def addAnimParam(self, longName, niceName, attType, value, minValue=None,
                     maxValue=None, keyable=True, readable=True, storable=True,
                     writable=True, uihost=None):
        """Add a parameter to the animation property.

        Note that animatable and keyable are True per default.

        Args:
            longName (str): The attribute name.
            niceName (str): The attribute nice name. (optional)
            attType (str): The Attribute Type.Exp:'string', 'bool', 'long', etc
            value (float or int): The default value.
            minValue (float or int): minimum value. (optional)
            maxValue (float or int): maximum value. (optional)
            keyable (bool): Set if the attribute is keyable or not. (optional)
            readable (bool): Set if the attribute is readable or not.(optional)
            storable (bool): Set if the attribute is storable or not.(optional)
            writable (bool): Set if the attribute is writable or not.(optional)
            uihost (dagNode): Optional uihost, if none self.uihost will be use

        Returns:
            str: The long name of the new attribute

        """
        if not uihost:
            uihost = self.uihost

        if self.options["classicChannelNames"]:
            attr = attribute.addAttribute(uihost, self.getName(longName),
                                          attType, value, niceName, None,
                                          minValue=minValue, maxValue=maxValue,
                                          keyable=keyable, readable=readable,
                                          storable=storable, writable=writable)
        else:
            if uihost.hasAttr(self.getCompName(longName)):
                attr = uihost.attr(self.getCompName(longName))
            else:
                attr = attribute.addAttribute(uihost,
                                              self.getCompName(longName),
                                              attType, value, niceName, None,
                                              minValue=minValue,
                                              maxValue=maxValue,
                                              keyable=keyable,
                                              readable=readable,
                                              storable=storable,
                                              writable=writable)

        return attr
Example #12
0
    def addSetupParam(self, longName, niceName, attType, value, minValue=None,
                      maxValue=None, keyable=True, readable=True,
                      storable=True, writable=True):
        """Add a parameter to the setup property.
        Note that animatable and keyable are False per default.

        Args:
            longName (str): The attribute name.
            niceName (str): The attribute nice name. (optional)
            attType (str): The Attribute Type. Exp: 'string', 'bool', etc..
            value (float or int): The default value.
            minValue (float or int): minimum value. (optional)
            maxValue (float or int): maximum value. (optional)
            keyable (bool): Set if the attribute is keyable or not.(optional)
            readable (bool): Set if the attribute is readable or not.(optional)
            storable (bool): Set if the attribute is storable or not.(optional)
            writable (bool): Set if the attribute is writable or not.(optional)

        Returns:
            str: The long name of the new attribute

        """
        attr = attribute.addAttribute(self.root, longName, attType, value,
                                      niceName, None, minValue=minValue,
                                      maxValue=maxValue, keyable=keyable,
                                      readable=readable, storable=storable,
                                      writable=writable)

        return attr
Example #13
0
def create_layer_node(name, affectedElements):
    """Create a transform node that contain the layer information.

    Args:
        name (str): layer name
        affectedElements (dagNode list): Elements affected by the layer.
                Only Mesh type is supported

    Returns:
        dagNode: layer node
    """

    fullName = name + "_crankLayer"

    # create node
    if pm.ls(fullName):
        pm.displayWarning("{} already exist".format(fullName))
        return
    layer_node = pm.createNode("transform",
                               n=fullName,
                               p=None,
                               ss=True)
    attribute.lockAttribute(layer_node)
    # add attrs
    attribute.addAttribute(
        layer_node, CRANK_TAG, "bool", False, keyable=False)
    # affected objects
    layer_node.addAttr("layer_objects", at='message', m=True)
    layer_node.addAttr("layer_blendshape_node", at='message', m=True)
    # master envelope for on/off
    attribute.addAttribute(layer_node,
                           "crank_layer_envelope",
                           "float",
                           value=1,
                           minValue=0,
                           maxValue=1)
    # create the post-blendshapes nodes for each affected object

    # connections
    for x in affectedElements:
        idx = attribute.get_next_available_index(layer_node.layer_objects)
        pm.connectAttr(x.message, layer_node.layer_objects[idx])

    return layer_node
def source_nodes():
    cmds.file(new=True, force=True)

    source1, _ = pm.polyCube(name="source1")
    source2, _ = pm.polyCube(name="source2")
    target, _ = pm.polyCube(name="target")

    ch1 = att.addAttribute(source1,
                           "chanName",
                           "double",
                           0,
                           minValue=0,
                           maxValue=1)
    ch2 = att.addAttribute(source2,
                           "chanName",
                           "double",
                           0,
                           minValue=0,
                           maxValue=1)

    pm.connectAttr(ch1, source1.ty)
    pm.connectAttr(ch2, source2.ty)
Example #15
0
    def addBlade(self, name, parentPos, parentDir):
        """Add a blade object to the guide.

        This mehod can initialize the object or draw it.
        Blade object is a 3points curve to define a plan in the guide.

        Args:
            name (str): Local name of the element.
            parentPos (dagNode): The parent of the element.
            parentDir (dagNode): The direction constraint of the element.

        Returns:
            dagNode:  The created blade curve.

        """
        if name not in self.blades.keys():
            self.blades[name] = vector.Blade(
                transform.getTransformFromPos(datatypes.Vector(0, 0, 0)))
            offset = False
        else:
            offset = True

        dist = .6 * self.root.attr("scaleX").get()
        blade = icon.guideBladeIcon(parent=parentPos,
                                    name=self.getName(name),
                                    lenX=dist,
                                    color=13,
                                    m=self.blades[name].transform)
        aim_cns = applyop.aimCns(blade,
                                 parentDir,
                                 axis="xy",
                                 wupType=2,
                                 wupVector=[0, 1, 0],
                                 wupObject=self.root,
                                 maintainOffset=offset)
        pm.pointConstraint(parentPos, blade)

        offsetAttr = attribute.addAttribute(blade, "bladeRollOffset", "float",
                                            aim_cns.attr("offsetX").get())
        pm.connectAttr(offsetAttr, aim_cns.attr("offsetX"))
        attribute.lockAttribute(blade)

        return blade
def characterizeBiped(*args):
    try:
        gCtl = pm.PyNode("global_C0_ctl")
        mocapAttach = att.addAttribute(
            gCtl,
            "mocapAttach",
            "float",
            1.0,
            minValue=0.0,
            maxValue=1.0
        )
    except Exception:
        pm.displayWarning("global_C0_ctl: Is not in the scene")
        return

    # Align skeleton
    for a, b in zip(skelFK, gearFK):
        try:
            oA = pm.PyNode(a)
        except Exception:
            pm.displayWarning(a + ": Is not in the scene")
        try:
            oB = pm.PyNode(b)
        except Exception:
            pm.displayWarning(b + ": Is not in the scene")
        tra.matchWorldTransform(oB, oA)

    # Constrain FK controls
    for a, b in zip(skelFK, gearFK):
        oA = pm.PyNode(a)
        oB = pm.PyNode(b)
        cns = pm.parentConstraint(oA, oB, mo=True)

        pb_node = pm.createNode("pairBlend")

        pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
        pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
        pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
        pm.connectAttr(pb_node + ".outRotateX", oB + ".rotateX", f=True)
        pm.connectAttr(pb_node + ".outRotateY", oB + ".rotateY", f=True)
        pm.connectAttr(pb_node + ".outRotateZ", oB + ".rotateZ", f=True)
        pm.setKeyframe(oB, at="rotateX")
        pm.setKeyframe(oB, at="rotateY")
        pm.setKeyframe(oB, at="rotateZ")

        pm.connectAttr(cns + ".constraintTranslateX",
                       pb_node + ".inTranslateX2")
        pm.connectAttr(cns + ".constraintTranslateY",
                       pb_node + ".inTranslateY2")
        pm.connectAttr(cns + ".constraintTranslateZ",
                       pb_node + ".inTranslateZ2")
        pm.connectAttr(pb_node + ".outTranslateX", oB + ".translateX", f=True)
        pm.connectAttr(pb_node + ".outTranslateY", oB + ".translateY", f=True)
        pm.connectAttr(pb_node + ".outTranslateZ", oB + ".translateZ", f=True)
        pm.setKeyframe(oB, at="translateX")
        pm.setKeyframe(oB, at="translateY")
        pm.setKeyframe(oB, at="translateZ")

        pm.connectAttr(mocapAttach, pb_node.attr("weight"))

    # Align IK controls with FK controls
    for a, b in zip(alignIK, alignFK):
        oA = pm.PyNode(a)
        oB = pm.PyNode(b)
        tra.matchWorldTransform(oB, oA)
        if a in [u"arm_L0_upv_ctl", u"arm_R0_upv_ctl"]:
            oA.attr("tz").set(-3)
        if a == u"arm_L0_ikcns_ctl":
            oA.attr("rx").set((oA.attr("rx").get() + 90))
        if a == u"arm_R0_ikcns_ctl":
            oA.attr("rx").set((oA.attr("rx").get() - 90))

    # constrain IK controls
    for a, b in zip(skelIK, gearIK):
        oA = pm.PyNode(a)
        oB = pm.PyNode(b)
        print b
        pb_node = pm.createNode("pairBlend")
        try:
            if b in (u"leg_L0_upv_ctl", u"leg_R0_upv_ctl"):
                att.lockAttribute(pm.PyNode(b), lock=False, keyable=True)
            if b in (u"leg_L0_mid_ctl",
                     u"leg_R0_mid_ctl",
                     u"arm_L0_mid_ctl",
                     u"arm_R0_mid_ctl"):
                cns = pm.pointConstraint(oA, oB, mo=True)
            else:
                cns = pm.parentConstraint(oA, oB, mo=True)
            pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
            pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
            pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
            pm.connectAttr(pb_node + ".outRotateX", oB + ".rotateX", f=True)
            pm.connectAttr(pb_node + ".outRotateY", oB + ".rotateY", f=True)
            pm.connectAttr(pb_node + ".outRotateZ", oB + ".rotateZ", f=True)
            pm.setKeyframe(oB, at="rotateX")
            pm.setKeyframe(oB, at="rotateY")
            pm.setKeyframe(oB, at="rotateZ")
        except Exception:
            cns = pm.pointConstraint(oA, oB, mo=True)

        pm.connectAttr(cns + ".constraintTranslateX",
                       pb_node + ".inTranslateX2")
        pm.connectAttr(cns + ".constraintTranslateY",
                       pb_node + ".inTranslateY2")
        pm.connectAttr(cns + ".constraintTranslateZ",
                       pb_node + ".inTranslateZ2")
        pm.connectAttr(pb_node + ".outTranslateX", oB + ".translateX", f=True)
        pm.connectAttr(pb_node + ".outTranslateY", oB + ".translateY", f=True)
        pm.connectAttr(pb_node + ".outTranslateZ", oB + ".translateZ", f=True)
        pm.setKeyframe(oB, at="translateX")
        pm.setKeyframe(oB, at="translateY")
        pm.setKeyframe(oB, at="translateZ")

        pm.connectAttr(mocapAttach, pb_node.attr("weight"))
Example #17
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
Example #18
0
    def initialHierarchy(self):
        """
        Create the inital structure for the rig.

        """
        # Root
        self.root = primitive.addTransformFromPos(
            self.model, self.getName("root"), self.guide.pos["root"])
        self.addToGroup(self.root, names=["componentsRoots"])

        # infos
        attribute.addAttribute(self.root, "componentType",
                               "string", self.guide.compType)
        attribute.addAttribute(self.root, "componentName",
                               "string", self.guide.compName)
        attribute.addAttribute(self.root, "componentVersion",
                               "string", str(self.guide.version)[1:-1])
        attribute.addAttribute(self.root, "componentAuthor",
                               "string", self.guide.author)
        attribute.addAttribute(self.root, "componentURL",
                               "string", self.guide.url)
        attribute.addAttribute(self.root, "componentEmail",
                               "string", self.guide.email)

        # joint --------------------------------
        if self.options["joint_rig"]:
            self.component_jnt_org = primitive.addTransform(
                self.rig.jnt_org, self.getName("jnt_org"))
            # The initial assigment of the active jnt and the parent relative
            # jnt is the same, later will be updated base in the user options
            self.active_jnt = self.component_jnt_org
            self.parent_relative_jnt = self.component_jnt_org

        return
Example #19
0
    def initialHierarchy(self):
        """Build the initial hierarchy of the rig.

        Create the rig model, the main properties,
        and a couple of base organisation nulls.
        Get the global size of the rig.

        """
        mgear.log("Initial Hierarchy")

        # --------------------------------------------------
        # Model
        self.model = primitive.addTransformFromPos(None,
                                                   self.options["rig_name"])
        attribute.lockAttribute(self.model)

        # --------------------------------------------------
        # INFOS
        self.isRig_att = attribute.addAttribute(self.model, "is_rig", "bool",
                                                True)
        self.rigName_att = attribute.addAttribute(self.model, "rig_name",
                                                  "string",
                                                  self.options["rig_name"])
        self.user_att = attribute.addAttribute(self.model, "user", "string",
                                               getpass.getuser())
        self.isWip_att = attribute.addAttribute(self.model, "wip", "bool",
                                                self.options["mode"] != 0)
        self.date_att = attribute.addAttribute(self.model, "date", "string",
                                               str(datetime.datetime.now()))
        self.mayaVersion_att = attribute.addAttribute(
            self.model, "maya_version", "string",
            str(pm.mel.eval("getApplicationVersionAsFloat")))
        self.gearVersion_att = attribute.addAttribute(self.model,
                                                      "gear_version", "string",
                                                      mgear.getVersion())
        self.synoptic_att = attribute.addAttribute(
            self.model, "synoptic", "string", str(self.options["synoptic"]))
        self.comments_att = attribute.addAttribute(
            self.model, "comments", "string", str(self.options["comments"]))
        self.ctlVis_att = attribute.addAttribute(self.model, "ctl_vis", "bool",
                                                 True)
        if versions.current() >= 201650:
            self.ctlVisPlayback_att = attribute.addAttribute(
                self.model, "ctl_vis_on_playback", "bool", True)
        self.jntVis_att = attribute.addAttribute(self.model, "jnt_vis", "bool",
                                                 True)

        self.qsA_att = attribute.addAttribute(self.model, "quickselA",
                                              "string", "")
        self.qsB_att = attribute.addAttribute(self.model, "quickselB",
                                              "string", "")
        self.qsC_att = attribute.addAttribute(self.model, "quickselC",
                                              "string", "")
        self.qsD_att = attribute.addAttribute(self.model, "quickselD",
                                              "string", "")
        self.qsE_att = attribute.addAttribute(self.model, "quickselE",
                                              "string", "")
        self.qsF_att = attribute.addAttribute(self.model, "quickselF",
                                              "string", "")

        self.rigGroups = self.model.addAttr("rigGroups", at='message', m=1)
        self.rigPoses = self.model.addAttr("rigPoses", at='message', m=1)
        self.rigCtlTags = self.model.addAttr("rigCtlTags", at='message', m=1)
        self.rigScriptNodes = self.model.addAttr("rigScriptNodes",
                                                 at='message',
                                                 m=1)

        # ------------------------- -------------------------
        # Global Ctl
        if self.options["worldCtl"]:
            if self.options["world_ctl_name"]:
                name = self.options["world_ctl_name"]
            else:
                name = "world_ctl"

            icon_shape = "circle"

        else:
            name = "global_C0_ctl"
            icon_shape = "crossarrow"

        self.global_ctl = self.addCtl(self.model,
                                      name,
                                      datatypes.Matrix(),
                                      self.options["C_color_fk"],
                                      icon_shape,
                                      w=10)
        attribute.setRotOrder(self.global_ctl, "ZXY")

        # Connect global visibility
        pm.connectAttr(self.ctlVis_att, self.global_ctl.attr("visibility"))
        if versions.current() >= 201650:
            pm.connectAttr(self.ctlVisPlayback_att,
                           self.global_ctl.attr("hideOnPlayback"))
        attribute.lockAttribute(self.global_ctl, ['v'])

        # --------------------------------------------------
        # Setup in world Space
        self.setupWS = primitive.addTransformFromPos(self.model, "setup")
        attribute.lockAttribute(self.setupWS)
        # --------------------------------------------------
        # Basic set of null
        if self.options["joint_rig"]:
            self.jnt_org = primitive.addTransformFromPos(self.model, "jnt_org")
            pm.connectAttr(self.jntVis_att, self.jnt_org.attr("visibility"))
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
Example #21
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)
    pm.connectAttr(tweakCtl.attr("surfaceMode"), sm[0].falloffMode)
    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 #22
0
    def addCtl(self,
               parent,
               name,
               m,
               color,
               iconShape,
               tp=None,
               lp=True,
               mirrorConf=[0, 0, 0, 0, 0, 0, 0, 0, 0],
               ** 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

        fullName = self.getName(name)
        bufferName = fullName + "_controlBuffer"
        if bufferName in self.rig.guide.controllers.keys():
            ctl_ref = self.rig.guide.controllers[bufferName]
            ctl = primitive.addTransform(parent, fullName, m)
            for shape in ctl_ref.getShapes():
                ctl.addChild(shape, shape=True, add=True)
                pm.rename(shape, fullName + "Shape")
            icon.setcolor(ctl, color)
        else:
            ctl = icon.create(
                parent, fullName, m, color, iconShape, **kwargs)

        # add metadata attirbutes.
        attribute.addAttribute(ctl, "isCtl", "bool", keyable=False)
        attribute.addAttribute(ctl, "uiHost", "string", keyable=False)

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

        # 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
Example #23
0
def add_frame_sculpt(layer_node, anim=False, keyf=[1, 0, 0, 1]):
    """Add a sculpt frame to each selected layer

    Args:
        layer_node (dagNode list):  ist of Crank layer node to add the
            sculpt frame
        anim (bool, optional): if True, will keyframe the sculpt frame in the
        specified range.
        keyf (list, optional):  Keyframe range configuration. EaseIn, pre hold,
        post hold and ease out
    """
    objs = layer_node.layer_objects.inputs()
    bs_node = layer_node.layer_blendshape_node.inputs()

    # ensure other targets are set to false the edit flag

    # get current frame
    cframe = int(pm.currentTime(query=True))

    # get valid name. Check if frame is ducplicated in layer
    frame_name = "frame_{}".format(str(cframe))
    i = 1
    while layer_node.hasAttr(frame_name):
        frame_name = "frame_{}_v{}".format(str(cframe), str(i))
        i += 1

    # create frame master channel
    master_chn = attribute.addAttribute(layer_node,
                                        frame_name,
                                        "float",
                                        value=1,
                                        minValue=0,
                                        maxValue=1)

    # keyframe in range the master channel
    if anim:
        # current frame
        pm.setKeyframe(master_chn,
                       t=[cframe],
                       v=1,
                       inTangentType="linear",
                       outTangentType="linear")

        # pre and post hold
        pre_hold = keyf[1]
        if pre_hold:
            pm.setKeyframe(master_chn,
                           t=[cframe - pre_hold],
                           v=1,
                           inTangentType="linear",
                           outTangentType="linear")

        post_hold = keyf[2]
        if post_hold:
            pm.setKeyframe(master_chn,
                           t=[cframe + post_hold],
                           v=1,
                           inTangentType="linear",
                           outTangentType="linear")

        # ease in and out
        if keyf[0]:
            ei = pre_hold + keyf[0]
            pm.setKeyframe(master_chn,
                           t=[cframe - ei],
                           v=0,
                           inTangentType="linear",
                           outTangentType="linear")
        if keyf[3]:
            eo = post_hold + keyf[3]
            pm.setKeyframe(master_chn,
                           t=[cframe + eo],
                           v=0,
                           inTangentType="linear",
                           outTangentType="linear")

    for obj, bsn in zip(objs, bs_node):
        dup = pm.duplicate(obj)[0]
        bst_name = "_".join([obj.name(), frame_name])
        pm.rename(dup, bst_name)
        indx = bsn.weight.getNumElements()
        pm.blendShape(bsn,
                      edit=True,
                      t=(obj, indx, dup, 1.0),
                      ts=True,
                      tc=True,
                      w=(indx, 1))
        pm.delete(dup)
        pm.blendShape(bsn, e=True, rtd=(0, indx))
        # is same as: bs.inputTarget[0].sculptTargetIndex.set(3)
        pm.sculptTarget(bsn, e=True, t=indx)

        # connect target to master channel
        pm.connectAttr(master_chn, bsn.attr(bst_name))
Example #24
0
def rig(edge_loop="",
        up_vertex="",
        low_vertex="",
        name_prefix="",
        thickness=0.3,
        do_skin=True,
        rigid_loops=5,
        falloff_loops=8,
        head_joint=None,
        jaw_joint=None,
        parent_node=None,
        control_name="ctl",
        upper_lip_ctl=None,
        lower_lip_ctl=None):

    ######
    # Var
    ######

    FRONT_OFFSET = .02
    NB_ROPE = 15

    ##################
    # Helper functions
    ##################
    def setName(name, side="C", idx=None):
        namesList = [name_prefix, side, name]
        if idx is not None:
            namesList[1] = side + str(idx)
        name = "_".join(namesList)
        return name

    ###############
    # Checkers
    ##############

    # Loop
    if edge_loop:
        try:
            edge_loop = [pm.PyNode(e) for e in edge_loop.split(",")]
        except pm.MayaNodeError:
            pm.displayWarning(
                "Some of the edges listed in edge loop can not be found")
            return
    else:
        pm.displayWarning("Please set the edge loop first")
        return

    # Vertex
    if up_vertex:
        try:
            up_vertex = pm.PyNode(up_vertex)
        except pm.MayaNodeError:
            pm.displayWarning("%s can not be found" % up_vertex)
            return
    else:
        pm.displayWarning("Please set the upper lip central vertex")
        return

    if low_vertex:
        try:
            low_vertex = pm.PyNode(low_vertex)
        except pm.MayaNodeError:
            pm.displayWarning("%s can not be found" % low_vertex)
            return
    else:
        pm.displayWarning("Please set the lower lip central vertex")
        return

    # skinnign data
    if do_skin:
        if not head_joint:
            pm.displayWarning("Please set the Head Jnt or unCheck Compute "
                              "Topological Autoskin")
            return
        else:
            try:
                head_joint = pm.PyNode(head_joint)
            except pm.MayaNodeError:
                pm.displayWarning(
                    "Head Joint: %s can not be found" % head_joint
                )
                return
        if not jaw_joint:
            pm.displayWarning("Please set the Jaw Jnt or unCheck Compute "
                              "Topological Autoskin")
            return
        else:
            try:
                jaw_joint = pm.PyNode(jaw_joint)
            except pm.MayaNodeError:
                pm.displayWarning("Jaw Joint: %s can not be found" % jaw_joint)
                return
    # check if the rig already exist in the current scene
    if pm.ls(setName("root")):
        pm.displayWarning("The object %s already exist in the scene. Please "
                          "choose another name prefix" % setName("root"))
        return

    #####################
    # Root creation
    #####################
    lips_root = primitive.addTransform(None, setName("root"))
    lipsCrv_root = primitive.addTransform(lips_root, setName("crvs"))
    lipsRope_root = primitive.addTransform(lips_root, setName("rope"))

    #####################
    # Geometry
    #####################
    geo = pm.listRelatives(edge_loop[0], parent=True)[0]

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

    #####################
    # Curves creation
    #####################

    # get extreme position using the outer loop
    extr_v = meshNavigation.getExtremeVertexFromLoop(edge_loop)
    upPos = extr_v[0]
    lowPos = extr_v[1]
    inPos = extr_v[2]
    outPos = extr_v[3]
    edgeList = extr_v[4]
    vertexList = extr_v[5]
    upPos = up_vertex
    lowPos = low_vertex

    # upper crv
    upLip_edgeRange = meshNavigation.edgeRangeInLoopFromMid(edgeList,
                                                            upPos,
                                                            inPos,
                                                            outPos)
    upCrv = curve.createCuveFromEdges(upLip_edgeRange,
                                      setName("upperLip"),
                                      parent=lipsCrv_root)
    # store the closest vertex by curv cv index. To be use fo the auto skining
    upLip_closestVtxList = []
    # offset upper lip Curve
    cvs = upCrv.getCVs(space="world")
    for i, cv in enumerate(cvs):

        closestVtx = meshNavigation.getClosestVertexFromTransform(geo, cv)
        upLip_closestVtxList.append(closestVtx)
        if i == 0:
            # we know the curv starts from right to left
            offset = [cv[0] - thickness, cv[1], cv[2] - thickness]
        elif i == len(cvs) - 1:
            offset = [cv[0] + thickness, cv[1], cv[2] - thickness]
        else:
            offset = [cv[0], cv[1] + thickness, cv[2]]
        upCrv.setCV(i, offset, space='world')

    # lower crv
    lowLip_edgeRange = meshNavigation.edgeRangeInLoopFromMid(edgeList,
                                                             lowPos,
                                                             inPos,
                                                             outPos)
    lowCrv = curve.createCuveFromEdges(lowLip_edgeRange,
                                       setName("lowerLip"),
                                       parent=lipsCrv_root)
    lowLip_closestVtxList = []
    # offset lower lip Curve
    cvs = lowCrv.getCVs(space="world")
    for i, cv in enumerate(cvs):
        closestVtx = meshNavigation.getClosestVertexFromTransform(geo, cv)
        lowLip_closestVtxList.append(closestVtx)
        if i == 0:
            # we know the curv starts from right to left
            offset = [cv[0] - thickness, cv[1], cv[2] - thickness]
        elif i == len(cvs) - 1:
            offset = [cv[0] + thickness, cv[1], cv[2] - thickness]
        else:
            # we populate the closest vertext list here to skipt the first
            # and latest point
            offset = [cv[0], cv[1] - thickness, cv[2]]
        lowCrv.setCV(i, offset, space='world')

    upCrv_ctl = curve.createCurveFromCurve(upCrv,
                                           setName("upCtl_crv"),
                                           nbPoints=7,
                                           parent=lipsCrv_root)
    lowCrv_ctl = curve.createCurveFromCurve(lowCrv,
                                            setName("lowCtl_crv"),
                                            nbPoints=7,
                                            parent=lipsCrv_root)

    upRope = curve.createCurveFromCurve(upCrv,
                                        setName("upRope_crv"),
                                        nbPoints=NB_ROPE,
                                        parent=lipsCrv_root)
    lowRope = curve.createCurveFromCurve(lowCrv,
                                         setName("lowRope_crv"),
                                         nbPoints=NB_ROPE,
                                         parent=lipsCrv_root)

    upCrv_upv = curve.createCurveFromCurve(upCrv,
                                           setName("upCrv_upv"),
                                           nbPoints=7,
                                           parent=lipsCrv_root)
    lowCrv_upv = curve.createCurveFromCurve(lowCrv,
                                            setName("lowCrv_upv"),
                                            nbPoints=7,
                                            parent=lipsCrv_root)

    upRope_upv = curve.createCurveFromCurve(upCrv,
                                            setName("upRope_upv"),
                                            nbPoints=NB_ROPE,
                                            parent=lipsCrv_root)
    lowRope_upv = curve.createCurveFromCurve(lowCrv,
                                             setName("lowRope_upv"),
                                             nbPoints=NB_ROPE,
                                             parent=lipsCrv_root)

    # offset upv curves

    for crv in [upCrv_upv, lowCrv_upv, upRope_upv, lowRope_upv]:
        cvs = crv.getCVs(space="world")
        for i, cv in enumerate(cvs):

            # we populate the closest vertext list here to skipt the first
            # and latest point
            offset = [cv[0], cv[1], cv[2] + FRONT_OFFSET]
            crv.setCV(i, offset, space='world')

    rigCrvs = [upCrv,
               lowCrv,
               upCrv_ctl,
               lowCrv_ctl,
               upRope,
               lowRope,
               upCrv_upv,
               lowCrv_upv,
               upRope_upv,
               lowRope_upv]

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

    ##################
    # Joints
    ##################

    lvlType = "transform"

    # upper joints
    upperJoints = []
    cvs = upCrv.getCVs(space="world")
    pm.progressWindow(title='Creating Upper Joints', progress=0, max=len(cvs))

    for i, cv in enumerate(cvs):
        pm.progressWindow(e=True,
                          step=1,
                          status='\nCreating Joint for  %s' % cv)
        oTransUpV = pm.PyNode(pm.createNode(
            lvlType,
            n=setName("upLipRopeUpv", idx=str(i).zfill(3)),
            p=lipsRope_root,
            ss=True))
        oTrans = pm.PyNode(
            pm.createNode(lvlType,
                          n=setName("upLipRope", idx=str(i).zfill(3)),
                          p=lipsRope_root, ss=True))

        oParam, oLength = curve.getCurveParamAtPosition(upRope, cv)
        uLength = curve.findLenghtFromParam(upRope, oParam)
        u = uLength / oLength

        applyop.pathCns(
            oTransUpV, upRope_upv, cnsType=False, u=u, tangent=False)

        cns = applyop.pathCns(
            oTrans, upRope, cnsType=False, u=u, tangent=False)

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

        pm.connectAttr(oTransUpV.attr("worldMatrix[0]"),
                       cns.attr("worldUpMatrix"))

        # getting joint parent
        if head_joint and isinstance(head_joint, (str, string_types)):
            try:
                j_parent = pm.PyNode(head_joint)
            except pm.MayaNodeError:
                j_parent = False
        elif head_joint and isinstance(head_joint, pm.PyNode):
            j_parent = head_joint
        else:
            j_parent = False

        jnt = rigbits.addJnt(oTrans, noReplace=True, parent=j_parent)
        upperJoints.append(jnt)
        pm.sets(defset, add=jnt)
    pm.progressWindow(e=True, endProgress=True)

    # lower joints
    lowerJoints = []
    cvs = lowCrv.getCVs(space="world")
    pm.progressWindow(title='Creating Lower Joints', progress=0, max=len(cvs))

    for i, cv in enumerate(cvs):
        pm.progressWindow(e=True,
                          step=1,
                          status='\nCreating Joint for  %s' % cv)
        oTransUpV = pm.PyNode(pm.createNode(
            lvlType,
            n=setName("lowLipRopeUpv", idx=str(i).zfill(3)),
            p=lipsRope_root,
            ss=True))

        oTrans = pm.PyNode(pm.createNode(
            lvlType,
            n=setName("lowLipRope", idx=str(i).zfill(3)),
            p=lipsRope_root,
            ss=True))

        oParam, oLength = curve.getCurveParamAtPosition(lowRope, cv)
        uLength = curve.findLenghtFromParam(lowRope, oParam)
        u = uLength / oLength

        applyop.pathCns(oTransUpV,
                        lowRope_upv,
                        cnsType=False,
                        u=u,
                        tangent=False)
        cns = applyop.pathCns(oTrans,
                              lowRope,
                              cnsType=False,
                              u=u,
                              tangent=False)

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

        pm.connectAttr(oTransUpV.attr("worldMatrix[0]"),
                       cns.attr("worldUpMatrix"))

        # getting joint parent
        if jaw_joint and isinstance(jaw_joint, (str, string_types)):
            try:
                j_parent = pm.PyNode(jaw_joint)
            except pm.MayaNodeError:
                pass
        elif jaw_joint and isinstance(jaw_joint, pm.PyNode):
            j_parent = jaw_joint
        else:
            j_parent = False
        jnt = rigbits.addJnt(oTrans, noReplace=True, parent=j_parent)
        lowerJoints.append(jnt)
        pm.sets(defset, add=jnt)
    pm.progressWindow(e=True, endProgress=True)

    ##################
    # Controls
    ##################

    # Controls lists
    upControls = []
    upVec = []
    upNpo = []
    lowControls = []
    lowVec = []
    lowNpo = []
    # controls options
    axis_list = ["sx", "sy", "sz", "ro"]
    upCtlOptions = [["corner", "R", "square", 4, .05, axis_list],
                    ["upOuter", "R", "circle", 14, .03, []],
                    ["upInner", "R", "circle", 14, .03, []],
                    ["upper", "C", "square", 4, .05, axis_list],
                    ["upInner", "L", "circle", 14, .03, []],
                    ["upOuter", "L", "circle", 14, .03, []],
                    ["corner", "L", "square", 4, .05, axis_list]]

    lowCtlOptions = [["lowOuter", "R", "circle", 14, .03, []],
                     ["lowInner", "R", "circle", 14, .03, []],
                     ["lower", "C", "square", 4, .05, axis_list],
                     ["lowInner", "L", "circle", 14, .03, []],
                     ["lowOuter", "L", "circle", 14, .03, []]]

    params = ["tx", "ty", "tz", "rx", "ry", "rz"]

    # upper controls
    cvs = upCrv_ctl.getCVs(space="world")
    pm.progressWindow(title='Upper controls', progress=0, max=len(cvs))

    v0 = transform.getTransformFromPos(cvs[0])
    v1 = transform.getTransformFromPos(cvs[-1])
    distSize = vector.getDistance(v0, v1) * 3

    for i, cv in enumerate(cvs):
        pm.progressWindow(e=True,
                          step=1,
                          status='\nCreating control for%s' % cv)
        t = transform.getTransformFromPos(cv)

        # Get nearest joint for orientation of controls
        joints = upperJoints + lowerJoints
        nearest_joint = None
        nearest_distance = None
        for joint in joints:
            distance = vector.getDistance(
                transform.getTranslation(joint),
                cv
            )
            if nearest_distance is None or distance < nearest_distance:
                nearest_distance = distance
                nearest_joint = joint

        if nearest_joint:
            t = transform.setMatrixPosition(
                transform.getTransform(nearest_joint), cv
            )
            temp = primitive.addTransform(
                lips_root, setName("temp"), t
            )
            temp.rx.set(0)
            t = transform.getTransform(temp)
            pm.delete(temp)

        oName = upCtlOptions[i][0]
        oSide = upCtlOptions[i][1]
        o_icon = upCtlOptions[i][2]
        color = upCtlOptions[i][3]
        wd = upCtlOptions[i][4]
        oPar = upCtlOptions[i][5]
        npo = primitive.addTransform(lips_root,
                                     setName("%s_npo" % oName, oSide),
                                     t)
        upNpo.append(npo)
        ctl = icon.create(npo,
                          setName("%s_%s" % (oName, control_name), oSide),
                          t,
                          icon=o_icon,
                          w=wd * distSize,
                          d=wd * distSize,
                          ro=datatypes.Vector(1.57079633, 0, 0),
                          po=datatypes.Vector(0, 0, .07 * distSize),
                          color=color)

        upControls.append(ctl)
        name_split = control_name.split("_")
        if len(name_split) == 2 and name_split[-1] == "ghost":
            pass
        else:
            pm.sets(ctlSet, add=ctl)
        attribute.addAttribute(ctl, "isCtl", "bool", keyable=False)
        attribute.setKeyableAttributes(ctl, params + oPar)

        upv = primitive.addTransform(ctl, setName("%s_upv" % oName, oSide), t)
        upv.attr("tz").set(FRONT_OFFSET)
        upVec.append(upv)
        if oSide == "R":
            npo.attr("sx").set(-1)
    pm.progressWindow(e=True, endProgress=True)

    # lower controls
    cvs = lowCrv_ctl.getCVs(space="world")
    pm.progressWindow(title='Lower controls', progress=0, max=len(cvs))

    for i, cv in enumerate(cvs[1:-1]):
        pm.progressWindow(e=True,
                          step=1,
                          status='\nCreating control for%s' % cv)

        t = transform.getTransformFromPos(cv)

        # Get nearest joint for orientation of controls
        joints = upperJoints + lowerJoints
        nearest_joint = None
        nearest_distance = None
        for joint in joints:
            distance = vector.getDistance(
                transform.getTranslation(joint),
                cv
            )
            if nearest_distance is None or distance < nearest_distance:
                nearest_distance = distance
                nearest_joint = joint

        if nearest_joint:
            t = transform.setMatrixPosition(
                transform.getTransform(nearest_joint), cv
            )
            temp = primitive.addTransform(
                lips_root, setName("temp"), t
            )
            temp.rx.set(0)
            t = transform.getTransform(temp)
            pm.delete(temp)

        oName = lowCtlOptions[i][0]
        oSide = lowCtlOptions[i][1]
        o_icon = lowCtlOptions[i][2]
        color = lowCtlOptions[i][3]
        wd = lowCtlOptions[i][4]
        oPar = lowCtlOptions[i][5]
        npo = primitive.addTransform(lips_root,
                                     setName("%s_npo" % oName, oSide),
                                     t)
        lowNpo.append(npo)
        ctl = icon.create(npo,
                          setName("%s_%s" % (oName, control_name), oSide),
                          t,
                          icon=o_icon,
                          w=wd * distSize,
                          d=wd * distSize,
                          ro=datatypes.Vector(1.57079633, 0, 0),
                          po=datatypes.Vector(0, 0, .07 * distSize),
                          color=color)
        lowControls.append(ctl)
        name_split = control_name.split("_")
        if len(name_split) == 2 and control_name.split("_")[-1] == "ghost":
            pass
        else:
            pm.sets(ctlSet, add=ctl)
        attribute.addAttribute(ctl, "isCtl", "bool", keyable=False)
        attribute.setKeyableAttributes(ctl, params + oPar)

        upv = primitive.addTransform(ctl, setName("%s_upv" % oName, oSide), t)
        upv.attr("tz").set(FRONT_OFFSET)
        lowVec.append(upv)
        if oSide == "R":
            npo.attr("sx").set(-1)
    pm.progressWindow(e=True, endProgress=True)

    # reparentig controls
    pm.parent(upNpo[1], lowNpo[0], upControls[0])
    pm.parent(upNpo[2], upNpo[4], upControls[3])
    pm.parent(upNpo[-2], lowNpo[-1], upControls[-1])
    pm.parent(lowNpo[1], lowNpo[3], lowControls[2])

    # Connecting control crvs with controls
    applyop.gear_curvecns_op(upCrv_ctl, upControls)
    applyop.gear_curvecns_op(lowCrv_ctl,
                             [upControls[0]] + lowControls + [upControls[-1]])

    applyop.gear_curvecns_op(upCrv_upv, upVec)
    applyop.gear_curvecns_op(lowCrv_upv, [upVec[0]] + lowVec + [upVec[-1]])

    # adding wires
    pm.wire(upCrv, w=upCrv_ctl, dropoffDistance=[0, 1000])
    pm.wire(lowCrv, w=lowCrv_ctl, dropoffDistance=[0, 1000])
    pm.wire(upRope, w=upCrv_ctl, dropoffDistance=[0, 1000])
    pm.wire(lowRope, w=lowCrv_ctl, dropoffDistance=[0, 1000])

    pm.wire(upRope_upv, w=upCrv_upv, dropoffDistance=[0, 1000])
    pm.wire(lowRope_upv, w=lowCrv_upv, dropoffDistance=[0, 1000])

    # setting constrains
    # up
    cns_node = pm.parentConstraint(upControls[0],
                                   upControls[3],
                                   upControls[1].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(upControls[0].name() + "W0").set(.75)
    cns_node.attr(upControls[3].name() + "W1").set(.25)
    cns_node.interpType.set(0)  # noFlip

    cns_node = pm.parentConstraint(upControls[0],
                                   upControls[3],
                                   upControls[2].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(upControls[0].name() + "W0").set(.25)
    cns_node.attr(upControls[3].name() + "W1").set(.75)
    cns_node.interpType.set(0)  # noFlip

    cns_node = pm.parentConstraint(upControls[3],
                                   upControls[6],
                                   upControls[4].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(upControls[3].name() + "W0").set(.75)
    cns_node.attr(upControls[6].name() + "W1").set(.25)
    cns_node.interpType.set(0)  # noFlip

    cns_node = pm.parentConstraint(upControls[3],
                                   upControls[6],
                                   upControls[5].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(upControls[3].name() + "W0").set(.25)
    cns_node.attr(upControls[6].name() + "W1").set(.75)
    cns_node.interpType.set(0)  # noFlip

    # low
    cns_node = pm.parentConstraint(upControls[0],
                                   lowControls[2],
                                   lowControls[0].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(upControls[0].name() + "W0").set(.75)
    cns_node.attr(lowControls[2].name() + "W1").set(.25)
    cns_node.interpType.set(0)  # noFlip

    cns_node = pm.parentConstraint(upControls[0],
                                   lowControls[2],
                                   lowControls[1].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(upControls[0].name() + "W0").set(.25)
    cns_node.attr(lowControls[2].name() + "W1").set(.75)
    cns_node.interpType.set(0)  # noFlip

    cns_node = pm.parentConstraint(lowControls[2],
                                   upControls[6],
                                   lowControls[3].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(lowControls[2].name() + "W0").set(.75)
    cns_node.attr(upControls[6].name() + "W1").set(.25)
    cns_node.interpType.set(0)  # noFlip

    cns_node = pm.parentConstraint(lowControls[2],
                                   upControls[6],
                                   lowControls[4].getParent(),
                                   mo=True,
                                   skipRotate=["x", "y", "z"])
    cns_node.attr(lowControls[2].name() + "W0").set(.25)
    cns_node.attr(upControls[6].name() + "W1").set(.75)
    cns_node.interpType.set(0)  # noFlip

    ###########################################
    # Connecting rig
    ###########################################
    if parent_node:
        try:
            if isinstance(parent_node, string_types):
                parent_node = pm.PyNode(parent_node)
            parent_node.addChild(lips_root)
        except pm.MayaNodeError:
            pm.displayWarning("The Lips rig can not be parent to: %s. Maybe "
                              "this object doesn't exist." % parent_node)
    if head_joint and jaw_joint:
        try:
            if isinstance(head_joint, string_types):
                head_joint = pm.PyNode(head_joint)
        except pm.MayaNodeError:
            pm.displayWarning("Head Joint or Upper Lip Joint %s. Can not be "
                              "fount in the scene" % head_joint)
            return
        try:
            if isinstance(jaw_joint, string_types):
                jaw_joint = pm.PyNode(jaw_joint)
        except pm.MayaNodeError:
            pm.displayWarning("Jaw Joint or Lower Lip Joint %s. Can not be "
                              "fount in the scene" % jaw_joint)
            return

        ref_ctls = [head_joint, jaw_joint]

        if upper_lip_ctl and lower_lip_ctl:
            try:
                if isinstance(upper_lip_ctl, string_types):
                    upper_lip_ctl = pm.PyNode(upper_lip_ctl)
            except pm.MayaNodeError:
                pm.displayWarning("Upper Lip Ctl %s. Can not be "
                                  "fount in the scene" % upper_lip_ctl)
                return
            try:
                if isinstance(lower_lip_ctl, string_types):
                    lower_lip_ctl = pm.PyNode(lower_lip_ctl)
            except pm.MayaNodeError:
                pm.displayWarning("Lower Lip Ctl %s. Can not be "
                                  "fount in the scene" % lower_lip_ctl)
                return
            ref_ctls = [upper_lip_ctl, lower_lip_ctl]

        # in order to avoid flips lets create a reference transform
        # also to avoid flips, set any multi target parentConstraint to noFlip
        ref_cns_list = []
        print (ref_ctls)
        for cns_ref in ref_ctls:

            t = transform.getTransformFromPos(
                cns_ref.getTranslation(space='world'))
            ref = pm.createNode("transform",
                                n=cns_ref.name() + "_cns",
                                p=cns_ref,
                                ss=True)
            ref.setMatrix(t, worldSpace=True)
            ref_cns_list.append(ref)
        # right corner connection
        cns_node = pm.parentConstraint(ref_cns_list[0],
                                       ref_cns_list[1],
                                       upControls[0].getParent(),
                                       mo=True)
        cns_node.interpType.set(0)  # noFlip
        # left corner connection
        cns_node = pm.parentConstraint(ref_cns_list[0],
                                       ref_cns_list[1],
                                       upControls[-1].getParent(),
                                       mo=True)
        cns_node.interpType.set(0)  # noFlip
        # up control connection
        cns_node = pm.parentConstraint(ref_cns_list[0],
                                       upControls[3].getParent(),
                                       mo=True)
        # low control connection
        cns_node = pm.parentConstraint(ref_cns_list[1],
                                       lowControls[2].getParent(),
                                       mo=True)

    ###########################################
    # Auto Skinning
    ###########################################
    if do_skin:
        # eyelid vertex rows
        totalLoops = rigid_loops + falloff_loops
        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(rigid_loops):
            for rr in range(2):
                skinPercList.append(1.0)
        increment = 1.0 / float(falloff_loops)
        # we invert to smooth out from 100 to 0
        inv = 1.0 - increment
        for r in range(falloff_loops):
            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
        if head_joint:
            try:
                head_joint = pm.PyNode(head_joint)
            except pm.MayaNodeError:
                pm.displayWarning(
                    "Auto skin aborted can not find %s " % head_joint)
                return

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

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

        lipsJoints = upperJoints + lowerJoints
        closestVtxList = upLip_closestVtxList + lowLip_closestVtxList
        pm.progressWindow(title='Auto skinning process',
                          progress=0,
                          max=len(lipsJoints))

        for i, jnt in enumerate(lipsJoints):
            pm.progressWindow(e=True, step=1, status='\nSkinning %s' % jnt)
            skinCluster.addInfluence(jnt, weight=0)
            v = closestVtxList[i]
            for row in vertexRowList:
                if v in row:
                    for i, rv in enumerate(row):
                        # find the deformer with max value for each vertex
                        w = pm.skinPercent(skinCluster,
                                           rv,
                                           query=True,
                                           value=True)
                        transJoint = pm.skinPercent(skinCluster,
                                                    rv,
                                                    query=True,
                                                    t=None)
                        max_value = max(w)
                        max_index = w.index(max_value)

                        perc = skinPercList[i]
                        t_value = [(jnt, perc),
                                   (transJoint[max_index], 1.0 - perc)]
                        pm.skinPercent(skinCluster,
                                       rv,
                                       transformValue=t_value)
        pm.progressWindow(e=True, endProgress=True)
Example #25
0
def postSpring(dist=5, hostUI=False, hostUI2=False, invertX=False):
    """Create the dynamic spring rig.

    This spring system use the mgear_spring node
    And transfer the position spring
    to rotation spring using an aim constraint.

    Note:
        The selected chain of object should be align with the X axis.

    Args:
        dist (float): The distance of the position spring.
        hostUI (dagNode): The spring active and intensity channel host.
        hostUI2 (dagNode): The daping and stiffness channel host for each
            object in the chain.
        invertX (bool): reverse the direction of the x axis.

    """
    oSel = pm.selected()

    if not hostUI2:
        hostUI2 = oSel[0]

    aSpring_active = attribute.addAttribute(
        hostUI2, "spring_active_%s" % oSel[0].name(), "double", 1.0,
        "___spring_active_______%s" % oSel[0].name(),
        "spring_active_%s" % oSel[0].name(), 0, 1)

    aSpring_intensity = attribute.addAttribute(
        hostUI2, "spring_intensity_%s" % oSel[0].name(), "double", 1.0,
        "___spring_intensity_______%s" % oSel[0].name(),
        "spring_intensity_%s" % oSel[0].name(), 0, 1)

    if invertX:
        dist = dist * -1
        # aim constraint
        aimAxis = "-xy"
    else:
        # aim constraint
        aimAxis = "xy"

    for obj in oSel:

        oParent = obj.getParent()

        oNpo = pm.PyNode(
            pm.createNode("transform",
                          n=obj.name() + "_npo",
                          p=oParent,
                          ss=True))
        oNpo.setTransformation(obj.getMatrix())
        pm.parent(obj, oNpo)

        oSpring_cns = pm.PyNode(
            pm.createNode("transform",
                          n=obj.name() + "_spr_cns",
                          p=oNpo,
                          ss=True))
        oSpring_cns.setTransformation(obj.getMatrix())
        pm.parent(obj, oSpring_cns)

        oSpringLvl = pm.PyNode(
            pm.createNode("transform",
                          n=obj.name() + "_spr_lvl",
                          p=oNpo,
                          ss=True))
        oM = obj.getTransformation()
        oM.addTranslation([dist, 0, 0], "object")
        oSpringLvl.setTransformation(oM.asMatrix())

        oSpringDriver = pm.PyNode(
            pm.createNode("transform",
                          n=obj.name() + "_spr",
                          p=oSpringLvl,
                          ss=True))

        try:
            defSet = pm.PyNode("rig_PLOT_grp")
            pm.sets(defSet, add=oSpring_cns)
        except TypeError:
            defSet = pm.sets(name="rig_PLOT_grp")
            pm.sets(defSet, remove=obj)
            pm.sets(defSet, add=oSpring_cns)

        # adding attributes:
        if not hostUI:
            hostUI = obj

        aSpring_damping = attribute.addAttribute(
            hostUI, "spring_damping_%s" % obj.name(), "double", .5,
            "damping_%s" % obj.name(), "damping_%s" % obj.name(), 0, 1)

        aSpring_stiffness_ = attribute.addAttribute(
            hostUI, "spring_stiffness_%s" % obj.name(), "double", .5,
            "stiffness_%s" % obj.name(), "stiffness_%s" % obj.name(), 0, 1)

        cns = applyop.aimCns(oSpring_cns, oSpringDriver, aimAxis, 2, [0, 1, 0],
                             oNpo, False)

        # change from fcurves to spring
        pb_node = pm.createNode("pairBlend")

        pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
        pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
        pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
        pm.setAttr(pb_node + ".translateXMode", 2)
        pm.setAttr(pb_node + ".translateYMode", 2)
        pm.setAttr(pb_node + ".translateZMode", 2)

        pm.connectAttr(pb_node + ".outRotateX",
                       oSpring_cns + ".rotateX",
                       f=True)
        pm.connectAttr(pb_node + ".outRotateY",
                       oSpring_cns + ".rotateY",
                       f=True)
        pm.connectAttr(pb_node + ".outRotateZ",
                       oSpring_cns + ".rotateZ",
                       f=True)

        pm.setKeyframe(oSpring_cns, at="rotateX")
        pm.setKeyframe(oSpring_cns, at="rotateY")
        pm.setKeyframe(oSpring_cns, at="rotateZ")

        # add sprint op
        springOP = applyop.gear_spring_op(oSpringDriver)

        # connecting attributes
        pm.connectAttr(aSpring_active, pb_node + ".weight")
        pm.connectAttr(aSpring_intensity, springOP + ".intensity")
        pm.connectAttr(aSpring_damping, springOP + ".damping")
        pm.connectAttr(aSpring_stiffness_, springOP + ".stiffness")
Example #26
0
def rig(
    eyeMesh=None,
    edgeLoop="",
    blinkH=20,
    namePrefix="eye",
    offset=0.05,
    rigidLoops=2,
    falloffLoops=4,
    headJnt=None,
    doSkin=True,
    parent_node=None,
    ctlName="ctl",
    sideRange=False,
    customCorner=False,
    intCorner=None,
    extCorner=None,
    ctlSet=None,
    defSet=None,
    upperVTrack=0.02,
    upperHTrack=0.01,
    lowerVTrack=0.02,
    lowerHTrack=0.01,
    aim_controller="",
    deformers_group="",
    everyNVertex=1,
):
    """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_node (None, optional): Description
        ctlName (str, optional): Description
        sideRange (bool, optional): Description
        customCorner (bool, optional): Description
        intCorner (None, optional): Description
        extCorner (None, optional): Description
        ctlSet (None, optional): Description
        defSet (None, optional): Description
        upperVTrack (None, optional): Description
        upperHTrack (None, optional): Description
        lowerVTrack (None, optional): Description
        lowerHTrack (None, optional): Description
        aim_controller (None, optional): Description
        deformers_group (None, optional): Description
        everyNVertex (int, optional): Will create a joint every N vertex

    No Longer Returned:
        TYPE: Description
    """

    ##########################################
    # INITIAL SETUP
    ##########################################
    up_axis = pm.upAxis(q=True, axis=True)
    if up_axis == "z":
        z_up = True
    else:
        z_up = False

    # getters
    edgeLoopList = get_edge_loop(edgeLoop)
    eyeMesh = get_eye_mesh(eyeMesh)

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

    # Convert data
    blinkH = blinkH / 100.0

    # Initial Data
    bboxCenter = meshNavigation.bboxCenter(eyeMesh)

    extr_v = meshNavigation.getExtremeVertexFromLoop(edgeLoopList, sideRange,
                                                     z_up)
    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

    ##########################################
    # CREATE OBJECTS
    ##########################################

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

    # Eyelid Main crvs
    try:
        upEyelid_edge = meshNavigation.edgeRangeInLoopFromMid(
            edgeList, upPos, inPos, outPos)
        up_crv = curve.createCurveFromOrderedEdges(upEyelid_edge,
                                                   inPos,
                                                   setName("upperEyelid"),
                                                   parent=eyeCrv_root)
        upCtl_crv = curve.createCurveFromOrderedEdges(upEyelid_edge,
                                                      inPos,
                                                      setName("upCtl_crv"),
                                                      parent=eyeCrv_root)
        pm.rebuildCurve(upCtl_crv, s=2, rt=0, rpo=True, ch=False)

        lowEyelid_edge = meshNavigation.edgeRangeInLoopFromMid(
            edgeList, lowPos, inPos, outPos)
        low_crv = curve.createCurveFromOrderedEdges(lowEyelid_edge,
                                                    inPos,
                                                    setName("lowerEyelid"),
                                                    parent=eyeCrv_root)
        lowCtl_crv = curve.createCurveFromOrderedEdges(lowEyelid_edge,
                                                       inPos,
                                                       setName("lowCtl_crv"),
                                                       parent=eyeCrv_root)

        pm.rebuildCurve(lowCtl_crv, 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

    # blendshape  curves. All crv have 30 point to allow blendshape connect
    upDriver_crv = curve.createCurveFromCurve(up_crv,
                                              setName("upDriver_crv"),
                                              nbPoints=30,
                                              parent=eyeCrv_root)
    upDriver_crv.attr("lineWidth").set(5)
    lowDriver_crv = curve.createCurveFromCurve(low_crv,
                                               setName("lowDriver_crv"),
                                               nbPoints=30,
                                               parent=eyeCrv_root)
    lowDriver_crv.attr("lineWidth").set(5)

    upRest_target_crv = curve.createCurveFromCurve(
        up_crv, setName("upRest_target_crv"), nbPoints=30, parent=eyeCrv_root)
    lowRest_target_crv = curve.createCurveFromCurve(
        low_crv,
        setName("lowRest_target_crv"),
        nbPoints=30,
        parent=eyeCrv_root)
    upProfile_target_crv = curve.createCurveFromCurve(
        up_crv,
        setName("upProfile_target_crv"),
        nbPoints=30,
        parent=eyeCrv_root,
    )
    lowProfile_target_crv = curve.createCurveFromCurve(
        low_crv,
        setName("lowProfile_target_crv"),
        nbPoints=30,
        parent=eyeCrv_root,
    )

    # mid driver
    midUpDriver_crv = curve.createCurveFromCurve(up_crv,
                                                 setName("midUpDriver_crv"),
                                                 nbPoints=30,
                                                 parent=eyeCrv_root)
    midLowDriver_crv = curve.createCurveFromCurve(low_crv,
                                                  setName("midLowDriver_crv"),
                                                  nbPoints=30,
                                                  parent=eyeCrv_root)

    # curve that define the close point of the eyelid
    closeTarget_crv = curve.createCurveFromCurve(up_crv,
                                                 setName("closeTarget_crv"),
                                                 nbPoints=30,
                                                 parent=eyeCrv_root)

    eyeCrv_root.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 ctlSet:
        ctlSet = "rig_controllers_grp"
    try:
        ctlSet = pm.PyNode(ctlSet)
    except pm.MayaNodeError:
        pm.sets(n=ctlSet, em=True)
        ctlSet = pm.PyNode(ctlSet)
    if not defSet:
        defSet = "rig_deformers_grp"
    try:
        defset = pm.PyNode(defSet)
    except pm.MayaNodeError:
        pm.sets(n=defSet, em=True)
        defset = pm.PyNode(defSet)

    # Calculate center looking at
    averagePosition = (upPos.getPosition(space="world") + lowPos.getPosition(
        space="world") + inPos.getPosition(space="world") +
                       outPos.getPosition(space="world")) / 4

    if z_up:
        axis = "zx"
    else:
        axis = "z-x"
    t = transform.getTransformLookingAt(bboxCenter,
                                        averagePosition,
                                        normalVec,
                                        axis=axis,
                                        negate=False)

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

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

    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)
    t = transform.getTransform(over_npo)

    # 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_ctl = None
    arrow_npo = None
    if aim_controller:
        arrow_ctl = pm.PyNode(aim_controller)
    else:
        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"])
    attribute.addAttribute(arrow_ctl, "isCtl", "bool", keyable=False)

    # tracking custom trigger
    if side == "R":
        tt = t_arrow
    else:
        tt = t
    aimTrigger_root = primitive.addTransform(center_lookat,
                                             setName("aimTrigger_root"), tt)
    # For some unknown reason the right side gets scewed rotation values
    mgear.core.transform.resetTransform(aimTrigger_root)
    aimTrigger_lvl = primitive.addTransform(aimTrigger_root,
                                            setName("aimTrigger_lvl"), tt)
    # For some unknown reason the right side gets scewed rotation values
    mgear.core.transform.resetTransform(aimTrigger_lvl)
    aimTrigger_lvl.attr("tz").set(1.0)
    aimTrigger_ref = primitive.addTransform(aimTrigger_lvl,
                                            setName("aimTrigger_ref"), tt)
    # For some unknown reason the right side gets scewed rotation values
    mgear.core.transform.resetTransform(aimTrigger_ref)
    aimTrigger_ref.attr("tz").set(0.0)
    # connect  trigger with arrow_ctl
    pm.parentConstraint(arrow_ctl, aimTrigger_ref, mo=True)

    # Blink driver controls
    if z_up:
        trigger_axis = "tz"
        ro_up = [0, 1.57079633 * 2, 1.57079633]
        ro_low = [0, 0, 1.57079633]
        po = [0, offset * -1, 0]
        low_pos = 2  # Z
    else:
        trigger_axis = "ty"
        ro_up = (1.57079633, 1.57079633, 0)
        ro_low = [1.57079633, 1.57079633, 1.57079633 * 2]
        po = [0, 0, offset]
        low_pos = 1  # Y

    # upper ctl
    p = upRest_target_crv.getCVs(space="world")[15]
    ut = transform.setMatrixPosition(datatypes.Matrix(), p)
    npo = primitive.addTransform(over_npo, setName("upBlink_npo"), ut)

    up_ctl = icon.create(
        npo,
        setName("upBlink_ctl"),
        ut,
        icon="arrow",
        w=2.5,
        d=2.5,
        ro=datatypes.Vector(ro_up[0], ro_up[1], ro_up[2]),
        po=datatypes.Vector(po[0], po[1], po[2]),
        color=4,
    )
    attribute.setKeyableAttributes(up_ctl, [trigger_axis])
    pm.sets(ctlSet, add=up_ctl)

    # use translation of the object to drive the blink
    blink_driver = primitive.addTransform(up_ctl, setName("blink_drv"), ut)

    # lowe ctl
    p_low = lowRest_target_crv.getCVs(space="world")[15]
    p[low_pos] = p_low[low_pos]
    lt = transform.setMatrixPosition(ut, p)
    npo = primitive.addTransform(over_npo, setName("lowBlink_npo"), lt)

    low_ctl = icon.create(
        npo,
        setName("lowBlink_ctl"),
        lt,
        icon="arrow",
        w=1.5,
        d=1.5,
        ro=datatypes.Vector(ro_low[0], ro_low[1], ro_low[2]),
        po=datatypes.Vector(po[0], po[1], po[2]),
        color=4,
    )
    attribute.setKeyableAttributes(low_ctl, [trigger_axis])
    pm.sets(ctlSet, add=low_ctl)

    # Controls lists
    upControls = []
    trackLvl = []
    track_corner_lvl = []
    corner_ctl = []
    ghost_ctl = []

    # upper eyelid controls
    upperCtlNames = ["inCorner", "upInMid", "upMid", "upOutMid", "outCorner"]
    cvs = upCtl_crv.getCVs(space="world")
    if side == "R" and not sideRange:
        # if side == "R":
        cvs = [cv for cv in reversed(cvs)]
        # offset = offset * -1
    for i, cv in enumerate(cvs):
        if utils.is_odd(i):
            color = 14
            wd = 0.3
            icon_shape = "circle"
            params = ["tx", "ty", "tz"]
        else:
            color = 4
            wd = 0.6
            icon_shape = "circle"
            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
        # track for corners and mid point level
        if i in [0, 2, 4]:
            # we add an extra level to input the tracking ofset values
            npo = primitive.addTransform(npo,
                                         setName("%s_trk" % upperCtlNames[i]),
                                         t)
            if i == 2:
                trackLvl.append(npo)
            else:
                track_corner_lvl.append(npo)

        if i in [1, 2, 3]:
            ctl = primitive.addTransform(npo,
                                         setName("%s_loc" % upperCtlNames[i]),
                                         t)
            # ghost controls
            if i == 2:
                gt = transform.setMatrixPosition(
                    t, transform.getPositionFromMatrix(ut))
            else:
                gt = t
            npo_g = primitive.addTransform(
                up_ctl, setName("%sCtl_npo" % upperCtlNames[i]), gt)
            ctl_g = icon.create(
                npo_g,
                setName("%s_%s" % (upperCtlNames[i], ctlName)),
                gt,
                icon=icon_shape,
                w=wd,
                d=wd,
                ro=datatypes.Vector(1.57079633, 0, 0),
                po=datatypes.Vector(0, 0, offset),
                color=color,
            )
            # define the ctl_param to recive the ctl configuration
            ctl_param = ctl_g
            ghost_ctl.append(ctl_g)
            # connect local SRT
            rigbits.connectLocalTransform([ctl_g, ctl])
        else:
            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,
            )
            # define the ctl_param to recive the ctl configuration
            ctl_param = ctl
        attribute.addAttribute(ctl_param, "isCtl", "bool", keyable=False)
        attribute.add_mirror_config_channels(ctl_param)
        node.add_controller_tag(ctl_param, over_npo)
        if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost":
            pass
        else:
            pm.sets(ctlSet, add=ctl_param)
        attribute.setKeyableAttributes(ctl_param, params)
        upControls.append(ctl)
        # add corner ctls to corner ctl list for tracking
        if i in [0, 4]:
            corner_ctl.append(ctl)
        # if side == "R":
        #     npoBase.attr("ry").set(180)
        #     npoBase.attr("sz").set(-1)
    # adding parent constraints to odd controls
    for i, ctl in enumerate(upControls):
        if utils.is_odd(i):
            cns_node = pm.parentConstraint(upControls[i - 1],
                                           upControls[i + 1],
                                           ctl.getParent(),
                                           mo=True)
            # Make the constraint "noFlip"
            cns_node.interpType.set(0)

    # adding parent constraint ghost controls
    cns_node = pm.parentConstraint(ghost_ctl[1],
                                   upControls[0],
                                   ghost_ctl[0].getParent(),
                                   mo=True)
    cns_node.interpType.set(0)
    cns_node = pm.parentConstraint(ghost_ctl[1],
                                   upControls[-1],
                                   ghost_ctl[2].getParent(),
                                   mo=True)
    cns_node.interpType.set(0)
    # lower eyelid controls
    lowControls = [upControls[0]]
    lowerCtlNames = [
        "inCorner",
        "lowInMid",
        "lowMid",
        "lowOutMid",
        "outCorner",
    ]

    cvs = lowCtl_crv.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 = 0.3
            icon_shape = "circle"
            params = ["tx", "ty", "tz"]
        else:
            color = 4
            wd = 0.6
            icon_shape = "circle"
            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 in [1, 2, 3]:
            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 = primitive.addTransform(npo,
                                         setName("%s_loc" % lowerCtlNames[i]),
                                         t)
            # ghost controls
            if i == 2:
                gt = transform.setMatrixPosition(
                    t, transform.getPositionFromMatrix(lt))
            else:
                gt = t
            # ghost controls
            npo_g = primitive.addTransform(
                low_ctl, setName("%sCtl_npo" % lowerCtlNames[i]), gt)
            ctl_g = icon.create(
                npo_g,
                setName("%s_%s" % (lowerCtlNames[i], ctlName)),
                gt,
                icon=icon_shape,
                w=wd,
                d=wd,
                ro=datatypes.Vector(1.57079633, 0, 0),
                po=datatypes.Vector(0, 0, offset),
                color=color,
            )
            # define the ctl_param to recive the ctl configuration
            ctl_param = ctl_g
            ghost_ctl.append(ctl_g)
            # connect local SRT
            rigbits.connectLocalTransform([ctl_g, ctl])
        else:
            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,
            )
            # define the ctl_param to recive the ctl configuration
            ctl_param = ctl
        attribute.addAttribute(ctl_param, "isCtl", "bool", keyable=False)
        attribute.add_mirror_config_channels(ctl_param)

        lowControls.append(ctl)
        if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost":
            pass
        else:
            pm.sets(ctlSet, add=ctl_param)
        attribute.setKeyableAttributes(ctl_param, 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_npo)
    lowControls.append(upControls[-1])

    # adding parent constraints to odd controls
    for i, ctl in enumerate(lowControls):
        if utils.is_odd(i):
            cns_node = pm.parentConstraint(
                lowControls[i - 1],
                lowControls[i + 1],
                ctl.getParent(),
                mo=True,
            )
            # Make the constraint "noFlip"
            cns_node.interpType.set(0)

    # adding parent constraint ghost controls
    cns_node = pm.parentConstraint(ghost_ctl[4],
                                   upControls[0],
                                   ghost_ctl[3].getParent(),
                                   mo=True)
    cns_node.interpType.set(0)
    cns_node = pm.parentConstraint(ghost_ctl[4],
                                   upControls[-1],
                                   ghost_ctl[5].getParent(),
                                   mo=True)
    cns_node.interpType.set(0)
    ##########################################
    # OPERATORS
    ##########################################
    # Connecting control crvs with controls
    applyop.gear_curvecns_op(upCtl_crv, upControls)
    applyop.gear_curvecns_op(lowCtl_crv, lowControls)

    # adding wires
    w1 = pm.wire(up_crv, w=upDriver_crv)[0]
    w2 = pm.wire(low_crv, w=lowDriver_crv)[0]

    w3 = pm.wire(upProfile_target_crv, w=upCtl_crv)[0]
    w4 = pm.wire(lowProfile_target_crv, w=lowCtl_crv)[0]

    if z_up:
        trigger_axis = "tz"
    else:
        trigger_axis = "ty"

    # connect blink driver
    pm.pointConstraint(low_ctl, blink_driver, mo=False)
    rest_val = blink_driver.attr(trigger_axis).get()

    up_div_node = node.createDivNode(up_ctl.attr(trigger_axis), rest_val)
    low_div_node = node.createDivNode(low_ctl.attr(trigger_axis),
                                      rest_val * -1)

    # contact driver
    minus_node = node.createPlusMinusAverage1D(
        [rest_val, blink_driver.attr(trigger_axis)], operation=2)
    contact_div_node = node.createDivNode(minus_node.output1D, rest_val)

    # wire tension
    for w in [w1, w2, w3, w4]:
        w.dropoffDistance[0].set(100)

    # TODO: what is the best solution?
    # trigger using proximity
    # remap_node = pm.createNode("remapValue")
    # contact_div_node.outputX >> remap_node.inputValue
    # remap_node.value[0].value_Interp.set(2)
    # remap_node.inputMin.set(0.995)
    # reverse_node = node.createReverseNode(remap_node.outColorR)
    # for w in [w1, w2]:
    #     reverse_node.outputX >> w.scale[0]

    # trigger at starting movement for up and low
    # up
    remap_node = pm.createNode("remapValue")
    up_ctl.attr(trigger_axis) >> remap_node.inputValue
    remap_node.value[0].value_Interp.set(2)
    remap_node.inputMax.set(rest_val / 8)
    reverse_node = node.createReverseNode(remap_node.outColorR)
    reverse_node.outputX >> w1.scale[0]
    # low
    remap_node = pm.createNode("remapValue")
    low_ctl.attr(trigger_axis) >> remap_node.inputValue
    remap_node.value[0].value_Interp.set(2)
    remap_node.inputMin.set((rest_val / 8) * -1)
    remap_node.outColorR >> w2.scale[0]

    # mid position drivers blendshapes
    bs_midUpDrive = pm.blendShape(
        lowRest_target_crv,
        upProfile_target_crv,
        midUpDriver_crv,
        n="midUpDriver_blendShape",
    )

    bs_midLowDrive = pm.blendShape(
        upRest_target_crv,
        lowProfile_target_crv,
        midLowDriver_crv,
        n="midlowDriver_blendShape",
    )

    bs_closeTarget = pm.blendShape(
        midUpDriver_crv,
        midLowDriver_crv,
        closeTarget_crv,
        n="closeTarget_blendShape",
    )

    pm.connectAttr(
        up_div_node.outputX,
        bs_midUpDrive[0].attr(lowRest_target_crv.name()),
    )

    pm.connectAttr(
        low_div_node.outputX,
        bs_midLowDrive[0].attr(upRest_target_crv.name()),
    )

    pm.setAttr(bs_closeTarget[0].attr(midUpDriver_crv.name()), 0.5)
    pm.setAttr(bs_closeTarget[0].attr(midLowDriver_crv.name()), 0.5)

    # Main crv drivers
    bs_upBlink = pm.blendShape(
        lowRest_target_crv,
        closeTarget_crv,
        upProfile_target_crv,
        upDriver_crv,
        n="upBlink_blendShape",
    )
    bs_lowBlink = pm.blendShape(
        upRest_target_crv,
        closeTarget_crv,
        lowProfile_target_crv,
        lowDriver_crv,
        n="lowBlink_blendShape",
    )

    # blink contact connections
    cond_node_up = node.createConditionNode(contact_div_node.outputX, 1, 3, 0,
                                            up_div_node.outputX)
    pm.connectAttr(
        cond_node_up.outColorR,
        bs_upBlink[0].attr(lowRest_target_crv.name()),
    )

    cond_node_low = node.createConditionNode(contact_div_node.outputX, 1, 3, 0,
                                             low_div_node.outputX)
    pm.connectAttr(
        cond_node_low.outColorR,
        bs_lowBlink[0].attr(upRest_target_crv.name()),
    )

    cond_node_close = node.createConditionNode(contact_div_node.outputX, 1, 2,
                                               1, 0)
    cond_node_close.colorIfFalseR.set(0)
    pm.connectAttr(
        cond_node_close.outColorR,
        bs_upBlink[0].attr(closeTarget_crv.name()),
    )

    pm.connectAttr(
        cond_node_close.outColorR,
        bs_lowBlink[0].attr(closeTarget_crv.name()),
    )

    pm.setAttr(bs_upBlink[0].attr(upProfile_target_crv.name()), 1)
    pm.setAttr(bs_lowBlink[0].attr(lowProfile_target_crv.name()), 1)

    # joints root
    jnt_root = primitive.addTransformFromPos(eye_root,
                                             setName("joints"),
                                             pos=bboxCenter)
    if deformers_group:
        deformers_group = pm.PyNode(deformers_group)
        pm.parentConstraint(eye_root, jnt_root, mo=True)
        pm.scaleConstraint(eye_root, jnt_root, mo=True)
        deformers_group.addChild(jnt_root)

    # 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 = up_crv.getCVs(space="world")
    upCrv_info = node.createCurveInfoNode(up_crv)

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

    if z_up:
        axis = "zy"
        wupVector = [0, 0, 1]
    else:
        axis = "-yz"
        wupVector = [0, 1, 0]

    for i, cv in enumerate(cvs):
        if i % everyNVertex:
            continue

        # 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(0.08)
        jntRoot.attr("visibility").set(False)
        upperEyelid_jntRoot.append(jntRoot)
        applyop.aimCns(jntRoot,
                       trn,
                       axis=axis,
                       wupObject=jnt_root,
                       wupVector=wupVector)

        jnt_ref = primitive.addJointFromPos(jntRoot,
                                            setName("upEyelid_jnt_ref", i),
                                            pos=cv)
        jnt_ref.attr("radius").set(0.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 = low_crv.getCVs(space="world")
    lowCrv_info = node.createCurveInfoNode(low_crv)

    # 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

        if i % everyNVertex:
            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(0.08)
        jntRoot.attr("visibility").set(False)
        lowerEyelid_jntRoot.append(jntRoot)
        applyop.aimCns(jntRoot,
                       trn,
                       axis=axis,
                       wupObject=jnt_root,
                       wupVector=wupVector)

        jnt_ref = primitive.addJointFromPos(jntRoot,
                                            setName("lowEyelid_jnt_ref", i),
                                            pos=cv)
        jnt_ref.attr("radius").set(0.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)

    # Adding channels for eye tracking
    upVTracking_att = attribute.addAttribute(up_ctl,
                                             "vTracking",
                                             "float",
                                             upperVTrack,
                                             minValue=0)
    upHTracking_att = attribute.addAttribute(up_ctl,
                                             "hTracking",
                                             "float",
                                             upperHTrack,
                                             minValue=0)

    lowVTracking_att = attribute.addAttribute(low_ctl,
                                              "vTracking",
                                              "float",
                                              lowerVTrack,
                                              minValue=0)
    lowHTracking_att = attribute.addAttribute(low_ctl,
                                              "hTracking",
                                              "float",
                                              lowerHTrack,
                                              minValue=0)

    # vertical tracking connect
    up_mult_node = node.createMulNode(upVTracking_att,
                                      aimTrigger_ref.attr("ty"))
    low_mult_node = node.createMulNode(lowVTracking_att,
                                       aimTrigger_ref.attr("ty"))
    # remap to use the low or the up eyelid as driver contact base on
    # the eyetrack trigger direction
    uT_remap_node = pm.createNode("remapValue")
    aimTrigger_ref.attr("ty") >> uT_remap_node.inputValue
    uT_remap_node.inputMax.set(0.1)
    uT_remap_node.inputMin.set(-0.1)
    up_mult_node.outputX >> uT_remap_node.outputMax
    low_mult_node.outputX >> uT_remap_node.outputMin
    # up
    u_remap_node = pm.createNode("remapValue")
    contact_div_node.outputX >> u_remap_node.inputValue
    u_remap_node.value[0].value_Interp.set(2)
    u_remap_node.inputMin.set(0.9)
    up_mult_node.outputX >> u_remap_node.outputMin
    uT_remap_node.outColorR >> u_remap_node.outputMax

    # low
    l_remap_node = pm.createNode("remapValue")
    contact_div_node.outputX >> l_remap_node.inputValue
    l_remap_node.value[0].value_Interp.set(2)
    l_remap_node.inputMin.set(0.9)
    low_mult_node.outputX >> l_remap_node.outputMin
    uT_remap_node.outColorR >> l_remap_node.outputMax

    # up connect and turn down to low when contact
    pm.connectAttr(u_remap_node.outColorR, trackLvl[0].attr("ty"))

    pm.connectAttr(l_remap_node.outColorR, trackLvl[1].attr("ty"))

    # horizontal tracking connect
    mult_node = node.createMulNode(upHTracking_att, aimTrigger_ref.attr("tx"))
    # Correct right side horizontal tracking
    # if side == "R":
    #     mult_node = node.createMulNode(mult_node.attr("outputX"), -1)
    pm.connectAttr(mult_node + ".outputX", trackLvl[0].attr("tx"))

    mult_node = node.createMulNode(lowHTracking_att, aimTrigger_ref.attr("tx"))
    # Correct right side horizontal tracking
    # if side == "R":
    #     mult_node = node.createMulNode(mult_node.attr("outputX"), -1)
    pm.connectAttr(mult_node + ".outputX", trackLvl[1].attr("tx"))

    # adding channels for corner tracking
    # track_corner_lvl
    for i, ctl in enumerate(corner_ctl):
        VTracking_att = attribute.addAttribute(ctl,
                                               "vTracking",
                                               "float",
                                               0.1,
                                               minValue=0)
        if z_up:
            mult_node = node.createMulNode(VTracking_att, up_ctl.tz)
            mult_node2 = node.createMulNode(VTracking_att, low_ctl.tz)
            plus_node = node.createPlusMinusAverage1D(
                [mult_node.outputX, mult_node2.outputX])

            mult_node3 = node.createMulNode(plus_node.output1D, -1)
            pm.connectAttr(mult_node3.outputX, track_corner_lvl[i].attr("ty"))
        else:
            mult_node = node.createMulNode(VTracking_att, up_ctl.ty)
            mult_node2 = node.createMulNode(VTracking_att, low_ctl.ty)
            plus_node = node.createPlusMinusAverage1D(
                [mult_node.outputX, mult_node2.outputX])

            pm.connectAttr(plus_node.output1D, track_corner_lvl[i].attr("ty"))

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

    ###########################################
    # 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 #27
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("upCtl_crv"),
                                                      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("lowCtl_crv"),
                                                       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):
            cns_node = pm.parentConstraint(upControls[i - 1],
                                           upControls[i + 1],
                                           ctl.getParent(),
                                           mo=True)
            # Make the constraint "noFlip"
            cns_node.interpType.set(0)

    # 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):
            cns_node = pm.parentConstraint(lowControls[i - 1],
                                           lowControls[i + 1],
                                           ctl.getParent(),
                                           mo=True)
            # Make the constraint "noFlip"
            cns_node.interpType.set(0)

    # 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 #28
0
def _createSoftTweakControls(name,
                             parent=None,
                             t=datatypes.Matrix(),
                             grps=None,
                             size=0.5):
    root_name = "{}_{}".format(name, "softTweak_root")
    namespace = None
    try:
        # simple check if exist a tweak with the same name
        exist = pm.PyNode(root_name)
        if exist:
            pm.displayError("the tweak: {} already exist. Please use a "
                            "unique name.".format(name))
            return False, False
    except pm.MayaNodeError:
        if parent:
            try:
                p = pm.PyNode(parent)
                namespace = p.namespace()

            except pm.MayaNodeError:
                pm.displayWarning("{} is not a valid parent or doesn't "
                                  "exist".format(parent))
                p = None
        else:
            p = None
        root = primitive.addTransform(p, root_name, t)
        attribute.addAttribute(root, "iconSize", "float", size, keyable=False)

        baseCtl = icon.create(parent=root,
                              name="{}_{}".format(name, "baseSoftTweak_ctl"),
                              m=t,
                              color=[1, 0.622, 0],
                              icon="square",
                              d=size,
                              w=size)
        tweakCtl = icon.create(parent=baseCtl,
                               name="{}_{}".format(name, "softTweak_ctl"),
                               m=t,
                               color=[0.89, 0.0, 0.143],
                               icon="diamond",
                               w=size * .8)
        attribute.addAttribute(tweakCtl, "falloff", "float", size)
        attribute.addAttribute(tweakCtl, "surfaceMode", "bool", False)

        if grps:
            if not isinstance(grps, list):
                grps = [grps]
            for grp in grps:
                try:
                    # try if exist
                    oGrp = pm.PyNode(grp)
                except pm.MayaNodeError:
                    # create a new grp if does't exist
                    if len(grp.split("_")) >= 3:  # check  name convention
                        name = grp
                    else:
                        name = "rig_{}_grp".format(grp)

                        # namespace basic handling
                        # NOTE: Doesn't support more than one namespace stacked
                        if namespace and len(name.split(":")) < 2:
                            name = namespace + name

                    oGrp = pm.sets(n=name, em=True)

                pm.sets(oGrp, add=[baseCtl, tweakCtl])
        if t:
            root.setMatrix(t, worldSpace=True)

        return baseCtl, tweakCtl
def addCtlMetadata(self, ctl):
    # type: (component.Main, pm.datatypes.Transform) -> None

    name = ctl.name()

    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)

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