def addObjects(self): self.root = self.addRoot() vTemp = transform.getOffsetPosition(self.root, [0, 0, 1]) self.sizeRef = self.addLoc("sizeRef", self.root, vTemp) pm.delete(self.sizeRef.getShapes()) attribute.lockAttribute(self.sizeRef)
def create_channel_master_node(name): """Create a new channel master node Args: name (str): name of the nodes Returns: str: name of the channel master node """ # Create data node (render sphere for outliner "icon") shp = cmds.createNode("renderSphere") cmds.setAttr("{}.radius".format(shp), 0) cmds.setAttr("{}.isHistoricallyInteresting".format(shp), 0) cmds.setAttr("{}.v".format(shp), 0) # Rename data node node = cmds.listRelatives(shp, p=True)[0] node = cmds.rename(node, string.normalize(name)) cmds.addAttr(node, ln=__TAG__, at="bool", dv=True) cmds.setAttr("{}.{}".format(node, __TAG__), k=False, l=True) cmds.addAttr(node, ln="data", dt="string") attribute.lockAttribute(pm.PyNode(node)) # init data cmds.setAttr("{}.data".format(node), cmu.init_channel_master_config_data(), type="string") return node
def addObjects(self): self.root = self.add2DRoot() vTemp = transform.getOffsetPosition(self.root, [0, 0, 1]) self.sizeRef = self.addLoc("sizeRef", self.root, vTemp) pm.delete(self.sizeRef.getShapes()) attribute.lockAttribute(self.sizeRef) # Now we need to show the range of the controls with # template curves. arrow_curves = [ self.addTCurve(self.getName("up"), datatypes.Vector(0, 0, 0), self.root), self.addTCurve(self.getName("right"), datatypes.Vector(0, 0, -90), self.root), self.addTCurve(self.getName("down"), datatypes.Vector(0, 0, 180), self.root), self.addTCurve(self.getName("left"), datatypes.Vector(0, 0, 90), self.root) ] for [arrow_curve, param] in zip(arrow_curves, ["ty_positive", "tx_positive", "ty_negative", "tx_negative"]): sh = arrow_curve.getShape() sh.template.set(1) self.root.attr(param) >> sh.visibility self.root.addChild(sh, add=True, shape=True) pm.delete(arrow_curves)
def finalize(self): """Finalize and clean the rig builing.""" # locking the attributes for all the ctl parents that are not ctl # itself. for t in self.transform2Lock: attribute.lockAttribute(t) return
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
def addObjects(self): self.root = self.addRoot() vTemp = transform.getOffsetPosition(self.root, [0, 0, 1]) self.sizeRef = self.addLoc("sizeRef", self.root, vTemp) pm.delete(self.sizeRef.getShapes()) attribute.lockAttribute(self.sizeRef) self.lookat = self.addLoc("lookat", self.root, vTemp) v = transform.getTranslation(self.root) self.sliding_surface = self.addSliderSurface("sliding_surface", self.root, v)
def addObjects(self): self.root = self.addRoot() vTemp = transform.getOffsetPosition(self.root, [0, 0, 1]) self.sizeRef = self.addLoc("sizeRef", self.root, vTemp) pm.delete(self.sizeRef.getShapes()) attribute.lockAttribute(self.sizeRef) vTemp = transform.getOffsetPosition(self.root, [0, 0, 0]) self.pivot = self.addLoc("pivot", self.root, vTemp) centers = [self.root, self.pivot] self.dispcrv = self.addDispCurve("crv", centers)
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) # this attribute will help to track the edit state to speed up the callback attribute.addAttribute(layer_node, "edit_state", "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 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 postConnect(self): """Post connection actions.""" # lock parameters xform_attrs = ["tx", "ty", "tz", "rx", "ry", "rz", "sx", "sy", "sz"] att.lockAttribute(self.fk_cns, xform_attrs) att.lockAttribute(self.ik_cns, xform_attrs) att.lockAttribute(self.ikRot_cns, xform_attrs) # self.fk_cns.setAttr("visibility", False) # self.ik_cns.setAttr("visibility", False) # self.ikRot_cns.setAttr("visibility", False) for npo in self.fk_npo: att.lockAttribute(npo, xform_attrs) # npo.setAttr("visibility", False) for chain in self.chain: chain.setAttr("visibility", False) att.setKeyableAttributes(self.ikRot_ctl, ["rx", "ry", "rz"])
def addObjects(self): """Add the Guide Root, blade and locators""" lockAttrs = ["tx", "ry", "rz"] self.root = self.addRoot() vTemp = transform.getOffsetPosition(self.root, [0, -3, 0.1]) self.knee = self.addLoc("knee", self.root, vTemp) attribute.lockAttribute(self.knee, lockAttrs) vTemp = transform.getOffsetPosition(self.root, [0, -6, 0]) self.ankle = self.addLoc("ankle", self.knee, vTemp) attribute.lockAttribute(self.ankle, lockAttrs) vTemp = transform.getOffsetPosition(self.root, [0, -9, .2]) self.foot = self.addLoc("foot", self.ankle, vTemp) attribute.lockAttribute(self.foot, lockAttrs) vTemp = transform.getOffsetPosition(self.root, [0, -9, 1]) self.eff = self.addLoc("eff", self.foot, vTemp) centers = [self.root, self.knee, self.ankle, self.foot, self.eff] self.dispcrv = self.addDispCurve("crv1", centers)
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"))
def addObjects(self): """Add all the objects needed to create the component.""" self.setup = primitive.addTransformFromPos( self.setupWS, self.getName("WS")) attribute.lockAttribute(self.setup) self.WIP = self.options["mode"] self.normal = self.getNormalFromPos(self.guide.apos) self.length0 = vector.getDistance(self.guide.apos[0], self.guide.apos[1]) self.length1 = vector.getDistance(self.guide.apos[1], self.guide.apos[2]) self.length2 = vector.getDistance(self.guide.apos[2], self.guide.apos[3]) self.length3 = vector.getDistance(self.guide.apos[3], self.guide.apos[4]) # 3bones chain self.chain3bones = primitive.add2DChain( self.setup, self.getName("chain3bones%s_jnt"), self.guide.apos[0:4], self.normal, False, self.WIP) # 2bones chain self.chain2bones = primitive.add2DChain( self.setup, self.getName("chain2bones%s_jnt"), self.guide.apos[0:3], self.normal, False, self.WIP) # Leg chain self.legBones = primitive.add2DChain( self.root, self.getName("legBones%s_jnt"), self.guide.apos[0:4], self.normal, False, self.WIP) # Leg chain FK ref self.legBonesFK = primitive.add2DChain( self.root, self.getName("legFK%s_jnt"), self.guide.apos[0:4], self.normal, False, self.WIP) # Leg chain IK ref self.legBonesIK = primitive.add2DChain( self.root, self.getName("legIK%s_jnt"), self.guide.apos[0:4], self.normal, False, self.WIP) # 1 bone chain for upv ref self.legChainUpvRef = primitive.add2DChain( self.root, self.getName("legUpvRef%s_jnt"), [self.guide.apos[0], self.guide.apos[3]], self.normal, False, self.WIP) # mid joints self.mid1_jnt = primitive.addJoint( self.legBones[0], self.getName("mid1_jnt"), self.legBones[1].getMatrix(worldSpace=True), self.WIP) self.mid1_jnt.attr("radius").set(3) self.mid1_jnt.setAttr("jointOrient", 0, 0, 0) self.mid2_jnt = primitive.addJoint( self.legBones[1], self.getName("mid2_jnt"), self.legBones[2].getMatrix(worldSpace=True), self.WIP) self.mid2_jnt.attr("radius").set(3) self.mid2_jnt.setAttr("jointOrient", 0, 0, 0) # base Controlers ----------------------------------- t = transform.getTransformFromPos(self.guide.apos[0]) self.root_npo = primitive.addTransform( self.root, self.getName("root_npo"), t) self.root_ctl = self.addCtl(self.root_npo, "root_ctl", t, self.color_fk, "circle", w=self.length0 / 6, tp=self.parentCtlTag) attribute.lockAttribute(self.root_ctl, ["sx", "sy", "sz", "v"]) # FK Controlers ----------------------------------- t = transform.getTransformLookingAt(self.guide.apos[0], self.guide.apos[1], self.normal, "xz", self.negate) self.fk0_npo = primitive.addTransform( self.root_ctl, self.getName("fk0_npo"), t) self.fk0_ctl = self.addCtl( self.fk0_npo, "fk0_ctl", t, self.color_fk, "cube", w=self.length0, h=self.size * .1, d=self.size * .1, po=datatypes.Vector(.5 * self.length0 * self.n_factor, 0, 0), tp=self.root_ctl) attribute.setKeyableAttributes(self.fk0_ctl) t = transform.getTransformLookingAt(self.guide.apos[1], self.guide.apos[2], self.normal, "xz", self.negate) self.fk1_npo = primitive.addTransform( self.fk0_ctl, self.getName("fk1_npo"), t) self.fk1_ctl = self.addCtl( self.fk1_npo, "fk1_ctl", t, self.color_fk, "cube", w=self.length1, h=self.size * .1, d=self.size * .1, po=datatypes.Vector(.5 * self.length1 * self.n_factor, 0, 0), tp=self.fk0_ctl) attribute.setKeyableAttributes(self.fk1_ctl) t = transform.getTransformLookingAt(self.guide.apos[2], self.guide.apos[3], self.normal, "xz", self.negate) self.fk2_npo = primitive.addTransform( self.fk1_ctl, self.getName("fk2_npo"), t) self.fk2_ctl = self.addCtl( self.fk2_npo, "fk2_ctl", t, self.color_fk, "cube", w=self.length2, h=self.size * .1, d=self.size * .1, po=datatypes.Vector(.5 * self.length2 * self.n_factor, 0, 0), tp=self.fk1_ctl) attribute.setKeyableAttributes(self.fk2_ctl) t = transform.getTransformLookingAt(self.guide.apos[3], self.guide.apos[4], self.normal, "xz", self.negate) self.fk3_npo = primitive.addTransform( self.fk2_ctl, self.getName("fk3_npo"), t) self.fk3_ctl = self.addCtl( self.fk3_npo, "fk3_ctl", t, self.color_fk, "cube", w=self.length3, h=self.size * .1, d=self.size * .1, po=datatypes.Vector(.5 * self.length3 * self.n_factor, 0, 0), tp=self.fk2_ctl) attribute.setKeyableAttributes(self.fk3_ctl) self.fk_ctl = [self.fk0_ctl, self.fk1_ctl, self.fk2_ctl, self.fk3_ctl] for x in self.fk_ctl: attribute.setInvertMirror(x, ["tx", "ty", "tz"]) # Mid Controlers ------------------------------------ self.knee_lvl = primitive.addTransform( self.root, self.getName("knee_lvl"), transform.getTransform(self.mid1_jnt)) self.knee_ctl = self.addCtl( self.knee_lvl, "knee_ctl", transform.getTransform(self.mid1_jnt), self.color_ik, "sphere", w=self.size * .2, tp=self.root_ctl) attribute.setInvertMirror(self.knee_ctl, ["tx", "ty", "tz"]) attribute.lockAttribute(self.knee_ctl, ["sx", "sy", "sz", "v"]) self.ankle_lvl = primitive.addTransform( self.root, self.getName("ankle_lvl"), transform.getTransform(self.mid2_jnt)) self.ankle_ctl = self.addCtl( self.ankle_lvl, "ankle_ctl", transform.getTransform(self.mid2_jnt), self.color_ik, "sphere", w=self.size * .2, tp=self.knee_ctl) attribute.setInvertMirror(self.ankle_ctl, ["tx", "ty", "tz"]) attribute.lockAttribute(self.ankle_ctl, ["sx", "sy", "sz", "v"]) # IK controls -------------------------------------------------------- # foot IK # "z-x", t_align = transform.getTransformLookingAt(self.guide.apos[3], self.guide.apos[4], self.normal, "zx", False) if self.settings["ikOri"]: t = transform.getTransformFromPos(self.guide.pos["foot"]) # t = transform.getTransformLookingAt(self.guide.pos["foot"], # self.guide.pos["eff"], # self.x_axis, # "zx", # False) else: t = t_align self.ik_cns = primitive.addTransform( self.root_ctl, self.getName("ik_cns"), t) self.ikcns_ctl = self.addCtl(self.ik_cns, "ikcns_ctl", t, self.color_ik, "null", w=self.size * .12, tp=self.ankle_ctl) attribute.setInvertMirror(self.ikcns_ctl, ["tx"]) attribute.lockAttribute(self.ikcns_ctl, ["sx", "sy", "sz", "v"]) self.ik_ctl = self.addCtl(self.ikcns_ctl, "ik_ctl", t, self.color_ik, "cube", w=self.size * .12, h=self.size * .12, d=self.size * .12, tp=self.ikcns_ctl) attribute.setKeyableAttributes(self.ik_ctl) attribute.setRotOrder(self.ik_ctl, "XZY") attribute.setInvertMirror(self.ik_ctl, ["tx", "ry", "rz"]) attribute.lockAttribute(self.ik_ctl, ["sx", "sy", "sz", "v"]) # 2 bones ik layer self.ik2b_ikCtl_ref = primitive.addTransform( self.ik_ctl, self.getName("ik2B_A_ref"), t_align) self.ik2b_bone_ref = primitive.addTransform( self.chain3bones[3], self.getName("ik2B_B_ref"), t_align) self.ik2b_blend = primitive.addTransform( self.ik_ctl, self.getName("ik2B_blend"), t_align) self.roll_ctl = self.addCtl(self.ik2b_blend, "roll_ctl", t_align, self.color_ik, "crossarrow", w=self.length2 * .5 * self.n_factor, tp=self.ik_ctl) self.ik2b_ik_npo = primitive.addTransform( self.roll_ctl, self.getName("ik2B_ik_npo"), transform.getTransform(self.chain3bones[-1])) self.ik2b_ik_ref = primitive.addTransformFromPos( self.ik2b_ik_npo, self.getName("ik2B_ik_ref"), self.guide.pos["ankle"]) attribute.lockAttribute( self.roll_ctl, ["tx", "ty", "tz", "sx", "sy", "sz", "v"]) # upv v = self.guide.apos[2] - self.guide.apos[0] v = self.normal ^ v v.normalize() v *= self.size * .5 v += self.guide.apos[1] self.upv_lvl = primitive.addTransformFromPos( self.root, self.getName("upv_lvl"), v) self.upv_cns = primitive.addTransformFromPos( self.upv_lvl, self.getName("upv_cns"), v) self.upv_ctl = self.addCtl(self.upv_cns, "upv_ctl", transform.getTransform(self.upv_cns), self.color_ik, "diamond", w=self.size * .12, tp=self.ik_ctl) attribute.setInvertMirror(self.upv_ctl, ["tx"]) attribute.setKeyableAttributes(self.upv_ctl, ["tx", "ty", "tz"]) # Soft IK objects 3 bones chain -------------------------------- t = transform.getTransformLookingAt(self.guide.pos["root"], self.guide.pos["foot"], self.x_axis, "zx", False) self.aim_tra = primitive.addTransform( self.root_ctl, self.getName("aimSoftIK"), t) t = transform.getTransformFromPos(self.guide.pos["foot"]) self.wristSoftIK = primitive.addTransform( self.aim_tra, self.getName("wristSoftIK"), t) self.softblendLoc = primitive.addTransform( self.root, self.getName("softblendLoc"), t) # Soft IK objects 2 Bones chain ---------------------------- t = transform.getTransformLookingAt(self.guide.pos["root"], self.guide.pos["ankle"], self.x_axis, "zx", False) self.aim_tra2 = primitive.addTransform( self.root_ctl, self.getName("aimSoftIK2"), t) t = transform.getTransformFromPos(self.guide.pos["ankle"]) self.ankleSoftIK = primitive.addTransform( self.aim_tra2, self.getName("ankleSoftIK"), t) self.softblendLoc2 = primitive.addTransform( self.root, self.getName("softblendLoc2"), t) # References -------------------------------------- self.ik_ref = primitive.addTransform( self.ik_ctl, self.getName("ik_ref"), transform.getTransform(self.ik_ctl)) self.fk_ref = primitive.addTransform( self.fk_ctl[3], self.getName("fk_ref"), transform.getTransform(self.ik_ctl)) # twist references -------------------------------------- self.rollRef = primitive.add2DChain(self.root, self.getName("rollChain"), self.guide.apos[:2], self.normal, False, self.WIP) self.tws0_loc = primitive.addTransform( self.rollRef[0], self.getName("tws0_loc"), transform.getTransform(self.legBones[0])) self.tws0_rot = primitive.addTransform( self.tws0_loc, self.getName("tws0_rot"), transform.getTransform(self.legBones[0])) self.tws0_rot.setAttr("sx", .001) self.tws1_loc = primitive.addTransform( self.mid1_jnt, self.getName("tws1_loc"), transform.getTransform(self.mid1_jnt)) self.tws1_rot = primitive.addTransform( self.tws1_loc, self.getName("tws1_rot"), transform.getTransform(self.mid1_jnt)) self.tws1_rot.setAttr("sx", .001) self.tws2_loc = primitive.addTransform( self.mid2_jnt, self.getName("tws2_loc"), transform.getTransform(self.mid2_jnt)) self.tws2_rot = primitive.addTransform( self.tws2_loc, self.getName("tws2_rot"), transform.getTransform(self.mid2_jnt)) self.tws2_rot.setAttr("sx", .001) self.tws3_loc = primitive.addTransform( self.legBones[3], self.getName("tws3_loc"), transform.getTransform(self.legBones[3])) self.tws3_rot = primitive.addTransform( self.tws3_loc, self.getName("tws3_rot"), transform.getTransform(self.legBones[3])) self.tws3_rot.setAttr("sx", .001) # Divisions ---------------------------------------- # We have at least one division at the start, the end and one for # the knee and one ankle o_set = self.settings self.divisions = o_set["div0"] + o_set["div1"] + o_set["div2"] + 4 self.div_cns = [] for i in range(self.divisions): div_cns = primitive.addTransform(self.root_ctl, self.getName("div%s_loc" % i)) self.div_cns.append(div_cns) self.jnt_pos.append([div_cns, i]) # End reference ------------------------------------ # To help the deformation on the foot self.end_ref = primitive.addTransform( self.tws3_rot, self.getName("end_ref"), transform.getTransform(self.legBones[3])) self.jnt_pos.append([self.end_ref, 'end']) # match IK FK references self.match_fk0_off = primitive.addTransform( self.root, self.getName("matchFk0_npo"), transform.getTransform(self.fk_ctl[1])) self.match_fk0 = primitive.addTransform( self.match_fk0_off, self.getName("fk0_mth"), transform.getTransform(self.fk_ctl[0])) self.match_fk1_off = primitive.addTransform( self.root, self.getName("matchFk1_npo"), transform.getTransform(self.fk_ctl[2])) self.match_fk1 = primitive.addTransform( self.match_fk1_off, self.getName("fk1_mth"), transform.getTransform(self.fk_ctl[1])) self.match_fk2_off = primitive.addTransform( self.root, self.getName("matchFk2_npo"), transform.getTransform(self.fk_ctl[3])) self.match_fk2 = primitive.addTransform( self.match_fk2_off, self.getName("fk2_mth"), transform.getTransform(self.fk_ctl[2])) self.match_fk3 = primitive.addTransform( self.ik_ctl, self.getName("fk3_mth"), transform.getTransform(self.fk_ctl[3])) self.match_ik = primitive.addTransform( self.fk3_ctl, self.getName("ik_mth"), transform.getTransform(self.ik_ctl)) self.match_ikUpv = primitive.addTransform( self.fk0_ctl, self.getName("upv_mth"), transform.getTransform(self.upv_ctl)) # add visual reference self.line_ref = icon.connection_display_curve( self.getName("visalRef"), [self.upv_ctl, self.knee_ctl])
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # Visibilities ------------------------------------- # ik if self.settings["useRollCtl"]: for shp in self.roll_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for bk_ctl in self.bk_ctl: for shp in bk_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.heel_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.tip_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # Roll / Bank -------------------------------------- if self.settings["useRollCtl"]: # Using the controler self.roll_att = self.roll_ctl.attr("rz") self.bank_att = self.roll_ctl.attr("rx") clamp_node = node.createClampNode( [self.roll_att, self.bank_att, self.bank_att], [0, -180, 0], [180, 0, 180]) inAdd_nod = node.createAddNode( clamp_node + ".outputB", pm.getAttr(self.in_piv.attr("rx")) * self.n_factor) pm.connectAttr(clamp_node + ".outputR", self.heel_loc.attr("rz")) pm.connectAttr(clamp_node + ".outputG", self.out_piv.attr("rx")) pm.connectAttr(inAdd_nod + ".output", self.in_piv.attr("rx")) # Reverse Controler offset ------------------------- angle_outputs = node.createAddNodeMulti(self.angles_att) for i, bk_loc in enumerate(reversed(self.bk_loc)): if i == 0: # First input = self.roll_att min_input = self.angles_att[i] elif i == len(self.angles_att): # Last sub_nod = node.createSubNode(self.roll_att, angle_outputs[i - 1]) input = sub_nod + ".output" min_input = -360 else: # Others sub_nod = node.createSubNode(self.roll_att, angle_outputs[i - 1]) input = sub_nod + ".output" min_input = self.angles_att[i] clamp_node = node.createClampNode(input, min_input, 0) add_node = node.createAddNode(clamp_node + ".outputR", bk_loc.getAttr("rz")) pm.connectAttr(add_node + ".output", bk_loc.attr("rz")) # Reverse compensation ----------------------------- for i, fk_loc in enumerate(self.fk_loc): bk_ctl = self.bk_ctl[-i - 1] bk_loc = self.bk_loc[-i - 1] fk_ctl = self.fk_ctl[i] # Inverse Rotorder applyop.gear_inverseRotorder_op(bk_loc, fk_ctl) pm.connectAttr(fk_ctl.attr("ro"), fk_loc.attr("ro")) attribute.lockAttribute(bk_loc, "ro") # Compensate the backward rotation # ik # addx_node = node.createAddNode(bk_loc.attr("rx"), bk_loc.attr("rx")) # addy_node = node.createAddNode(bk_loc.attr("ry"), bk_loc.attr("ry")) # addz_node = node.createAddNode(bk_loc.attr("rz"), bk_loc.attr("rz")) addz_node = node.createAddNode( bk_loc.attr("rz"), -bk_loc.getAttr("rz") - fk_loc.getAttr("rz")) neg_node = node.createMulNode([bk_loc.attr("rx"), bk_loc.attr("ry"), addz_node + ".output"], [-1, -1, -1]) ik_outputs = [neg_node + ".outputX", neg_node + ".outputY", neg_node + ".outputZ"] # fk fk_outputs = [0, 0, fk_loc.getAttr("rz")] # blend blend_node = node.createBlendNode(ik_outputs, fk_outputs, self.blend_att) pm.connectAttr(blend_node + ".output", fk_loc.attr("rotate")) return
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 addObjects(self): """Add all the objects needed to create the component.""" self.normal = self.guide.blades["blade"].z * -1 self.binormal = self.guide.blades["blade"].x self.isFk = self.settings["mode"] != 1 self.isIk = self.settings["mode"] != 0 self.isFkIk = self.settings["mode"] == 2 self.WIP = self.options["mode"] # FK controllers ------------------------------------ if self.isFk: self.fk_npo = [] self.fk_ctl = [] self.fk_ref = [] self.fk_off = [] t = self.guide.tra["root"] self.ik_cns = primitive.addTransform(self.root, self.getName("ik_cns"), t) parent = self.ik_cns tOld = False fk_ctl = None self.previousTag = self.parentCtlTag for i, t in enumerate( transform.getChainTransform(self.guide.apos, self.normal, self.negate)): dist = vector.getDistance(self.guide.apos[i], self.guide.apos[i + 1]) if self.settings["neutralpose"] or not tOld: tnpo = t else: tnpo = transform.setMatrixPosition( tOld, transform.getPositionFromMatrix(t)) if i: tref = transform.setMatrixPosition( tOld, transform.getPositionFromMatrix(t)) fk_ref = primitive.addTransform( fk_ctl, self.getName("fk%s_ref" % i), tref) self.fk_ref.append(fk_ref) else: tref = t fk_off = primitive.addTransform(parent, self.getName("fk%s_off" % i), tref) fk_npo = primitive.addTransform(fk_off, self.getName("fk%s_npo" % i), tnpo) # ro is rotation offset. Yup. They coded it in radians... 1.5708 rad is 90 deg :\ fk_ctl = self.addCtl( fk_npo, "fk%s_ctl" % i, t, self.color_fk, "compas", w=dist, po=datatypes.Vector(0, 0, 0), ro=datatypes.Vector(-1.5708, 0 - 1.5708), tp=self.previousTag, ) # lock vis attribute.lockAttribute(fk_ctl, attributes=['v']) # set rotateOrder to xzy. "Barrel roll" rotx remains stable. Spread roty stays on plane of hands. fk_ctl.rotateOrder.set(3) self.fk_off.append(fk_off) self.fk_npo.append(fk_npo) self.fk_ctl.append(fk_ctl) tOld = t self.previousTag = fk_ctl # IK controllers ------------------------------------ if self.isIk: normal = vector.getTransposedVector( self.normal, [self.guide.apos[0], self.guide.apos[1]], [self.guide.apos[-2], self.guide.apos[-1]]) t = transform.getTransformLookingAt(self.guide.apos[-2], self.guide.apos[-1], normal, "xy", self.negate) t = transform.setMatrixPosition(t, self.guide.apos[-1]) self.ik_cns = primitive.addTransform(self.root, self.getName("ik_cns"), t) self.ikcns_ctl = self.addCtl(self.ik_cns, "ikcns_ctl", t, self.color_ik, "null", w=self.size, tp=self.parentCtlTag) self.ik_ctl = self.addCtl(self.ikcns_ctl, "ik_ctl", t, self.color_ik, "cube", w=self.size * .3, h=self.size * .3, d=self.size * .3, tp=self.ikcns_ctl) attribute.setKeyableAttributes(self.ik_ctl, self.t_params) attribute.lockAttribute(self.ik_ctl, attributes=['v']) v = self.guide.apos[-1] - self.guide.apos[0] v = v ^ self.normal v.normalize() v *= self.size v += self.guide.apos[1] self.upv_cns = primitive.addTransformFromPos( self.root, self.getName("upv_cns"), v) self.upv_ctl = self.addCtl(self.upv_cns, "upv_ctl", transform.getTransform(self.upv_cns), self.color_ik, "diamond", w=self.size * .1, tp=self.parentCtlTag) attribute.setKeyableAttributes(self.upv_ctl, self.t_params) # Chain self.chain = primitive.add2DChain(self.root, self.getName("chain"), self.guide.apos, self.normal, self.negate) self.chain[0].attr("visibility").set(self.WIP) # Chain of deformers ------------------------------- self.loc = [] parent = self.root for i, t in enumerate( transform.getChainTransform(self.guide.apos, self.normal, self.negate)): loc = primitive.addTransform(parent, self.getName("%s_loc" % i), t) self.loc.append(loc) self.jnt_pos.append([loc, i, None, False])
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # Visibilities ------------------------------------- if self.isFkIk: # fk fkvis_node = node.createReverseNode(self.blend_att) for fk_ctl in self.fk_ctl: for shp in fk_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) # ik for shp in self.upv_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ikcns_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ik_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # FK Chain ----------------------------------------- if self.isFk: for off, ref in zip(self.fk_off[1:], self.fk_ref): applyop.gear_mulmatrix_op(ref.worldMatrix, off.parentInverseMatrix, off, "rt") # IK Chain ----------------------------------------- if self.isIk: self.ikh = primitive.addIkHandle(self.root, self.getName("ikh"), self.chain) self.ikh.attr("visibility").set(False) # Constraint and up vector pm.pointConstraint(self.ik_ctl, self.ikh, maintainOffset=False) pm.poleVectorConstraint(self.upv_ctl, self.ikh) # TwistTest o_list = [round(elem, 4) for elem in transform.getTranslation(self.chain[1])] \ != [round(elem, 4) for elem in self.guide.apos[1]] if o_list: add_nodeTwist = node.createAddNode(180.0, self.roll_att) pm.connectAttr(add_nodeTwist + ".output", self.ikh.attr("twist")) else: pm.connectAttr(self.roll_att, self.ikh.attr("twist")) # Chain of deformers ------------------------------- if self.settings["mode"] == 0: # fk only # Loop until the last one and connect aim constraints from index+1 for i, loc in enumerate(self.loc[0:-1]): pm.pointConstraint(self.fk_ctl[i], loc, maintainOffset=False) pm.connectAttr(self.fk_ctl[i] + ".scale", loc + ".scale") pm.aimConstraint( self.fk_ctl[i + 1], loc, maintainOffset=False, aimVector=(1, 0, 0), upVector=(0, 1, 0), worldUpType='none', ) oRoot = rigbits.addNPO(loc)[0] pm.parentConstraint(self.fk_ctl[i], oRoot, mo=True) attribute.lockAttribute(oRoot) # Then connect the last in the chain as a parent constraint pm.parentConstraint(self.fk_ctl[-1], self.loc[-1], maintainOffset=False) pm.connectAttr(self.fk_ctl[-1] + ".scale", self.loc[-1] + ".scale")
def addJoint(self, obj, name, newActiveJnt=None, UniScale=False, segComp=0, gearMulMatrix=True): """Add joint as child of the active joint or under driver object. Args: obj (dagNode): The input driver object for the joint. name (str): The joint name. newActiveJnt (bool or dagNode): If a joint is pass, this joint will be the active joint and parent of the newly created joint. UniScale (bool): Connects the joint scale with the Z axis for a unifor scalin, if set Falsewill connect with each axis separated. segComp (bool): Set True or False the segment compensation in the joint.. gearMulMatrix (bool): Use the custom gear_multiply matrix node, if False will use Maya's default mulMatrix node. Returns: dagNode: The newly created joint. """ customName = self.getCustomJointName(len(self.jointList)) if self.options["joint_rig"]: if newActiveJnt: self.active_jnt = newActiveJnt jnt = primitive.addJoint(self.active_jnt, customName or self.getName(str(name) + "_jnt"), transform.getTransform(obj)) # Disconnect inversScale for better preformance if isinstance(self.active_jnt, pm.nodetypes.Joint): try: pm.disconnectAttr(self.active_jnt.scale, jnt.inverseScale) except RuntimeError: # This handle the situation where we have in between joints # transformation due a negative scaling pm.ungroup(jnt.getParent()) # All new jnts are the active by default self.active_jnt = jnt if gearMulMatrix: mulmat_node = applyop.gear_mulmatrix_op( obj + ".worldMatrix", jnt + ".parentInverseMatrix") dm_node = node.createDecomposeMatrixNode( mulmat_node + ".output") m = mulmat_node.attr('output').get() else: mulmat_node = node.createMultMatrixNode( obj + ".worldMatrix", jnt + ".parentInverseMatrix") dm_node = node.createDecomposeMatrixNode( mulmat_node + ".matrixSum") m = mulmat_node.attr('matrixSum').get() pm.connectAttr(dm_node + ".outputTranslate", jnt + ".t") pm.connectAttr(dm_node + ".outputRotate", jnt + ".r") # TODO: fix squash stretch solver to scale the joint uniform # the next line cheat the uniform scaling only fo X or Y axis # oriented joints if self.options["force_uniScale"]: UniScale = True # invert negative scaling in Joints. We only inver Z axis, so is # the only axis that we are checking if dm_node.attr("outputScaleZ").get() < 0: mul_nod_invert = node.createMulNode( dm_node.attr("outputScaleZ"), -1) out_val = mul_nod_invert.attr("outputX") else: out_val = dm_node.attr("outputScaleZ") # connect scaling if UniScale: pm.connectAttr(out_val, jnt + ".sx") pm.connectAttr(out_val, jnt + ".sy") pm.connectAttr(out_val, jnt + ".sz") else: pm.connectAttr(dm_node.attr("outputScaleX"), jnt + ".sx") pm.connectAttr(dm_node.attr("outputScaleY"), jnt + ".sy") pm.connectAttr(out_val, jnt + ".sz") pm.connectAttr(dm_node + ".outputShear", jnt + ".shear") # Segment scale compensate Off to avoid issues with the global # scale jnt.setAttr("segmentScaleCompensate", segComp) jnt.setAttr("jointOrient", 0, 0, 0) # setting the joint orient compensation in order to have clean # rotation channels jnt.attr("jointOrientX").set(jnt.attr("rx").get()) jnt.attr("jointOrientY").set(jnt.attr("ry").get()) jnt.attr("jointOrientZ").set(jnt.attr("rz").get()) im = m.inverse() if gearMulMatrix: mul_nod = applyop.gear_mulmatrix_op( mulmat_node.attr('output'), im, jnt, 'r') dm_node2 = mul_nod.output.listConnections()[0] else: mul_nod = node.createMultMatrixNode( mulmat_node.attr('matrixSum'), im, jnt, 'r') dm_node2 = mul_nod.matrixSum.listConnections()[0] # if jnt.attr("sz").get() < 0: if dm_node.attr("outputScaleZ").get() < 0: # if negative scaling we have to negate some axis for rotation neg_rot_node = pm.createNode("multiplyDivide") pm.setAttr(neg_rot_node + ".operation", 1) pm.connectAttr(dm_node2.outputRotate, neg_rot_node + ".input1", f=True) for v, axis in zip([-1, -1, 1], "XYZ"): pm.setAttr(neg_rot_node + ".input2" + axis, v) pm.connectAttr(neg_rot_node + ".output", jnt + ".r", f=True) # set not keyable attribute.setNotKeyableAttributes(jnt) else: jnt = primitive.addJoint(obj, customName or self.getName(str(name) + "_jnt"), transform.getTransform(obj)) pm.connectAttr(self.rig.jntVis_att, jnt.attr("visibility")) attribute.lockAttribute(jnt) self.addToGroup(jnt, "deformers") # This is a workaround due the evaluation problem with compound attr # TODO: This workaround, should be removed onces the evaluation issue # is fixed # github issue: Shifter: Joint connection: Maya evaluation Bug #210 dm = jnt.r.listConnections(p=True, type="decomposeMatrix") if dm: at = dm[0] dm_node = at.node() pm.disconnectAttr(at, jnt.r) pm.connectAttr(dm_node.outputRotateX, jnt.rx) pm.connectAttr(dm_node.outputRotateY, jnt.ry) pm.connectAttr(dm_node.outputRotateZ, jnt.rz) dm = jnt.t.listConnections(p=True, type="decomposeMatrix") if dm: at = dm[0] dm_node = at.node() pm.disconnectAttr(at, jnt.t) pm.connectAttr(dm_node.outputTranslateX, jnt.tx) pm.connectAttr(dm_node.outputTranslateY, jnt.ty) pm.connectAttr(dm_node.outputTranslateZ, jnt.tz) # dm = jnt.s.listConnections(p=True, type="decomposeMatrix") # if dm: # at = dm[0] # dm_node = at.node() # pm.disconnectAttr(at, jnt.s) # pm.connectAttr(dm_node.outputScaleX, jnt.sx) # pm.connectAttr(dm_node.outputScaleY, jnt.sy) # pm.connectAttr(dm_node.outputScaleZ, jnt.sz) return jnt