8099 lines
389 KiB
Python
8099 lines
389 KiB
Python
#Author: Jeremy Ernst
|
|
#Date: 4.9.13
|
|
|
|
|
|
|
|
import maya.cmds as cmds
|
|
import maya.mel as mel
|
|
import os, ast
|
|
import Modules.ART_UpperLegIKTwist as uplegik
|
|
import Modules.ART_rigUtils as utils
|
|
|
|
reload(uplegik)
|
|
|
|
class AutoRigger():
|
|
|
|
def __init__(self, handCtrlSpace, progressBar):
|
|
|
|
|
|
self.handCtrlSpace = handCtrlSpace
|
|
|
|
#get access to our maya tools
|
|
toolsPath = cmds.internalVar(usd = True) + "mayaTools.txt"
|
|
if os.path.exists(toolsPath):
|
|
|
|
f = open(toolsPath, 'r')
|
|
self.mayaToolsDir = f.readline()
|
|
f.close()
|
|
|
|
|
|
#create a progress window to track the progress of the rig build
|
|
self.progress = 0
|
|
cmds.progressBar(progressBar, edit = True, progress=self.progress, status='Creating Spine Rig')
|
|
|
|
|
|
|
|
#build the core of the rig
|
|
import Modules.ART_Core
|
|
coreNodes = Modules.ART_Core.RigCore()
|
|
|
|
|
|
#BODY CONTROL
|
|
self.buildHips()
|
|
|
|
"""
|
|
#create the rig settings node
|
|
"Rig_Settings" = cmds.group(empty = True, name = "Rig_Settings")
|
|
cmds.setAttr("Rig_Settings" + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".rx", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".ry", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".rz", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr("Rig_Settings" + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#build the spine rigs
|
|
self.createDriverSkeleton()
|
|
self.buildCoreComponents()
|
|
"""
|
|
|
|
#to be replaced by modules
|
|
fkControls = self.buildFKSpine()
|
|
ikControls = self.buildIKSpine(fkControls)
|
|
|
|
|
|
#build the leg rigs
|
|
|
|
#first determine the leg style
|
|
legStyle = cmds.getAttr("SkeletonSettings_Cache.legStyle")
|
|
|
|
if legStyle == "Standard Biped":
|
|
cmds.progressBar(progressBar, edit = True, progress = 20, status='Creating Leg Rigs')
|
|
self.buildFKLegs()
|
|
self.buildIKLegs()
|
|
self.finishLegs()
|
|
|
|
|
|
cmds.progressBar(progressBar, edit = True, progress = 30, status='Creating Toe Rigs')
|
|
self.buildToes()
|
|
cmds.progressBar(progressBar, edit = True, progress = 40, status='Creating Auto Hips and Spine')
|
|
self.buildAutoHips()
|
|
self.autoSpine()
|
|
|
|
if legStyle == "Hind Leg":
|
|
pass
|
|
|
|
|
|
|
|
#build the arms
|
|
cmds.progressBar(progressBar, edit = True, progress = 50, status='Creating Arm Rigs')
|
|
spineBones = self.getSpineJoints()
|
|
lastSpine = "driver_" + spineBones[-1]
|
|
print lastSpine
|
|
import Modules.ART_Arm
|
|
reload(Modules.ART_Arm)
|
|
Modules.ART_Arm.Arm(True, "", None, "l", lastSpine, 6, True)
|
|
Modules.ART_Arm.Arm(True, "", None, "r", lastSpine, 13, True)
|
|
|
|
|
|
"""
|
|
self.buildFKArms()
|
|
self.buildIkArms()
|
|
"""
|
|
|
|
cmds.progressBar(progressBar, edit = True, progress = 60, status='Creating Finger Rigs')
|
|
self.buildFingers()
|
|
|
|
#build the neck and head rig
|
|
cmds.progressBar(progressBar, edit = True, progress = 70, status='Creating Neck and Head Rigs')
|
|
self.buildNeckAndHead()
|
|
|
|
|
|
#rig extra joints
|
|
cmds.progressBar(progressBar, edit = True, progress = 80, status='Creating Rigs for Custom Joints')
|
|
createdControls = self.rigLeafJoints()
|
|
createdJiggleNodes = self.rigJiggleJoints()
|
|
createdChainNodes = self.rigCustomJointChains()
|
|
|
|
|
|
|
|
|
|
|
|
#clean up the hierarchy
|
|
cmds.progressBar(progressBar, edit = True, progress = 90, status='Cleaning up Scene')
|
|
|
|
bodyGrp = cmds.group(empty = True, name = "body_grp")
|
|
for obj in ["spine_splineIK_curve", "splineIK_spine_01_splineIK", "body_anim_space_switcher_follow"]:
|
|
if cmds.objExists(obj):
|
|
cmds.parent(obj, bodyGrp)
|
|
|
|
if cmds.objExists("autoHips_sys_grp"):
|
|
cmds.parent("autoHips_sys_grp", "body_anim")
|
|
|
|
|
|
rigGrp = "ctrl_rig"
|
|
cmds.parent([bodyGrp, "leg_sys_grp"], rigGrp)
|
|
|
|
"""
|
|
rigGrp = cmds.group(empty = True, name = "ctrl_rig")
|
|
cmds.parent([bodyGrp, "leg_sys_grp", "Rig_Settings"], rigGrp)
|
|
cmds.parent(rigGrp, "offset_anim")
|
|
"""
|
|
|
|
|
|
#Arms
|
|
"""
|
|
if cmds.objExists("arm_rig_master_grp_l"):
|
|
cmds.setAttr("Rig_Settings.lArmMode", 1)
|
|
|
|
if cmds.objExists("lowerarm_l_roll_grp"):
|
|
cmds.parent("lowerarm_l_roll_grp", "arm_rig_master_grp_l")
|
|
|
|
cmds.parent("arm_rig_master_grp_l", "ctrl_rig")
|
|
|
|
|
|
if cmds.objExists("arm_rig_master_grp_r"):
|
|
cmds.setAttr("Rig_Settings.rArmMode", 1)
|
|
|
|
if cmds.objExists("lowerarm_r_roll_grp"):
|
|
cmds.parent("lowerarm_r_roll_grp", "arm_rig_master_grp_r")
|
|
|
|
cmds.parent("arm_rig_master_grp_r", "ctrl_rig")
|
|
|
|
if cmds.objExists("arm_rig_master_grp_r") and cmds.objExists("arm_rig_master_grp_l"):
|
|
armSysGrp = cmds.group(empty = True, name = "arm_sys_grp")
|
|
cmds.parent(armSysGrp, "ctrl_rig")
|
|
cmds.parent(["arm_rig_master_grp_r", "arm_rig_master_grp_l", "ik_wrist_l_anim_space_switcher_follow", "ik_wrist_r_anim_space_switcher_follow"], armSysGrp)
|
|
|
|
#arm twists
|
|
if cmds.objExists("upperarm_twist_grp_l"):
|
|
cmds.parent("upperarm_twist_grp_l", armSysGrp)
|
|
|
|
if cmds.objExists("upperarm_twist_grp_r"):
|
|
cmds.parent("upperarm_twist_grp_r", armSysGrp)
|
|
"""
|
|
|
|
|
|
if cmds.objExists("neck_01_fk_anim_grp"):
|
|
cmds.parent("neck_01_fk_anim_grp", "ctrl_rig")
|
|
|
|
#Fingers
|
|
if cmds.objExists("finger_sys_grp_l"):
|
|
cmds.parent("finger_sys_grp_l", "ctrl_rig")
|
|
|
|
if cmds.objExists("finger_sys_grp_r"):
|
|
cmds.parent("finger_sys_grp_r", "ctrl_rig")
|
|
|
|
|
|
#Custom Joints (leaf, jiggle, chain)
|
|
if len(createdControls) > 0:
|
|
for each in createdControls:
|
|
cmds.parent(each, "ctrl_rig")
|
|
|
|
if len(createdJiggleNodes) > 0:
|
|
for each in createdJiggleNodes:
|
|
cmds.parent(each, "ctrl_rig")
|
|
|
|
if len(createdChainNodes) > 0:
|
|
for each in createdChainNodes:
|
|
cmds.parent(each, "ctrl_rig")
|
|
|
|
cmds.parent("head_sys_grp", "ctrl_rig")
|
|
|
|
#finish grouping everything under 1 character grp
|
|
if cmds.objExists("Proxy_Geo_Skin_Grp"):
|
|
try:
|
|
cmds.parent("Proxy_Geo_Skin_Grp", "rig_grp")
|
|
except:
|
|
pass
|
|
|
|
if cmds.objExists("dynHairChain"):
|
|
try:
|
|
cmds.parent("dynHairChain", "rig_grp")
|
|
except:
|
|
pass
|
|
|
|
|
|
#add world spaces to each space switch control
|
|
self.addSpaces()
|
|
|
|
#Hide all joints
|
|
joints = cmds.ls(type = 'joint')
|
|
for joint in joints:
|
|
if cmds.getAttr(joint + ".v", settable = True):
|
|
cmds.setAttr(joint + ".v", 0)
|
|
cmds.progressBar(progressBar, edit = True, progress = 100, status='Cleaning up Scene')
|
|
|
|
#delete the joint mover
|
|
cmds.select("root_mover_grp", r = True, hi = True)
|
|
cmds.select("Skeleton_Settings", add = True)
|
|
nodes = cmds.ls(sl = True, transforms = True)
|
|
cmds.select(clear = True)
|
|
|
|
for node in nodes:
|
|
cmds.lockNode(node, lock = False)
|
|
cmds.lockNode("JointMover", lock = False)
|
|
cmds.delete("JointMover")
|
|
|
|
#find and delete junk nodes/clean scene
|
|
for obj in ["invis_legs_Rig_Settings", "invis_legs_Rig_Settings1", "invis_legs_spine_splineIK_curve", "invis_legs_spine_splineIK_curve1","invis_legs_master_anim_space_switcher_follow", "invis_legs_master_anim_space_switcher_follow1"]:
|
|
try:
|
|
cmds.select("*" + obj + "*")
|
|
selection = cmds.ls(sl = True)
|
|
for each in selection:
|
|
if cmds.objExists(each):
|
|
cmds.delete(each)
|
|
except:
|
|
pass
|
|
|
|
|
|
cmds.select(all = True)
|
|
selection = cmds.ls(sl = True)
|
|
|
|
for each in selection:
|
|
if each.find("invis_") == 0:
|
|
|
|
try:
|
|
parent = cmds.listRelatives(each, parent = True)
|
|
if parent == None:
|
|
cmds.delete(each)
|
|
except:
|
|
pass
|
|
|
|
|
|
|
|
|
|
#set default rotate Orders
|
|
self.setDefaultRotateOrders()
|
|
|
|
#end progress window
|
|
cmds.select(clear = True)
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def setDefaultRotateOrders(self):
|
|
|
|
cmds.setAttr("body_anim.rotateOrder", 5)
|
|
cmds.setAttr("hip_anim.rotateOrder", 5)
|
|
if cmds.objExists("mid_ik_anim"):
|
|
cmds.setAttr("mid_ik_anim.rotateOrder", 5)
|
|
cmds.setAttr("chest_ik_anim.rotateOrder", 5)
|
|
cmds.setAttr("head_fk_anim.rotateOrder", 5)
|
|
|
|
|
|
for control in ["neck_01_fk_anim", "neck_02_fk_anim", "neck_03_fk_anim"]:
|
|
if cmds.objExists(control):
|
|
cmds.setAttr(control + ".rotateOrder", 5)
|
|
|
|
for control in ["spine_01_anim", "spine_02_anim", "spine_03_anim", "spine_04_anim", "spine_05_anim"]:
|
|
if cmds.objExists(control):
|
|
cmds.setAttr(control + ".rotateOrder", 5)
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def addSpaces(self):
|
|
|
|
cmds.select("*_space_switcher_follow")
|
|
nodes = cmds.ls(sl = True)
|
|
spaceSwitchers = []
|
|
for node in nodes:
|
|
if node.find("invis") != 0:
|
|
spaceSwitchers.append(node)
|
|
|
|
|
|
for node in spaceSwitchers:
|
|
#create a 'world' locator to constrain to
|
|
worldLoc = cmds.spaceLocator(name = node + "_world_pos")[0]
|
|
cmds.setAttr(worldLoc + ".v", 0)
|
|
|
|
#position world loc to be in same place as node
|
|
constraint = cmds.parentConstraint(node, worldLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#add the constraint between worldLoc and node
|
|
if node == "spine_01_space_switcher_follow":
|
|
constraint = cmds.orientConstraint(worldLoc, node)[0]
|
|
|
|
else:
|
|
constraint = cmds.parentConstraint(worldLoc, node)[0]
|
|
|
|
#add the attr to the space switcher node for that space
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_world", minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
|
|
#connect that attr to the constraint
|
|
cmds.connectAttr(spaceSwitchNode + ".space_world", constraint + "." + worldLoc + "W0")
|
|
|
|
#parent worldLoc under the offset_anim
|
|
if worldLoc.find("master_anim") == 0:
|
|
cmds.parent(worldLoc, "rig_grp")
|
|
|
|
else:
|
|
cmds.parent(worldLoc, "offset_anim")
|
|
|
|
|
|
|
|
|
|
#SETUP SPECIAL CASES
|
|
for node in spaceSwitchers:
|
|
if node == "chest_ik_anim_space_switcher_follow":
|
|
|
|
#create a locator named world aligned
|
|
spaceLoc = cmds.spaceLocator(name = "chest_ik_world_aligned")[0]
|
|
cmds.setAttr(spaceLoc + ".v",0)
|
|
|
|
#constrain it to the chest ik anim
|
|
constraint = cmds.pointConstraint("chest_ik_anim", spaceLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#duplicate the locator
|
|
worldOrientLoc = cmds.duplicate(spaceLoc, name = "chest_ik_world_orient")[0]
|
|
|
|
#orient constrain the space loc to the world orient loc
|
|
cmds.orientConstraint(worldOrientLoc, spaceLoc, mo = True)
|
|
|
|
#parent the space loc under the hip anim
|
|
cmds.parent(spaceLoc, "body_anim")
|
|
|
|
#parent the worldOrientLoc under the master anim
|
|
cmds.parent(worldOrientLoc, "master_anim")
|
|
|
|
#add attr to the space switcher node
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_chest_ik_world_aligned", minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceLoc, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(len(targets)):
|
|
if targets[i].find(spaceLoc) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_chest_ik_world_aligned", constraint + "." + spaceLoc + "W" + str(weight))
|
|
|
|
|
|
|
|
if node == "ik_wrist_l_anim_space_switcher_follow":
|
|
|
|
spaceList = ["body_anim", "head_fk_anim"]
|
|
|
|
if cmds.objExists("chest_ik_anim"):
|
|
spaceList.append("chest_ik_anim")
|
|
for spaceObj in spaceList:
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
|
|
|
|
#add attr to the space switcher node
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_" + spaceObj, minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceObj, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(len(targets)):
|
|
if targets[i].find(spaceObj) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_" + spaceObj, constraint + "." + spaceObj + "W" + str(weight))
|
|
|
|
if node == "ik_wrist_r_anim_space_switcher_follow":
|
|
spaceList = ["body_anim", "head_fk_anim"]
|
|
if cmds.objExists("chest_ik_anim"):
|
|
spaceList.append("chest_ik_anim")
|
|
for spaceObj in spaceList:
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
|
|
|
|
#add attr to the space switcher node
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_" + spaceObj, minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceObj, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(len(targets)):
|
|
if targets[i].find(spaceObj) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_" + spaceObj, constraint + "." + spaceObj + "W" + str(weight))
|
|
|
|
if node == "ik_elbow_l_anim_space_switcher_follow":
|
|
spaceList = ["body_anim"]
|
|
if cmds.objExists("chest_ik_anim"):
|
|
spaceList.append("chest_ik_anim")
|
|
for spaceObj in spaceList:
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
|
|
|
|
#add attr to the space switcher node
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_" + spaceObj, minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceObj, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(len(targets)):
|
|
if targets[i].find(spaceObj) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_" + spaceObj, constraint + "." + spaceObj + "W" + str(weight))
|
|
|
|
if node == "ik_elbow_r_anim_space_switcher_follow":
|
|
spaceList = ["body_anim"]
|
|
if cmds.objExists("chest_ik_anim"):
|
|
spaceList.append("chest_ik_anim")
|
|
for spaceObj in spaceList:
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
|
|
|
|
#add attr to the space switcher node
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_" + spaceObj, minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceObj, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(int(len(targets))):
|
|
if targets[i].find(spaceObj) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_" + spaceObj, constraint + "." + spaceObj + "W" + str(weight))
|
|
|
|
if node == "ik_foot_anim_l_space_switcher_follow":
|
|
for spaceObj in ["body_anim"]:
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
|
|
|
|
#add attr to the space switcher node
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_" + spaceObj, minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceObj, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(int(len(targets))):
|
|
if targets[i].find(spaceObj) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_" + spaceObj, constraint + "." + spaceObj + "W" + str(weight))
|
|
|
|
if node == "ik_foot_anim_r_space_switcher_follow":
|
|
for spaceObj in ["body_anim"]:
|
|
spaceSwitchNode = node.rpartition("_follow")[0]
|
|
|
|
|
|
#add attr to the space switcher node
|
|
cmds.select(spaceSwitchNode)
|
|
cmds.addAttr(ln = "space_" + spaceObj, minValue = 0, maxValue = 1, dv = 0, keyable = True)
|
|
|
|
#add constraint to the new object on the follow node
|
|
constraint = cmds.parentConstraint(spaceObj, node, mo = True)[0]
|
|
|
|
#hook up connections
|
|
targets = cmds.parentConstraint(constraint, q = True, targetList = True)
|
|
weight = 0
|
|
for i in range(int(len(targets))):
|
|
if targets[i].find(spaceObj) != -1:
|
|
weight = i
|
|
|
|
cmds.connectAttr(spaceSwitchNode + ".space_" + spaceObj, constraint + "." + spaceObj + "W" + str(weight))
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildCoreComponents(self):
|
|
|
|
#builds the master, the root, the hips/body
|
|
|
|
#BODY CONTROL
|
|
self.buildHips()
|
|
|
|
#MASTER CONTROL
|
|
masterControl = self.createControl("circle", 150, "master_anim")
|
|
|
|
constraint = cmds.pointConstraint("root", masterControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.makeIdentity(masterControl, apply = True)
|
|
cmds.setAttr(masterControl + ".overrideEnabled", 1)
|
|
cmds.setAttr(masterControl + ".overrideColor", 18)
|
|
|
|
spaceSwitchFollow = cmds.group(empty = True, name = masterControl + "_space_switcher_follow")
|
|
constraint = cmds.parentConstraint("root", spaceSwitchFollow)[0]
|
|
cmds.delete(constraint)
|
|
|
|
spaceSwitcher = cmds.group(empty = True, name = masterControl + "_space_switcher")
|
|
constraint = cmds.parentConstraint("root", spaceSwitcher)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(spaceSwitcher, spaceSwitchFollow)
|
|
cmds.parent(masterControl, spaceSwitcher)
|
|
cmds.makeIdentity(masterControl, apply = True)
|
|
|
|
|
|
|
|
#OFFSET CONTROL
|
|
offsetControl = self.createControl("square", 140, "offset_anim")
|
|
constraint = cmds.pointConstraint("root", offsetControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(offsetControl, masterControl)
|
|
cmds.makeIdentity(offsetControl, apply = True)
|
|
cmds.setAttr(offsetControl + ".overrideEnabled", 1)
|
|
cmds.setAttr(offsetControl + ".overrideColor", 17)
|
|
|
|
#ROOT ANIM
|
|
rootControl = self.createControl("sphere", 10, "root_anim")
|
|
constraint = cmds.parentConstraint("driver_root", rootControl)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(rootControl, masterControl)
|
|
cmds.makeIdentity(rootControl, apply = True)
|
|
cmds.parentConstraint(rootControl, "driver_root")
|
|
cmds.setAttr(rootControl + ".overrideEnabled", 1)
|
|
cmds.setAttr(rootControl + ".overrideColor", 30)
|
|
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(masterControl + attr, lock = True, keyable = False)
|
|
cmds.setAttr(offsetControl + attr, lock = True, keyable = False)
|
|
cmds.setAttr(rootControl + attr, lock = True, keyable = False)
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildHips(self):
|
|
|
|
#create the grp and position and orient it correctly
|
|
bodyGrp = cmds.group(empty = True, name = "body_anim_grp")
|
|
bodyCtrl = self.createControl("square", 100, "body_anim")
|
|
constraint = cmds.parentConstraint("pelvis", bodyGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#world alignment
|
|
for attr in [".rx", ".ry", ".rz"]:
|
|
print cmds.getAttr(bodyGrp + attr)
|
|
|
|
if cmds.getAttr(bodyGrp + attr) < 45:
|
|
if cmds.getAttr(bodyGrp + attr) > 0:
|
|
cmds.setAttr(bodyGrp + attr, 0)
|
|
|
|
if cmds.getAttr(bodyGrp + attr) >= 80:
|
|
if cmds.getAttr(bodyGrp + attr) < 90:
|
|
cmds.setAttr(bodyGrp + attr, 90)
|
|
|
|
if cmds.getAttr(bodyGrp + attr) > 90:
|
|
if cmds.getAttr(bodyGrp + attr) < 100:
|
|
cmds.setAttr(bodyGrp + attr, 90)
|
|
|
|
if cmds.getAttr(bodyGrp + attr) <= -80:
|
|
if cmds.getAttr(bodyGrp + attr) > -90:
|
|
cmds.setAttr(bodyGrp + attr, -90)
|
|
|
|
|
|
if cmds.getAttr(bodyGrp + attr) > -90:
|
|
if cmds.getAttr(bodyGrp + attr) < -100:
|
|
cmds.setAttr(bodyGrp + attr, -90)
|
|
|
|
for attr in [".rx", ".ry", ".rz"]:
|
|
print cmds.getAttr(bodyGrp + attr)
|
|
|
|
#create space switcher
|
|
spaceSwitcherFollow = cmds.duplicate(bodyGrp, name = "body_anim_space_switcher_follow")[0]
|
|
spaceSwitcher = cmds.duplicate(bodyGrp, name = "body_anim_space_switcher")[0]
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(bodyGrp, spaceSwitcher)
|
|
|
|
|
|
#create temp duplicate and orient control to joint
|
|
tempDupe = cmds.duplicate(bodyCtrl)[0]
|
|
constraint = cmds.parentConstraint("pelvis", bodyCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#parent control to grp
|
|
cmds.parent(bodyCtrl, bodyGrp)
|
|
constraint = cmds.orientConstraint(tempDupe, bodyCtrl)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(bodyCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#clean up body control creation
|
|
cmds.delete(tempDupe)
|
|
|
|
#set control color
|
|
cmds.setAttr(bodyCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(bodyCtrl + ".overrideColor", 17)
|
|
|
|
#lock attrs
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(bodyCtrl + attr, lock = True, keyable = False)
|
|
|
|
#build pelvis
|
|
self.buildPelvisControl()
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildPelvisControl(self):
|
|
|
|
#create the grp and position and orient it correctly
|
|
hipGrp = cmds.group(empty = True, name = "hip_anim_grp")
|
|
hipCtrl = self.createControl("circle", 60, "hip_anim")
|
|
constraint = cmds.parentConstraint("pelvis", hipGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create temp duplicate and orient control to joint
|
|
tempDupe = cmds.duplicate(hipCtrl)[0]
|
|
constraint = cmds.parentConstraint("pelvis", hipCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#parent control to grp
|
|
cmds.parent(hipCtrl, hipGrp)
|
|
constraint = cmds.orientConstraint(tempDupe, hipCtrl)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(hipCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#parent the grp to the body anim
|
|
cmds.parent(hipGrp, "body_anim")
|
|
|
|
|
|
#clean up body control creation
|
|
cmds.delete(tempDupe)
|
|
|
|
#set control color
|
|
cmds.setAttr(hipCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(hipCtrl + ".overrideColor", 18)
|
|
|
|
#lock attrs
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(hipCtrl + attr, lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildFKSpine(self):
|
|
|
|
#find the number of spine bones from the skeleton settings
|
|
spineJoints = self.getSpineJoints()
|
|
fkControls = []
|
|
parent = None
|
|
|
|
for joint in spineJoints:
|
|
if joint == "spine_01":
|
|
#add space switcher node to base of spine
|
|
spaceSwitcherFollow = cmds.group(empty = True, name = joint + "_space_switcher_follow")
|
|
constraint = cmds.parentConstraint(joint, spaceSwitcherFollow)[0]
|
|
cmds.delete(constraint)
|
|
spaceSwitcher = cmds.duplicate(spaceSwitcherFollow, name = joint + "_space_switcher")[0]
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
|
|
#create an empty group in the same space as the joint
|
|
group = cmds.group(empty = True, name = joint + "_anim_grp")
|
|
constraint = cmds.parentConstraint(joint, group)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create an additional layer of group that has zeroed attrs
|
|
offsetGroup = cmds.group(empty = True, name = joint + "_anim_offset_grp")
|
|
constraint = cmds.parentConstraint(joint, offsetGroup)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(offsetGroup, group)
|
|
|
|
#create a control object in the same space as the joint
|
|
control = self.createControl("circle", 45, joint + "_anim")
|
|
tempDupe = cmds.duplicate(control)[0]
|
|
constraint = cmds.parentConstraint(joint, control)[0]
|
|
cmds.delete(constraint)
|
|
fkControls.append(control)
|
|
|
|
|
|
#parent the control object to the group
|
|
cmds.parent(control, offsetGroup)
|
|
constraint = cmds.orientConstraint(tempDupe, control, skip = ["x", "z"])[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#setup hierarchy
|
|
if parent != None:
|
|
cmds.parent(group, parent, absolute = True)
|
|
|
|
else:
|
|
cmds.parent(group, spaceSwitcher)
|
|
cmds.parent(spaceSwitcherFollow, "body_anim")
|
|
|
|
|
|
#set the parent to be the current spine control
|
|
parent = control
|
|
|
|
#clean up
|
|
cmds.delete(tempDupe)
|
|
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
#set the control's color
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
#create length attr on spine controls. need to find up axis for control first
|
|
upAxis = self.getUpAxis(control)
|
|
cmds.aliasAttr("length", control + ".translate" + upAxis)
|
|
|
|
|
|
|
|
|
|
return fkControls
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildIKSpine(self, fkControls):
|
|
|
|
|
|
numSpineBones = cmds.getAttr("Skeleton_Settings.numSpineBones")
|
|
|
|
if numSpineBones > 2:
|
|
#duplicate the spine joints we'll need for the spline IK
|
|
spineJoints = self.getSpineJoints()
|
|
print "SPINE JOINTS:"
|
|
print spineJoints
|
|
|
|
parent = None
|
|
rigJoints = []
|
|
|
|
for joint in spineJoints:
|
|
spineBone = cmds.duplicate(joint, parentOnly = True, name = "splineIK_" + joint)[0]
|
|
|
|
if parent != None:
|
|
cmds.parent(spineBone, parent)
|
|
|
|
else:
|
|
cmds.parent(spineBone, world = True)
|
|
|
|
parent = spineBone
|
|
rigJoints.append(str(spineBone))
|
|
|
|
|
|
for joint in rigJoints:
|
|
twistJoint = cmds.duplicate(joint, name = "twist_" + joint, parentOnly = True)[0]
|
|
cmds.parent(twistJoint, joint)
|
|
|
|
# find the driver top and mid joints
|
|
topDriverJoint = "driver_"+spineJoints[len(spineJoints) - 1]
|
|
print topDriverJoint
|
|
midDriverJoint = "driver_"+spineJoints[len(spineJoints) / 2]
|
|
print midDriverJoint
|
|
|
|
|
|
#create the spline IK
|
|
ikNodes = cmds.ikHandle(sj = str(rigJoints[0]), ee = str(rigJoints[len(rigJoints) - 1]), sol = "ikSplineSolver", createCurve = True, simplifyCurve = True, parentCurve = False, name = str(rigJoints[0]) + "_splineIK")
|
|
ikHandle = ikNodes[0]
|
|
ikCurve = ikNodes[2]
|
|
ikCurve = cmds.rename(ikCurve, "spine_splineIK_curve")
|
|
cmds.setAttr(ikCurve + ".inheritsTransform", 0)
|
|
cmds.setAttr(ikHandle + ".v", 0)
|
|
cmds.setAttr(ikCurve + ".v", 0)
|
|
|
|
#create the three joints to skin the curve to
|
|
botJoint = cmds.duplicate(rigJoints[0], name = "spine_splineIK_bottom_joint", parentOnly = True)[0]
|
|
topJoint = cmds.duplicate(rigJoints[len(rigJoints) - 1], name = "spine_splineIK_top_joint", parentOnly = True)[0]
|
|
midJoint = cmds.duplicate(topJoint, name = "spine_splineIK_mid_joint", parentOnly = True)[0]
|
|
|
|
cmds.parent([botJoint, topJoint,midJoint], world = True)
|
|
|
|
constraint = cmds.pointConstraint([botJoint, topJoint], midJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#skin the joints to the curve
|
|
cmds.select([botJoint, topJoint, midJoint])
|
|
skin = cmds.skinCluster( [botJoint, topJoint, midJoint], ikCurve, toSelectedBones = True )[0]
|
|
|
|
#skin weight the curve
|
|
curveShape = cmds.listRelatives(ikCurve, shapes = True)[0]
|
|
numSpans = cmds.getAttr(curveShape + ".spans")
|
|
degree = cmds.getAttr(curveShape + ".degree")
|
|
numCVs = numSpans + degree
|
|
|
|
#this should always be the case, but just to be safe
|
|
if numCVs == 4:
|
|
cmds.skinPercent(skin, ikCurve + ".cv[0]", transformValue = [(botJoint, 1.0)])
|
|
cmds.skinPercent(skin, ikCurve + ".cv[1]", transformValue = [(botJoint, 0.5), (midJoint, 0.5)])
|
|
cmds.skinPercent(skin, ikCurve + ".cv[2]", transformValue = [(midJoint, 0.5), (topJoint, 0.5)])
|
|
cmds.skinPercent(skin, ikCurve + ".cv[3]", transformValue = [(topJoint, 1.0)])
|
|
|
|
#create the controls
|
|
|
|
#TOP CTRL
|
|
topCtrl = self.createControl("circle", 50, "chest_ik_anim")
|
|
|
|
#set the control's color
|
|
cmds.setAttr(topCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(topCtrl + ".overrideColor", 17)
|
|
|
|
#position the control
|
|
constraint = cmds.pointConstraint(topJoint, topCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create the control grp
|
|
topCtrlGrp = cmds.group(empty = True, name = topCtrl + "_grp")
|
|
constraint = cmds.parentConstraint(topJoint, topCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#create the top control driver group
|
|
topCtrlDriver = cmds.duplicate(topCtrlGrp, name = "chest_ik_anim_driver_grp")
|
|
|
|
#create the space switcher group
|
|
spaceSwitcherFollow = cmds.group(empty = True, name = topCtrl + "_space_switcher_follow")
|
|
constraint = cmds.parentConstraint(topCtrlGrp, spaceSwitcherFollow)[0]
|
|
cmds.delete(constraint)
|
|
spaceSwitcher = cmds.duplicate(spaceSwitcherFollow, parentOnly = True, name = topCtrl + "_space_switcher")[0]
|
|
|
|
|
|
#parent objects
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(topCtrlGrp, spaceSwitcher)
|
|
cmds.parent(topCtrlDriver, topCtrlGrp)
|
|
cmds.parent(topCtrl, topCtrlDriver)
|
|
cmds.makeIdentity(topCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(topJoint, topCtrl)
|
|
|
|
|
|
|
|
|
|
#MID CTRL
|
|
midCtrl = self.createControl("circle", 45, "mid_ik_anim")
|
|
|
|
#set the control's color
|
|
cmds.setAttr(midCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(midCtrl + ".overrideColor", 18)
|
|
|
|
#position the control
|
|
constraint = cmds.pointConstraint(midJoint, midCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create the control grp
|
|
midCtrlGrp = cmds.group(empty = True, name = midCtrl + "_grp")
|
|
constraint = cmds.parentConstraint(midJoint, midCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#mid control driver grp
|
|
midCtrlDriver = cmds.duplicate(midCtrlGrp, name = "mid_ik_anim_driver_grp")
|
|
midCtrlTranslateDriver = cmds.duplicate(midCtrlGrp, name = "mid_ik_anim_translate_driver_grp")
|
|
|
|
#parent objects
|
|
cmds.parent(midCtrl, midCtrlDriver)
|
|
cmds.parent(midCtrlDriver, midCtrlTranslateDriver)
|
|
cmds.parent(midCtrlTranslateDriver, midCtrlGrp)
|
|
cmds.makeIdentity(midCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(midJoint, midCtrl)
|
|
cmds.parent(botJoint, "hip_anim")
|
|
|
|
|
|
|
|
|
|
#ADDING STRETCH
|
|
|
|
#add the attr to the top ctrl
|
|
cmds.select(topCtrl)
|
|
cmds.addAttr(longName='stretch', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
cmds.addAttr(longName='squash', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
|
|
#create the curveInfo node#find
|
|
cmds.select(ikCurve)
|
|
curveInfoNode = cmds.arclen(cmds.ls(sl = True), ch = True )
|
|
originalLength = cmds.getAttr(curveInfoNode + ".arcLength")
|
|
|
|
#create the multiply/divide node that will get the scale factor
|
|
divideNode = cmds.shadingNode("multiplyDivide", asUtility = True)
|
|
divideNode_Inverse = cmds.shadingNode("multiplyDivide", asUtility = True)
|
|
cmds.setAttr(divideNode + ".operation", 2)
|
|
cmds.setAttr(divideNode + ".input2X", originalLength)
|
|
cmds.setAttr(divideNode_Inverse + ".operation", 2)
|
|
cmds.setAttr(divideNode_Inverse + ".input1X", originalLength)
|
|
|
|
#create the blendcolors node
|
|
blenderNode = cmds.shadingNode("blendColors", asUtility = True)
|
|
cmds.setAttr(blenderNode + ".color2R", 1)
|
|
|
|
blenderNode_Inverse = cmds.shadingNode("blendColors", asUtility = True)
|
|
cmds.setAttr(blenderNode_Inverse + ".color2R", 1)
|
|
|
|
#connect attrs
|
|
cmds.connectAttr(curveInfoNode + ".arcLength", divideNode + ".input1X")
|
|
cmds.connectAttr(curveInfoNode + ".arcLength", divideNode_Inverse + ".input2X")
|
|
cmds.connectAttr(divideNode + ".outputX", blenderNode + ".color1R")
|
|
cmds.connectAttr(divideNode_Inverse + ".outputX", blenderNode_Inverse + ".color1R")
|
|
|
|
cmds.connectAttr(topCtrl + ".stretch", blenderNode + ".blender")
|
|
cmds.connectAttr(topCtrl + ".squash", blenderNode_Inverse + ".blender")
|
|
upAxis = self.getUpAxis(topCtrl)
|
|
if upAxis == "X":
|
|
axisB = "Y"
|
|
axisC = "Z"
|
|
if upAxis == "Y":
|
|
axisB = "X"
|
|
axisC = "Z"
|
|
if upAxis == "Z":
|
|
axisB = "X"
|
|
axisC = "Y"
|
|
|
|
for i in range(len(rigJoints) - 2):
|
|
children = cmds.listRelatives(rigJoints[i], children = True)
|
|
for child in children:
|
|
if child.find("twist") != -1:
|
|
twistJoint = child
|
|
|
|
cmds.connectAttr(blenderNode_Inverse + ".outputR", twistJoint + ".scale" + axisB)
|
|
cmds.connectAttr(blenderNode_Inverse + ".outputR", twistJoint + ".scale" + axisC)
|
|
|
|
cmds.connectAttr(blenderNode + ".outputR", rigJoints[0] + ".scale" + upAxis)
|
|
|
|
#add twist amount attrs and setup
|
|
cmds.select(topCtrl)
|
|
cmds.addAttr(longName='twist_amount', defaultValue=1, minValue=0, keyable = True)
|
|
|
|
#find number of spine joints and divide 1 by numSpineJoints
|
|
num = len(spineJoints)
|
|
val = 1.0/float(num)
|
|
twistamount = val
|
|
|
|
locGrp = cmds.group(empty = True, name = "spineIK_twist_grp")
|
|
cmds.parent(locGrp, "body_anim")
|
|
|
|
for i in range(int(num - 1)):
|
|
|
|
#create a locator that will be orient constrained between the body and chest
|
|
locator = cmds.spaceLocator(name = spineJoints[i] + "_twistLoc")[0]
|
|
group = cmds.group(empty = True, name = spineJoints[i] + "_twistLocGrp")
|
|
constraint = cmds.parentConstraint(spineJoints[i], locator)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(spineJoints[i], group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(locator, group)
|
|
cmds.parent(group, locGrp)
|
|
cmds.setAttr(locator + ".v", 0, lock = True)
|
|
|
|
|
|
#duplicate the locator and parent it under the group. This will be the locator that takes the rotation x twist amount and gives us the final value
|
|
orientLoc = cmds.duplicate(locator, name = spineJoints[i] + "_orientLoc")[0]
|
|
|
|
#create constraints between body/chest
|
|
constraint = cmds.orientConstraint(["body_anim", topCtrl], locator)[0]
|
|
|
|
#set weights on constraint
|
|
firstValue = 1 - twistamount
|
|
secondValue = 1 - firstValue
|
|
|
|
cmds.setAttr(constraint + ".body_animW0", firstValue)
|
|
cmds.setAttr(constraint + "." + topCtrl + "W1", secondValue)
|
|
|
|
#factor in twist amount
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = spineJoints[i] + "_twist_amount")
|
|
|
|
#expose the twistAmount on the control as an attr
|
|
cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2X")
|
|
cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2Y")
|
|
cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2Z")
|
|
cmds.connectAttr(locator + ".rotate", twistMultNode + ".input1")
|
|
|
|
cmds.connectAttr(twistMultNode + ".output", orientLoc + ".rotate")
|
|
|
|
#constrain the spine joint to the orientLoc
|
|
if upAxis == "X":
|
|
skipped = ["y", "z"]
|
|
if upAxis == "Y":
|
|
skipped = ["x", "z"]
|
|
if upAxis == "Z":
|
|
skipped = ["x", "y"]
|
|
|
|
|
|
cmds.orientConstraint(orientLoc, "twist_splineIK_" + spineJoints[i], skip = skipped)
|
|
|
|
twistamount = twistamount + val
|
|
|
|
|
|
|
|
#parent the components to the body anim
|
|
cmds.parent(midCtrlGrp, "body_anim")
|
|
cmds.parent(midCtrl, world = True)
|
|
cmds.parent(midJoint, world = True)
|
|
|
|
for attr in [".rx", ".ry", ".rz"]:
|
|
cmds.setAttr(midCtrlGrp + attr, 0)
|
|
|
|
cmds.parent(midCtrl, midCtrlDriver)
|
|
cmds.makeIdentity(midCtrl, t = 1, r = 1, s = 0, apply = True)
|
|
cmds.parent(midJoint, midCtrl)
|
|
|
|
|
|
cmds.parent(spaceSwitcherFollow, "body_anim")
|
|
cmds.parent(rigJoints[0], "body_anim")
|
|
|
|
#world alignment
|
|
cmds.parent(topCtrl, world = True)
|
|
cmds.parent(topJoint, world = True)
|
|
for attr in [".rx", ".ry", ".rz"]:
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) < 45:
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) > 0:
|
|
cmds.setAttr(spaceSwitcherFollow + attr, 0)
|
|
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) >= 80:
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) < 90:
|
|
cmds.setAttr(spaceSwitcherFollow + attr, 90)
|
|
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) > 90:
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) < 100:
|
|
cmds.setAttr(spaceSwitcherFollow + attr, 90)
|
|
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) <= -80:
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) > -90:
|
|
cmds.setAttr(spaceSwitcherFollow + attr, -90)
|
|
|
|
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) > -90:
|
|
if cmds.getAttr(spaceSwitcherFollow + attr) < -100:
|
|
cmds.setAttr(spaceSwitcherFollow + attr, -90)
|
|
|
|
cmds.parent(topCtrl, topCtrlDriver)
|
|
cmds.makeIdentity(topCtrl, t = 1, r = 1, s = 0, apply = True)
|
|
cmds.parent(topJoint, topCtrl)
|
|
|
|
|
|
#hookup spine driver joints
|
|
driverJoints = []
|
|
for joint in rigJoints:
|
|
driverJoint = joint.partition("splineIK_")[2]
|
|
driverJoint = "driver_" + driverJoint
|
|
driverJoints.append(driverJoint)
|
|
|
|
|
|
#hookup spine to driver
|
|
self.hookupSpine(rigJoints, fkControls)
|
|
|
|
#control driver joints
|
|
children = cmds.listRelatives(rigJoints[len(rigJoints) -1], children = True)
|
|
for child in children:
|
|
if child.find("twist") != -1:
|
|
twistJoint = child
|
|
|
|
topSpineJointConstraint = cmds.pointConstraint(topJoint, twistJoint, mo = True)[0]
|
|
topSpineBone = twistJoint.partition("twist_")[2]
|
|
cmds.pointConstraint(topSpineBone, twistJoint)[0]
|
|
|
|
|
|
#connect attr on top spine joint constraint
|
|
target = cmds.pointConstraint(topSpineJointConstraint, q = True, weightAliasList = True)[0]
|
|
cmds.connectAttr(topCtrl + ".stretch", topSpineJointConstraint + "." + target)
|
|
|
|
|
|
#create stretch meter attr
|
|
cmds.select(topCtrl)
|
|
cmds.addAttr(longName='stretchFactor',keyable = True)
|
|
cmds.connectAttr(divideNode + ".outputX", topCtrl + ".stretchFactor")
|
|
cmds.setAttr(topCtrl + ".stretchFactor", lock = True)
|
|
|
|
|
|
cmds.select(midCtrl)
|
|
cmds.addAttr(longName='stretchFactor',keyable = True)
|
|
cmds.connectAttr(topCtrl + ".stretchFactor", midCtrl + ".stretchFactor")
|
|
cmds.setAttr(midCtrl + ".stretchFactor", lock = True)
|
|
|
|
|
|
#lock and hide attrs that should not be keyable
|
|
for control in [topCtrl, midCtrl]:
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, keyable = False, lock = True)
|
|
|
|
# Create a couple nodes that can be used to make IK/FK matching work better.
|
|
chest_match_node = cmds.duplicate(topCtrl, po=True, name=topCtrl+"_MATCH")
|
|
cmds.parent(chest_match_node, topDriverJoint)
|
|
|
|
mid_match_node = cmds.duplicate(midCtrl, po=True, name=midCtrl+"_MATCH")
|
|
cmds.parent(mid_match_node, midDriverJoint)
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildFKLegs(self):
|
|
|
|
#need to create the leg joints for each side based on the driver thigh, calf, and foot
|
|
|
|
for side in ["l", "r"]:
|
|
|
|
ball = False
|
|
|
|
#create joints
|
|
fkThighJoint = cmds.duplicate("driver_thigh_" + side, name = "fk_leg_thigh_" + side, parentOnly = True)[0]
|
|
fkCalfJoint = cmds.duplicate("driver_calf_" + side, name = "fk_leg_calf_" + side, parentOnly = True)[0]
|
|
fkFootJoint = cmds.duplicate("driver_foot_" + side, name = "fk_leg_foot_" + side, parentOnly = True)[0]
|
|
|
|
if cmds.objExists("driver_ball_" + side):
|
|
ball = True
|
|
fkBallJoint = cmds.duplicate("driver_ball_" + side, name = "fk_leg_ball_" + side, parentOnly = True)[0]
|
|
|
|
for joint in [fkThighJoint, fkCalfJoint, fkFootJoint]:
|
|
cmds.parent(joint, world = True)
|
|
|
|
if ball:
|
|
cmds.parent(fkBallJoint, fkFootJoint)
|
|
|
|
|
|
cmds.parent(fkFootJoint, fkCalfJoint)
|
|
cmds.parent(fkCalfJoint, fkThighJoint)
|
|
cmds.makeIdentity(fkThighJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
|
|
#create controls for each joint
|
|
|
|
|
|
#THIGH
|
|
fkThighCtrl = self.createControl("circle", 30, "fk_thigh_" + side + "_anim")
|
|
cmds.setAttr(fkThighCtrl + ".ry", -90)
|
|
cmds.makeIdentity(fkThighCtrl, r = 1, apply =True)
|
|
|
|
fkThighCtrlGrp = cmds.group(empty = True, name = "fk_thigh_" + side + "_anim_grp")
|
|
|
|
|
|
constraint = cmds.parentConstraint(fkThighJoint, fkThighCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(fkThighJoint, fkThighCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
fkThighOrientGrp = cmds.duplicate(fkThighCtrlGrp, parentOnly = True, name = "fk_thigh_" + side + "_orient_grp")
|
|
fkThighWorldNode = cmds.duplicate(fkThighOrientGrp, parentOnly = True, name = "fk_thigh_" + side + "_world")
|
|
cmds.orientConstraint(fkThighWorldNode, fkThighOrientGrp)
|
|
cmds.parent(fkThighWorldNode, "body_anim")
|
|
cmds.parent(fkThighCtrl, fkThighCtrlGrp)
|
|
cmds.parent(fkThighCtrlGrp, fkThighOrientGrp)
|
|
|
|
|
|
|
|
|
|
#get the distance between the hip and knee
|
|
thighPos = cmds.xform("driver_thigh_" + side, q = True, ws = True, t = True)
|
|
kneePos = cmds.xform("driver_calf_" + side, q = True, ws = True, t = True)
|
|
dist = (thighPos[2] - kneePos[2]) / 2
|
|
|
|
|
|
#move the ctrl to the position of dist
|
|
upAxis = self.getUpAxis(fkThighCtrl)
|
|
|
|
if side == "l":
|
|
cmds.setAttr(fkThighCtrl + ".translate" + upAxis, dist * -1)
|
|
|
|
else:
|
|
cmds.setAttr(fkThighCtrl + ".translate" + upAxis, dist)
|
|
|
|
#get the pivot of the thigh and set the pivot of the ctrl to that position
|
|
piv = cmds.xform(fkThighJoint, q = True, ws = True, rotatePivot = True)
|
|
cmds.xform(fkThighCtrl, ws = True, piv = (piv[0], piv[1], piv[2]))
|
|
|
|
|
|
#lock attrs that should not be animated
|
|
cmds.setAttr(fkThighCtrl + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(fkThighCtrl + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(fkThighCtrl + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(fkThighCtrl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(fkThighCtrl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(fkThighCtrl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(fkThighCtrl + ".v", lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#CALF
|
|
fkCalfCtrl = self.createControl("semiCircle", 5, "fk_calf_" + side + "_anim")
|
|
cmds.makeIdentity(fkCalfCtrl, s = 1, apply = True)
|
|
cmds.setAttr(fkCalfCtrl + ".sx", .5)
|
|
cmds.setAttr(fkCalfCtrl + ".sy", .75)
|
|
cmds.setAttr(fkCalfCtrl + ".rx", 180)
|
|
cmds.setAttr(fkCalfCtrl + ".ry", -90)
|
|
cmds.makeIdentity(fkCalfCtrl, s = 1, apply = True)
|
|
|
|
fkCalfCtrlGrp = cmds.group(empty = True, name = "fk_calf_" + side + "_anim_grp")
|
|
|
|
constraint = cmds.parentConstraint(fkCalfJoint, fkCalfCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.pointConstraint(fkCalfJoint, fkCalfCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(fkCalfCtrl, fkCalfCtrlGrp)
|
|
|
|
|
|
|
|
#get the pivot of the calf and set the pivot of the ctrl to that position
|
|
piv = cmds.xform(fkCalfJoint, q = True, ws = True, rotatePivot = True)
|
|
cmds.xform(fkCalfCtrl, ws = True, piv = (piv[0], piv[1], piv[2]))
|
|
|
|
#parent the fk ctrl grp to the thigh anim
|
|
cmds.parent(fkCalfCtrlGrp, fkThighCtrl)
|
|
|
|
cmds.makeIdentity(fkCalfCtrl, r = 1, apply = True)
|
|
|
|
#lock attrs that should not be animated
|
|
cmds.setAttr(fkCalfCtrl + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(fkCalfCtrl + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(fkCalfCtrl + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(fkCalfCtrl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(fkCalfCtrl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(fkCalfCtrl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(fkCalfCtrl + ".v", lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
#FOOT
|
|
fkFootCtrl = self.createControl("circle", 17, "fk_foot_" + side + "_anim")
|
|
cmds.setAttr(fkFootCtrl + ".ry", -90)
|
|
cmds.makeIdentity(fkFootCtrl, r = 1, apply =True)
|
|
|
|
fkFootCtrlGrp = cmds.group(empty = True, name = "fk_foot_" + side + "_anim_grp")
|
|
|
|
constraint = cmds.parentConstraint(fkFootJoint, fkFootCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(fkFootJoint, fkFootCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(fkFootCtrl, fkFootCtrlGrp)
|
|
|
|
|
|
#get the pivot of the thigh and set the pivot of the ctrl to that position
|
|
piv = cmds.xform(fkFootJoint, q = True, ws = True, rotatePivot = True)
|
|
cmds.xform(fkFootCtrl, ws = True, piv = (piv[0], piv[1], piv[2]))
|
|
|
|
|
|
#parent the fk ctrl grp to the thigh anim
|
|
cmds.parent(fkFootCtrlGrp, fkCalfCtrl)
|
|
|
|
#lock attrs that should not be animated
|
|
cmds.setAttr(fkFootCtrl + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(fkFootCtrl + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(fkFootCtrl + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(fkFootCtrl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(fkFootCtrl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(fkFootCtrl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(fkFootCtrl + ".v", lock = True, keyable = False)
|
|
|
|
|
|
if ball:
|
|
#BALL
|
|
fkBallCtrl = self.createControl("arrowOnBall", 2, "fk_ball_" + side + "_anim")
|
|
|
|
if side == "l":
|
|
cmds.setAttr(fkBallCtrl + ".rx", -90)
|
|
cmds.makeIdentity(fkBallCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
else:
|
|
cmds.setAttr(fkBallCtrl + ".rx", 90)
|
|
cmds.makeIdentity(fkBallCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
fkBallCtrlGrp = cmds.group(empty = True, name = "fk_ball_" + side + "_anim_grp")
|
|
|
|
constraint = cmds.parentConstraint(fkBallJoint, fkBallCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(fkBallJoint, fkBallCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(fkBallCtrl, fkBallCtrlGrp)
|
|
|
|
|
|
#get the pivot of the thigh and set the pivot of the ctrl to that position
|
|
piv = cmds.xform(fkBallJoint, q = True, ws = True, rotatePivot = True)
|
|
cmds.xform(fkBallCtrl, ws = True, piv = (piv[0], piv[1], piv[2]))
|
|
|
|
|
|
#parent the fk ctrl grp to the thigh anim
|
|
cmds.parent(fkBallCtrlGrp, fkFootCtrl)
|
|
|
|
|
|
#lock attrs that should not be animated
|
|
cmds.setAttr(fkBallCtrl + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(fkBallCtrl + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(fkBallCtrl + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(fkBallCtrl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(fkBallCtrl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(fkBallCtrl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(fkBallCtrl + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#hook up leg joints to follow ctrls
|
|
cmds.orientConstraint(fkThighCtrl, fkThighJoint)
|
|
cmds.orientConstraint(fkCalfCtrl, fkCalfJoint)
|
|
cmds.orientConstraint(fkFootCtrl, fkFootJoint)
|
|
|
|
if ball:
|
|
cmds.orientConstraint(fkBallCtrl, fkBallJoint)
|
|
|
|
|
|
|
|
#color the controls
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
cmds.setAttr(fkThighCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(fkThighCtrl + ".overrideColor", color)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildIKLegs(self):
|
|
|
|
#need to create the leg joints for each side based on the driver thigh, calf, and foot
|
|
|
|
for side in ["l", "r"]:
|
|
|
|
#create joints
|
|
ikThighJoint = cmds.duplicate("driver_thigh_" + side, name = "ik_leg_thigh_" + side, parentOnly = True)[0]
|
|
ikCalfJoint = cmds.duplicate("driver_calf_" + side, name = "ik_leg_calf_" + side, parentOnly = True)[0]
|
|
ikFootJoint = cmds.duplicate("driver_foot_" + side, name = "ik_leg_foot_" + side, parentOnly = True)[0]
|
|
cmds.setAttr(ikThighJoint + ".v", 0)
|
|
|
|
for joint in [ikThighJoint, ikCalfJoint, ikFootJoint]:
|
|
cmds.parent(joint, world = True)
|
|
|
|
cmds.parent(ikFootJoint, ikCalfJoint)
|
|
cmds.parent(ikCalfJoint, ikThighJoint)
|
|
cmds.makeIdentity(ikThighJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#create the 2 joint chain for the no flip setup
|
|
cmds.select(clear = True)
|
|
beginJoint = cmds.joint(name = "noflip_begin_joint_" + side)
|
|
cmds.select(clear = True)
|
|
endJoint = cmds.joint(name = "noflip_end_joint_" + side)
|
|
cmds.select(clear = True)
|
|
cmds.setAttr(beginJoint + ".v", 0)
|
|
|
|
beginPos = cmds.xform(ikThighJoint, q = True, ws = True, t = True)
|
|
cmds.xform(beginJoint, ws = True, t = (beginPos[0], 0, beginPos[2]))
|
|
endPos = cmds.xform(ikFootJoint, q = True, ws = True, t = True)
|
|
cmds.xform(endJoint, ws = True, relative = True, t = (endPos[0], 0, endPos[2]))
|
|
cmds.parent(endJoint, beginJoint)
|
|
cmds.makeIdentity(beginJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#set preferred angle
|
|
cmds.setAttr(beginJoint + ".preferredAngleX", -90)
|
|
|
|
|
|
#apply a RP IK solver to the 2 bone chain
|
|
ikNodes = cmds.ikHandle(name = "noflip_chain_ikHandle_" + side, solver = "ikRPsolver", sj = beginJoint, ee = endJoint)
|
|
for node in ikNodes:
|
|
cmds.setAttr(node + ".v", 0)
|
|
|
|
#create a locator(target loc) and group it
|
|
targetLoc = cmds.spaceLocator(name = "noflip_target_loc_" + side)[0]
|
|
targetGrp = cmds.group(empty = True, name = "noflip_target_loc_grp_" + side)
|
|
cmds.setAttr(targetLoc + ".v", 0)
|
|
|
|
constraint = cmds.pointConstraint(beginJoint, targetGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(targetLoc, targetGrp)
|
|
constraint = cmds.pointConstraint(endJoint, targetLoc)
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(ikNodes[0], targetLoc)
|
|
|
|
#create the foot control
|
|
footCtrl = self.createControl("foot", 1, ("ik_foot_anim_" + side))
|
|
footCtrlGrp = cmds.group(empty = True, name = "ik_foot_anim_grp_" + side)
|
|
constraint = cmds.pointConstraint(ikFootJoint, footCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
|
|
#position the foot control
|
|
footCtrlPos = cmds.xform("ball_mover_" + side + "_grp", q = True, ws = True, t = True)
|
|
cmds.xform(footCtrl, ws = True, t = (footCtrlPos[0], 0, 0))
|
|
constraint = cmds.pointConstraint("ball_mover_" + side + "_grp", footCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.makeIdentity(footCtrl, t=1, r=1, s=1, apply = True)
|
|
|
|
if side == "r":
|
|
cmds.setAttr(footCtrl + ".sx", -1)
|
|
cmds.makeIdentity(footCtrl, t=1, r=1, s=1, apply = True)
|
|
|
|
cmds.xform(footCtrl, ws = True, piv = [endPos[0], endPos[1], endPos[2]])
|
|
|
|
footCtrlSpaceSwitcherFollow = cmds.duplicate(footCtrlGrp, po = True, name = "ik_foot_anim_" + side + "_space_switcher_follow")[0]
|
|
footCtrlSpaceSwitcher = cmds.duplicate(footCtrlGrp, po = True, name = "ik_foot_anim_" + side + "_space_switcher")[0]
|
|
|
|
cmds.parent(footCtrlSpaceSwitcher, footCtrlSpaceSwitcherFollow)
|
|
cmds.parent(footCtrlGrp, footCtrlSpaceSwitcher)
|
|
cmds.parent(footCtrl, footCtrlGrp)
|
|
cmds.makeIdentity(footCtrl, t=1, r=1, s=1, apply = True)
|
|
|
|
|
|
#create the noflip pole vector loc
|
|
scale = self.getScaleFactor()
|
|
noflipVectorLoc = cmds.spaceLocator(name = "noflip_pv_loc_" + side)[0]
|
|
noflipVectorGrp = cmds.group(name = "noflip_pv_loc_grp_" + side, empty = True)
|
|
|
|
constraint = cmds.pointConstraint([beginJoint, endJoint], noflipVectorLoc)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.pointConstraint(targetLoc, noflipVectorGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.setAttr(noflipVectorLoc + ".v", 0)
|
|
|
|
|
|
|
|
|
|
noflipVectorLocPos = cmds.xform(footCtrl + "_end_loc", q = True, ws = True, t = True)
|
|
if side == "l":
|
|
cmds.setAttr(noflipVectorLoc + ".ty", noflipVectorLocPos[1])
|
|
else:
|
|
cmds.setAttr(noflipVectorLoc + ".ty", noflipVectorLocPos[1] * -1)
|
|
|
|
cmds.makeIdentity(noflipVectorLoc, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.parent(noflipVectorLoc, noflipVectorGrp)
|
|
if side == "l":
|
|
cmds.setAttr(noflipVectorLoc + ".ty", (200 * scale))
|
|
else:
|
|
cmds.setAttr(noflipVectorLoc + ".ty", (-200 * scale))
|
|
|
|
cmds.makeIdentity(noflipVectorLoc, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parentConstraint(endJoint, noflipVectorGrp)
|
|
|
|
|
|
#duplicate the targetGrp to create our aim vector locator
|
|
aimGrp = cmds.duplicate(targetGrp, name = "noflip_aim_grp_" + side, parentOnly = True)[0]
|
|
aimSoftGrp = cmds.duplicate(targetGrp, name = "noflip_aim_soft_grp_" + side, parentOnly = True)[0]
|
|
aimLoc = cmds.duplicate(targetLoc, name = "noflip_aim_loc_" + side, parentOnly = True)[0]
|
|
cmds.parent(aimSoftGrp, aimGrp)
|
|
cmds.parent(aimLoc, aimSoftGrp)
|
|
cmds.setAttr(aimGrp + ".v", 0)
|
|
|
|
if side == "r":
|
|
cmds.setAttr(aimGrp + ".ry", 90)
|
|
|
|
else:
|
|
cmds.setAttr(aimGrp + ".ry", -90)
|
|
|
|
|
|
#connectAttrs of targetLoc and aimLoc
|
|
cmds.connectAttr(targetLoc + ".tx", aimLoc + ".tx")
|
|
cmds.connectAttr(targetLoc + ".tz", aimLoc + ".tz")
|
|
|
|
|
|
#pole vector constraint between aimLoc and ikNodes[0] (2bone chain ik handle)
|
|
cmds.poleVectorConstraint(aimLoc, ikNodes[0])
|
|
|
|
if side == "l":
|
|
cmds.setAttr(ikNodes[0] + ".twist", 180)
|
|
|
|
twistAmt = cmds.getAttr(beginJoint + ".rz")
|
|
cmds.setAttr(ikNodes[0] + ".twist", twistAmt * -1)
|
|
|
|
|
|
#create RP IK on the actual IK leg chain
|
|
#set preferred angle first
|
|
cmds.setAttr(ikThighJoint + ".preferredAngleZ", 90)
|
|
cmds.setAttr(ikCalfJoint + ".preferredAngleZ", 90)
|
|
|
|
ikNodesLeg = cmds.ikHandle(name = "foot_ikHandle_" + side, solver = "ikRPsolver", sj = ikThighJoint, ee = ikFootJoint)
|
|
footIK = ikNodesLeg[0]
|
|
cmds.setAttr(footIK + ".v", 0)
|
|
|
|
cmds.parent(footIK, targetLoc)
|
|
|
|
|
|
#create pole vector constraint between knee loc and full ik leg rp ik handle
|
|
cmds.poleVectorConstraint(noflipVectorLoc, footIK)
|
|
|
|
#set limits on the aimLoc in Z space
|
|
minTz = cmds.getAttr(aimLoc + ".tz")
|
|
maxTz = cmds.xform(aimGrp, q = True, ws = True, t = True)[0]
|
|
|
|
if side == "l":
|
|
maxTz = maxTz * -1
|
|
|
|
cmds.transformLimits(aimLoc, etz = (True, True), tz = (minTz, maxTz))
|
|
|
|
|
|
#create the twist control
|
|
kneeCtrl = self.createControl("arrow", 2, ("ik_knee_anim_" + side))
|
|
constraint = cmds.pointConstraint(ikCalfJoint, kneeCtrl)[0]
|
|
cmds.delete(constraint)
|
|
kneeCtrlGrp = cmds.group(name = "ik_knee_anim_grp_" + side, empty = True)
|
|
constraint = cmds.parentConstraint(ikCalfJoint, kneeCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(kneeCtrl, kneeCtrlGrp)
|
|
cmds.makeIdentity(kneeCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
upAxis = self.getUpAxis(kneeCtrl)
|
|
|
|
cmds.pointConstraint(ikCalfJoint, kneeCtrlGrp, mo = True)
|
|
cmds.setAttr(kneeCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(kneeCtrl + ".overrideDisplayType", 2)
|
|
|
|
|
|
|
|
|
|
|
|
#Create foot rig
|
|
|
|
#create joints for ball and toe in IK leg skeleton
|
|
cmds.select(clear = True)
|
|
ikBallJoint = cmds.joint(name = "ik_leg_ball_" + side)
|
|
cmds.select(clear = True)
|
|
|
|
ikToeJoint = cmds.joint(name = "ik_leg_toe_" + side)
|
|
cmds.select(clear = True)
|
|
|
|
#position joints
|
|
constraint = cmds.parentConstraint("ball_" + side + "_lra", ikBallJoint)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.pointConstraint("jointmover_toe_" + side + "_end", ikToeJoint)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.orientConstraint(ikBallJoint, ikToeJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#parent joints into IK leg hierarchy
|
|
cmds.parent(ikToeJoint, ikBallJoint)
|
|
cmds.parent(ikBallJoint, ikFootJoint)
|
|
|
|
cmds.makeIdentity(ikBallJoint, r = 1, apply = True)
|
|
|
|
#create SC IK for ankle to ball and ball to toe
|
|
ballIKNodes = cmds.ikHandle(name = "ikHandle_ball_" + side, solver = "ikSCsolver", sj = ikFootJoint, ee = ikBallJoint)
|
|
toeIKNodes = cmds.ikHandle(name = "ikHandle_toe_" + side, solver = "ikSCsolver", sj = ikBallJoint, ee = ikToeJoint)
|
|
|
|
cmds.setAttr(ballIKNodes[0] + ".v", 0)
|
|
cmds.setAttr(toeIKNodes[0] + ".v", 0)
|
|
|
|
|
|
|
|
#create the locators we need for all of the pivot points
|
|
toeTipPivot = cmds.spaceLocator(name = "ik_foot_toe_tip_pivot_" + side)[0]
|
|
insidePivot = cmds.spaceLocator(name = "ik_foot_inside_pivot_" + side)[0]
|
|
outsidePivot = cmds.spaceLocator(name = "ik_foot_outside_pivot_" + side)[0]
|
|
heelPivot = cmds.spaceLocator(name = "ik_foot_heel_pivot_" + side)[0]
|
|
toePivot = cmds.spaceLocator(name = "ik_foot_toe_pivot_" + side)[0]
|
|
ballPivot = cmds.spaceLocator(name = "ik_foot_ball_pivot_" + side)[0]
|
|
masterBallPivot = cmds.spaceLocator(name = "master_foot_ball_pivot_" + side)[0]
|
|
|
|
#create the controls
|
|
heelControl = self.createControl("arrowOnBall", 1.5, "heel_ctrl_" + side)
|
|
toeWiggleControl = self.createControl("arrowOnBall", 2, "toe_wiggle_ctrl_" + side)
|
|
toeControl = self.createControl("arrowOnBall", 1.5, "toe_tip_ctrl_" + side)
|
|
|
|
if side == "l":
|
|
cmds.setAttr(toeControl + ".rx", -90)
|
|
cmds.setAttr(toeControl + ".rz", -90)
|
|
cmds.makeIdentity(toeControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
else:
|
|
cmds.setAttr(toeControl + ".rx", 90)
|
|
cmds.setAttr(toeControl + ".rz", -90)
|
|
cmds.makeIdentity(toeControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
if side == "l":
|
|
cmds.setAttr(toeWiggleControl + ".rx", -90)
|
|
cmds.makeIdentity(toeWiggleControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
else:
|
|
cmds.setAttr(toeWiggleControl + ".rx", 90)
|
|
cmds.makeIdentity(toeWiggleControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
cmds.setAttr(heelControl + ".rx", -90)
|
|
cmds.makeIdentity(heelControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#position and orient controls
|
|
constraint = cmds.parentConstraint("jointmover_" + side + "_heel_loc", heelControl)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint("ball_" + side + "_lra", toeWiggleControl)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.pointConstraint("jointmover_toe_" + side + "_end", toeControl)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.orientConstraint(toeWiggleControl, toeControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#position the pivots
|
|
constraint = cmds.pointConstraint(heelControl, heelPivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.orientConstraint(heelControl, heelPivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint(toeWiggleControl, ballPivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint(toeControl, toeTipPivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint(toeControl, toePivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint("inside_pivot_" + side + "_mover", insidePivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint("outside_pivot_" + side + "_mover", outsidePivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint(ballPivot, masterBallPivot)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
|
|
|
|
#create groups for each pivot and parent the pivot to the corresponding group
|
|
for piv in [heelPivot, ballPivot, toeTipPivot, toePivot, insidePivot, outsidePivot, masterBallPivot]:
|
|
pivGrp = cmds.group(empty = True, name = piv + "_grp")
|
|
constraint = cmds.parentConstraint(piv, pivGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(piv, pivGrp)
|
|
shape = cmds.listRelatives(piv, shapes = True)[0]
|
|
cmds.setAttr(shape + ".v", 0)
|
|
|
|
|
|
|
|
#create groups for each control and parent the control to the corresponding group
|
|
for ctrl in [heelControl, toeWiggleControl, toeControl]:
|
|
grp = cmds.group(empty = True, name = ctrl + "_grp")
|
|
constraint = cmds.parentConstraint(ctrl, grp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(ctrl, grp)
|
|
|
|
if side == "r":
|
|
if ctrl == heelControl:
|
|
cmds.setAttr(grp + ".rx", (cmds.getAttr(grp + ".rx")) *1)
|
|
cmds.setAttr(grp + ".ry", (cmds.getAttr(grp + ".ry")) *1)
|
|
|
|
|
|
|
|
#setup pivot hierarchy
|
|
cmds.parent(toeWiggleControl + "_grp", toePivot)
|
|
cmds.parent(ballPivot + "_grp", toePivot)
|
|
cmds.parent(toePivot + "_grp", heelPivot)
|
|
cmds.parent(heelPivot + "_grp", outsidePivot)
|
|
cmds.parent(outsidePivot + "_grp", insidePivot)
|
|
cmds.parent(insidePivot + "_grp", toeTipPivot)
|
|
|
|
|
|
|
|
#setup foot roll
|
|
cmds.setAttr(heelControl + ".rz", 0)
|
|
cmds.setAttr(heelPivot + ".rz", 0)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", 0)
|
|
cmds.setDrivenKeyframe([heelPivot + ".rz", toePivot + ".rz", ballPivot + ".rz"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
|
|
|
|
|
|
if side == "l":
|
|
cmds.setAttr(heelControl + ".rz", -90)
|
|
cmds.setAttr(heelPivot + ".rz", 0)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", -90)
|
|
cmds.setDrivenKeyframe([heelPivot + ".rz", toePivot + ".rz", ballPivot + ".rz"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(heelControl + ".rz", 90)
|
|
cmds.setAttr(heelPivot + ".rz", 90)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", 0)
|
|
cmds.setDrivenKeyframe([heelPivot + ".rz", toePivot + ".rz", ballPivot + ".rz"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(heelControl + ".rz", 0)
|
|
cmds.setAttr(heelPivot + ".rz", 0)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", 0)
|
|
|
|
|
|
if side == "r":
|
|
cmds.setAttr(heelControl + ".rz", -90)
|
|
cmds.setAttr(heelPivot + ".rz", 0)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", -90)
|
|
cmds.setDrivenKeyframe([heelPivot + ".rz", toePivot + ".rz", ballPivot + ".rz"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(heelControl + ".rz", 90)
|
|
cmds.setAttr(heelPivot + ".rz", 90)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", 0)
|
|
cmds.setDrivenKeyframe([heelPivot + ".rz", toePivot + ".rz", ballPivot + ".rz"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(heelControl + ".rz", 0)
|
|
cmds.setAttr(heelPivot + ".rz", 0)
|
|
cmds.setAttr(toePivot + ".rz", 0)
|
|
cmds.setAttr(ballPivot + ".rz", 0)
|
|
|
|
|
|
#setup heel rotate X and Y
|
|
|
|
if side == "l":
|
|
cmds.connectAttr(heelControl + ".rx", ballPivot + ".ry")
|
|
|
|
if side == "r":
|
|
heelControlRXMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = heelControl + "_RX_MultNode")
|
|
cmds.connectAttr(heelControl + ".rx", heelControlRXMultNode + ".input1X")
|
|
cmds.setAttr(heelControlRXMultNode + ".input2X", -1)
|
|
cmds.connectAttr(heelControlRXMultNode + ".outputX", ballPivot + ".ry")
|
|
|
|
|
|
|
|
|
|
if side == "l":
|
|
heelControlRYMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = heelControl + "_RY_MultNode")
|
|
cmds.connectAttr(heelControl + ".ry", heelControlRYMultNode + ".input1X")
|
|
cmds.setAttr(heelControlRYMultNode + ".input2X", -1)
|
|
cmds.connectAttr(heelControlRYMultNode + ".outputX", ballPivot + ".rx")
|
|
|
|
else:
|
|
cmds.connectAttr(heelControl + ".ry", ballPivot + ".rx")
|
|
|
|
|
|
#setup toe control Y and Z rotates
|
|
cmds.connectAttr(toeControl + ".ry", toeTipPivot + ".ry")
|
|
cmds.connectAttr(toeControl + ".rz", toeTipPivot + ".rz")
|
|
|
|
|
|
#setup the toe control RX (side to side)
|
|
if side == "l":
|
|
cmds.setAttr(toeControl + ".rx", 0)
|
|
cmds.setAttr(insidePivot + ".rx", 0)
|
|
cmds.setAttr(outsidePivot + ".rx", 0)
|
|
cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(toeControl + ".rx", -90)
|
|
cmds.setAttr(insidePivot + ".rx", 0)
|
|
cmds.setAttr(outsidePivot + ".rx", -90)
|
|
cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(toeControl + ".rx", 90)
|
|
cmds.setAttr(insidePivot + ".rx", 90)
|
|
cmds.setAttr(outsidePivot + ".rx", 0)
|
|
cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(toeControl + ".rx", 0)
|
|
cmds.setAttr(insidePivot + ".rx", 0)
|
|
cmds.setAttr(outsidePivot + ".rx", 0)
|
|
|
|
if side == "r":
|
|
cmds.setAttr(toeControl + ".rx", 0)
|
|
cmds.setAttr(insidePivot + ".rx", 0)
|
|
cmds.setAttr(outsidePivot + ".rx", 0)
|
|
cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(toeControl + ".rx", -90)
|
|
cmds.setAttr(insidePivot + ".rx", 0)
|
|
cmds.setAttr(outsidePivot + ".rx", 90)
|
|
cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(toeControl + ".rx", 90)
|
|
cmds.setAttr(insidePivot + ".rx", -90)
|
|
cmds.setAttr(outsidePivot + ".rx", 0)
|
|
cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(toeControl + ".rx", 0)
|
|
cmds.setAttr(insidePivot + ".rx", 0)
|
|
cmds.setAttr(outsidePivot + ".rx", 0)
|
|
|
|
|
|
|
|
#parent the IK nodes into the foot rig setup
|
|
cmds.parent(footIK, ballPivot)
|
|
cmds.parent(ballIKNodes[0], ballPivot)
|
|
cmds.parent(toeIKNodes[0], toeWiggleControl)
|
|
cmds.pointConstraint(footCtrl, targetLoc, mo = True)
|
|
cmds.parent([toeTipPivot + "_grp", heelControl + "_grp", toeControl + "_grp"], masterBallPivot)
|
|
cmds.parent(masterBallPivot + "_grp", footCtrl)
|
|
|
|
|
|
#add the heel pivot and ball pivot attrs to the foot control
|
|
cmds.select(heelControl)
|
|
|
|
cmds.addAttr(longName= ( "heelPivot" ), defaultValue=0, keyable = True)
|
|
cmds.addAttr(longName= ( "ballPivot" ), defaultValue=0, keyable = True)
|
|
|
|
#setup heel and ball pivot
|
|
|
|
if side == "r":
|
|
heelPivotMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = heelPivot + "_MultNode")
|
|
cmds.connectAttr(heelControl + ".heelPivot", heelPivotMultNode + ".input1X")
|
|
cmds.setAttr(heelPivotMultNode + ".input2X", -1)
|
|
cmds.connectAttr(heelPivotMultNode + ".outputX", heelPivot + ".rx")
|
|
|
|
else:
|
|
cmds.connectAttr(heelControl + ".heelPivot", heelPivot + ".rx")
|
|
|
|
cmds.connectAttr(heelControl + ".ballPivot", masterBallPivot + ".ry")
|
|
|
|
|
|
#clean up the hierarchy
|
|
ctrlGrp = cmds.group(name = "leg_ctrl_grp_" + side, empty = True)
|
|
cmds.parent([ikThighJoint, targetGrp, aimGrp, noflipVectorGrp], ctrlGrp)
|
|
legGroup = cmds.group(name = "leg_group_" + side, empty = True)
|
|
constraint = cmds.pointConstraint("driver_pelvis", legGroup)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent([footCtrlSpaceSwitcherFollow, beginJoint, ctrlGrp], legGroup)
|
|
cmds.orientConstraint("body_anim_grp", ctrlGrp, mo = True)
|
|
cmds.pointConstraint("body_anim", ctrlGrp, mo = True)
|
|
|
|
#constrain aimGrp
|
|
cmds.pointConstraint("body_anim", aimGrp, mo = True)
|
|
cmds.orientConstraint("offset_anim", aimGrp, mo = True)
|
|
|
|
|
|
#cmds.parentConstraint("driver_pelvis", beginJoint, mo = True)
|
|
ikGrp = cmds.group(name = "ik_leg_grp_" + side, empty = True)
|
|
cmds.parent(ikGrp, legGroup)
|
|
cmds.parent([kneeCtrlGrp, footCtrlSpaceSwitcherFollow], ikGrp)
|
|
|
|
|
|
|
|
#color the controls
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
for control in [footCtrl]:
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
|
|
#connect ik twist attr to ik leg twist
|
|
cmds.select(footCtrl)
|
|
cmds.addAttr(longName=("knee_twist"), at = 'double', keyable = True)
|
|
if side == "r":
|
|
cmds.connectAttr(footCtrl + ".knee_twist", footIK + ".twist")
|
|
|
|
else:
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", name = "ik_leg_" + side + "_twistMultNode", asUtility = True)
|
|
cmds.connectAttr(footCtrl + ".knee_twist", twistMultNode + ".input1X")
|
|
cmds.setAttr(twistMultNode + ".input2X", -1)
|
|
cmds.connectAttr(twistMultNode + ".outputX", footIK + ".twist")
|
|
|
|
|
|
|
|
#add stretchy IK to legs
|
|
cmds.select(footCtrl)
|
|
cmds.addAttr(longName=("stretch"), at = 'double',min = 0, max = 1, dv = 0, keyable = True)
|
|
cmds.addAttr(longName=("squash"), at = 'double',min = 0, max = 1, dv = 0, keyable = True)
|
|
cmds.addAttr(longName=("toeCtrlVis"), at = 'bool', dv = 0, keyable = True)
|
|
stretchMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "ikLeg_stretchToggleMultNode_" + side)
|
|
|
|
|
|
|
|
#need to get the total length of the leg chain
|
|
totalDist = abs(cmds.getAttr(ikCalfJoint + ".tx" ) + cmds.getAttr(ikFootJoint + ".tx"))
|
|
|
|
|
|
#create a distanceBetween node
|
|
distBetween = cmds.shadingNode("distanceBetween", asUtility = True, name = side + "_ik_leg_distBetween")
|
|
|
|
#get world positions of upper arm and ik
|
|
baseGrp = cmds.group(empty = True, name = "ik_leg_base_grp_" + side)
|
|
endGrp = cmds.group(empty = True, name = "ik_leg_end_grp_" + side)
|
|
cmds.pointConstraint(ikThighJoint, baseGrp)
|
|
cmds.pointConstraint(footCtrl, endGrp)
|
|
|
|
#hook in group translates into distanceBetween node inputs
|
|
cmds.connectAttr(baseGrp + ".translate", distBetween + ".point1")
|
|
cmds.connectAttr(endGrp + ".translate", distBetween + ".point2")
|
|
|
|
#create a condition node that will compare original length to current length
|
|
#if second term is greater than, or equal to the first term, the chain needs to stretch
|
|
ikLegCondition = cmds.shadingNode("condition", asUtility = True, name = side + "_ik_leg_stretch_condition")
|
|
cmds.setAttr(ikLegCondition + ".operation", 3)
|
|
cmds.connectAttr(distBetween + ".distance", ikLegCondition + ".secondTerm")
|
|
cmds.setAttr(ikLegCondition + ".firstTerm", totalDist)
|
|
|
|
#hook up the condition node's return colors
|
|
cmds.setAttr(ikLegCondition + ".colorIfTrueR", totalDist)
|
|
cmds.connectAttr(distBetween + ".distance", ikLegCondition + ".colorIfFalseR")
|
|
|
|
|
|
#create the mult/divide node(set to divide) that will take the original creation length as a static value in input2x, and the connected length into 1x.
|
|
legDistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "leg_dist_multNode_" + side)
|
|
cmds.setAttr(legDistMultNode + ".operation", 2) #divide
|
|
cmds.connectAttr(ikLegCondition + ".outColorR", legDistMultNode + ".input1X")
|
|
|
|
|
|
#add attr to foot control for stretch bias
|
|
cmds.addAttr(footCtrl, ln = "stretchBias", minValue = 0.0, maxValue = 1.0, defaultValue = 0.0, keyable = True)
|
|
|
|
#add divide node so that instead of driving 0-1, we're actually only driving 0 - 0.2
|
|
divNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "stretchBias_Div_" + side)
|
|
cmds.connectAttr(footCtrl + ".stretchBias", divNode + ".input1X")
|
|
cmds.setAttr(divNode + ".operation", 2)
|
|
cmds.setAttr(divNode + ".input2X", 5)
|
|
|
|
#create the add node and connect the stretchBias into it, adding 1
|
|
addNode = cmds.shadingNode("plusMinusAverage", asUtility = True, name = "stretchBias_Add_" + side)
|
|
cmds.connectAttr(divNode + ".outputX", addNode + ".input1D[0]")
|
|
cmds.setAttr(addNode + ".input1D[1]", 1.0)
|
|
|
|
#connect output of addNode to new mult node input1x
|
|
stretchBiasMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "stretchBias_multNode_" + side)
|
|
cmds.connectAttr(addNode + ".output1D", stretchBiasMultNode + ".input1X")
|
|
|
|
#set input2x to totalDist
|
|
cmds.setAttr(stretchBiasMultNode + ".input2X", totalDist)
|
|
|
|
#connect output to input2x on legDistMultNode
|
|
cmds.connectAttr(stretchBiasMultNode + ".outputX", legDistMultNode + ".input2X")
|
|
|
|
|
|
|
|
#create a stretch toggle mult node that multiplies the stretch factor by the bool of the stretch attr. (0 or 1), this way our condition reads
|
|
#if this result is greater than the original length(impossible if stretch bool is off, since result will be 0), than take this result and plug it
|
|
#into the scale of our IK arm joints
|
|
stretchToggleCondition = cmds.shadingNode("condition", asUtility = True, name = "leg_stretch_toggle_condition_" + side)
|
|
cmds.setAttr(stretchToggleCondition + ".operation", 0)
|
|
cmds.connectAttr(footCtrl + ".stretch", stretchToggleCondition + ".firstTerm")
|
|
cmds.setAttr(stretchToggleCondition + ".secondTerm", 1)
|
|
cmds.connectAttr(legDistMultNode + ".outputX", stretchToggleCondition + ".colorIfTrueR")
|
|
cmds.setAttr(stretchToggleCondition + ".colorIfFalseR", 1)
|
|
|
|
|
|
#set up the squash nodes
|
|
squashMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = side + "_ik_leg_squash_mult")
|
|
cmds.setAttr(squashMultNode + ".operation", 2)
|
|
cmds.setAttr(squashMultNode + ".input1X", totalDist)
|
|
cmds.connectAttr(ikLegCondition + ".outColorR", squashMultNode + ".input2X")
|
|
|
|
|
|
#create a stretch toggle mult node that multiplies the stretch factor by the bool of the stretch attr. (0 or 1), this way our condition reads
|
|
#if this result is greater than the original length(impossible if stretch bool is off, since result will be 0), than take this result and plug it
|
|
#into the scale of our IK arm joints
|
|
squashToggleCondition = cmds.shadingNode("condition", asUtility = True, name = "leg_squash_toggle_condition_" + side)
|
|
cmds.setAttr(squashToggleCondition + ".operation", 0)
|
|
cmds.connectAttr(footCtrl + ".squash", squashToggleCondition + ".firstTerm")
|
|
cmds.setAttr(squashToggleCondition + ".secondTerm", 1)
|
|
cmds.connectAttr(squashMultNode + ".outputX", squashToggleCondition + ".colorIfTrueR")
|
|
cmds.setAttr(squashToggleCondition + ".colorIfFalseR", 1)
|
|
|
|
|
|
|
|
#connect to arm scale
|
|
cmds.connectAttr(stretchToggleCondition + ".outColorR", ikThighJoint + ".sx")
|
|
cmds.connectAttr(stretchToggleCondition + ".outColorR", ikCalfJoint + ".sx")
|
|
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikCalfJoint + ".sy")
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikCalfJoint + ".sz")
|
|
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikThighJoint + ".sy")
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikThighJoint + ".sz")
|
|
|
|
|
|
#add base and end groups to arm grp
|
|
cmds.parent([baseGrp, endGrp], ctrlGrp)
|
|
|
|
|
|
#lock attrs on control that shouldn't be animated
|
|
|
|
for control in [toeControl, heelControl, toeWiggleControl]:
|
|
cmds.setAttr(control + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#lock attrs on foot control that should not be animated
|
|
cmds.setAttr(footCtrl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(footCtrl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(footCtrl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(footCtrl + ".v", lock = True, keyable = False)
|
|
|
|
#lock attrs on knee control that should not be animated
|
|
cmds.connectAttr(footCtrl + ".knee_twist", kneeCtrl + ".rx")
|
|
|
|
|
|
cmds.setAttr(kneeCtrl + ".rx", lock = False, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".ry", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".rz", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(kneeCtrl + ".v", lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildFingers(self):
|
|
|
|
#find out which finger joints need to be rigged
|
|
for side in ["l", "r"]:
|
|
|
|
|
|
#create a list to hold all ctrl groups that are created
|
|
ctrlGroups = []
|
|
ikGrps = []
|
|
joints = []
|
|
fkOrients = []
|
|
metaJoints = []
|
|
ikJoints = []
|
|
|
|
|
|
children = cmds.listRelatives("driver_hand_" + side, children = True, type = 'joint')
|
|
allChildren = cmds.listRelatives("driver_hand_" + side, allDescendents = True, type = 'joint')
|
|
|
|
#find out how many finger joints we have for each finger
|
|
thumbMeta = [False, None]
|
|
indexMeta = [False, None]
|
|
middleMeta = [False, None]
|
|
ringMeta = [False, None]
|
|
pinkyMeta = [False, None]
|
|
numThumbJoints = [0, "thumb"]
|
|
numIndexJoints = [0, "index"]
|
|
numMiddleJoints = [0, "middle"]
|
|
numRingJoints = [0, "ring"]
|
|
numPinkyJoints = [0, "pinky"]
|
|
|
|
if allChildren:
|
|
for finger in allChildren:
|
|
#find if metatarsals exist
|
|
if finger.find("meta") != -1:
|
|
if finger.partition("driver_")[2].find("index") == 0:
|
|
indexMeta = [True, "index"]
|
|
if finger.partition("driver_")[2].find("middle") == 0:
|
|
middleMeta = [True, "middle"]
|
|
if finger.partition("driver_")[2].find("ring") == 0:
|
|
ringMeta = [True, "ring"]
|
|
if finger.partition("driver_")[2].find("pinky") == 0:
|
|
pinkyMeta = [True, "pinky"]
|
|
|
|
|
|
#get num fingers -meta
|
|
if finger.partition("driver_")[2].find("thumb") == 0:
|
|
numThumbJoints[0] += 1
|
|
if finger.partition("driver_")[2].find("index") == 0:
|
|
numIndexJoints[0] += 1
|
|
if finger.partition("driver_")[2].find("middle") == 0:
|
|
numMiddleJoints[0] += 1
|
|
if finger.partition("driver_")[2].find("ring") == 0:
|
|
numRingJoints[0] += 1
|
|
if finger.partition("driver_")[2].find("pinky") == 0:
|
|
numPinkyJoints[0] += 1
|
|
|
|
|
|
#subtract metacarpals (only if they exist!)
|
|
if indexMeta[0] == True:
|
|
numIndexJoints[0] -= 1
|
|
if middleMeta[0] == True:
|
|
numMiddleJoints[0] -= 1
|
|
if ringMeta[0] == True:
|
|
numRingJoints[0] -= 1
|
|
if pinkyMeta[0] == True:
|
|
numPinkyJoints[0] -= 1
|
|
|
|
|
|
|
|
|
|
#duplicate the driver joints to be used as the rig joints
|
|
if children:
|
|
for child in children:
|
|
for mode in ["fk", "ik"]:
|
|
dupeChildNodes = cmds.duplicate(child, name = "temp")
|
|
|
|
#parent root joint of each finger to world if not already child of world
|
|
parent = cmds.listRelatives(dupeChildNodes[0], parent = True)[0]
|
|
if parent != None:
|
|
cmds.parent(dupeChildNodes[0], world = True)
|
|
|
|
#rename duped joints
|
|
for node in dupeChildNodes:
|
|
if node == "temp":
|
|
niceName = child.partition("driver_")[2]
|
|
joint = cmds.rename(node, "rig_" + mode + "_" + niceName)
|
|
if mode == "ik":
|
|
ikJoints.append(joint)
|
|
else:
|
|
joints.append(joint)
|
|
|
|
else:
|
|
niceName = node.partition("driver_")[2]
|
|
cmds.rename("rig_*|" + node, "rig_" + mode + "_" + niceName)
|
|
|
|
|
|
|
|
|
|
#if the metacarpal fingers exist, create a control for them
|
|
for meta in [indexMeta, middleMeta, ringMeta, pinkyMeta]:
|
|
if meta[0] == True:
|
|
#create the control object for the metacarpal
|
|
ctrlName = meta[1]
|
|
ctrlName = ctrlName + "_metacarpal_ctrl_" + side
|
|
control = self.createControl("square", 1, ctrlName)
|
|
constraint = cmds.parentConstraint("rig_fk_" + meta[1] + "_metacarpal_" + side, control)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.setAttr(control + ".sx", 0)
|
|
cmds.setAttr(control + ".sy", 15)
|
|
cmds.setAttr(control + ".sz", 15)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#create the group node and parent ctrl to it
|
|
ctrlGrp = cmds.group(empty = True, name = ctrlName + "_grp")
|
|
constraint = cmds.parentConstraint("rig_fk_" + meta[1] + "_metacarpal_" + side, ctrlGrp)[0]
|
|
metaJoints.append(ctrlGrp)
|
|
|
|
cmds.delete(constraint)
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#parent constrain the rig joint to the control
|
|
cmds.parentConstraint(control, "rig_fk_" + meta[1] + "_metacarpal_" + side, mo = True)
|
|
cmds.parentConstraint(control, "rig_ik_" + meta[1] + "_metacarpal_" + side, mo = True)
|
|
|
|
#lock attrs on control that shouldn't be animated
|
|
cmds.setAttr(control + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#color the controls
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
|
|
|
|
#Create the FK orient joints
|
|
|
|
#first create a group for the IK handles to go into. Then setup the constraints on this group and set driven keys
|
|
ikHandlesGrp = cmds.group(empty = True, name = "fkOrient_ikHandles_" + side + "_grp")
|
|
constraint = cmds.parentConstraint("ik_wrist_" + side + "_anim", "fk_wrist_" + side + "_anim", ikHandlesGrp, mo = True)[0]
|
|
|
|
cmds.setAttr("Rig_Settings" + "." + side + "ArmMode", 0)
|
|
cmds.setAttr(constraint + ".ik_wrist_" + side + "_anim" + "W0", 0)
|
|
cmds.setAttr(constraint + ".fk_wrist_" + side + "_anim" + "W1", 1)
|
|
cmds.setDrivenKeyframe([constraint + ".ik_wrist_" + side + "_anim" + "W0", constraint + ".fk_wrist_" + side + "_anim" + "W1"], cd = "Rig_Settings" + "." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings" + "." + side + "ArmMode", 1)
|
|
cmds.setAttr(constraint + ".ik_wrist_" + side + "_anim" + "W0", 1)
|
|
cmds.setAttr(constraint + ".fk_wrist_" + side + "_anim" + "W1", 0)
|
|
cmds.setDrivenKeyframe([constraint + ".ik_wrist_" + side + "_anim" + "W0", constraint + ".fk_wrist_" + side + "_anim" + "W1"], cd = "Rig_Settings" + "." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
|
|
|
|
for fingers in [numIndexJoints, numMiddleJoints, numRingJoints, numPinkyJoints, numThumbJoints]:
|
|
if fingers[0] > 0:
|
|
|
|
#setup metaCtrl name
|
|
if fingers[1] == "thumb":
|
|
metaCtrl = fingers[1] + "_01_" + side
|
|
|
|
else:
|
|
metaCtrl = fingers[1] + "_metacarpal_ctrl_" + side
|
|
|
|
#create the base and end joint
|
|
baseJoint = cmds.duplicate("rig_fk_" + fingers[1] + "_01_" + side, po = True, name = "rig_fkOrient_" + fingers[1] + "_01_" + side)[0]
|
|
endJoint = cmds.duplicate("rig_fk_" + fingers[1] + "_0" + str(fingers[0]) + "_" + side, po = True, name = "rig_fkOrient_" + fingers[1] + "_0" + str(fingers[0]) + "_" + side)[0]
|
|
|
|
|
|
#position the end joint
|
|
scaleFactor = self.getScaleFactor()
|
|
if side == "l":
|
|
cmds.parent(endJoint, "rig_fk_" + fingers[1] + "_0" + str(fingers[0]) + "_" + side)
|
|
cmds.setAttr(endJoint + ".tx", 5 * scaleFactor)
|
|
|
|
else:
|
|
cmds.parent(endJoint, "rig_fk_" + fingers[1] + "_0" + str(fingers[0]) + "_" + side)
|
|
cmds.setAttr(endJoint + ".tx", -5 * scaleFactor)
|
|
|
|
#parent the end joint to the base joint
|
|
cmds.parent(endJoint, baseJoint)
|
|
|
|
#create SC ik handles for each chain
|
|
ikNodes = cmds.ikHandle(sol = "ikSCsolver", name = baseJoint + "_ikHandle", sj = baseJoint, ee = endJoint)[0]
|
|
cmds.parent(ikNodes, ikHandlesGrp)
|
|
cmds.setAttr(ikNodes + ".v", 0)
|
|
|
|
#parent our orient joint to the metacarpal if it exists
|
|
if cmds.objExists(metaCtrl):
|
|
if fingers[1] == "thumb":
|
|
fkOrients.append(baseJoint)
|
|
|
|
else:
|
|
cmds.parent(baseJoint, metaCtrl)
|
|
|
|
else:
|
|
fkOrients.append(baseJoint)
|
|
|
|
|
|
|
|
#Create FK controls for the fingers
|
|
fkControls = []
|
|
for fingers in [numIndexJoints, numMiddleJoints, numRingJoints, numPinkyJoints, numThumbJoints]:
|
|
for i in range(int(fingers[0])):
|
|
|
|
#create an FK control per finger
|
|
ctrlName = fingers[1] + "_finger_fk_ctrl_" + str(i + 1) + "_" + side
|
|
control = self.createControl("circle", 3, ctrlName)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
|
|
|
|
metaCtrl = fingers[1] + "_metacarpal_ctrl_" + side
|
|
|
|
if cmds.objExists(metaCtrl) == False:
|
|
if (i + 1) == 1:
|
|
ctrlGroups.append(ctrlGrp)
|
|
|
|
#add the created control to the controls list
|
|
fkControls.append(control)
|
|
|
|
#position control
|
|
constraint = cmds.parentConstraint("rig_fk_" + fingers[1] + "_0" + str(i+1) + "_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_fk_" + fingers[1] + "_0" + str(i+1) + "_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
|
|
#duplicate the ctrl group to create the driven group
|
|
drivenGrp = cmds.duplicate(ctrlGrp, parentOnly = True, name = control + "_driven_grp")[0]
|
|
ctrlGroups.append(drivenGrp)
|
|
cmds.parent(drivenGrp, ctrlGrp)
|
|
|
|
#parent control to grp
|
|
cmds.parent(control, drivenGrp)
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".ry", -90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#constrain finger joint to control
|
|
cmds.parentConstraint(control, "rig_fk_" + fingers[1] + "_0" + str(i+1) + "_" + side, mo = True)
|
|
|
|
|
|
#if we aren't the root of the finger chain, then parent our ctrlGrp to the previous fk control
|
|
if i != 0:
|
|
cmds.parent(ctrlGrp, ctrlParent)
|
|
|
|
else:
|
|
|
|
#if the control grp is the root of the finger chain, need to parent the ctrl grp to the metaCtrl
|
|
if cmds.objExists(metaCtrl):
|
|
cmds.parent(ctrlGrp, metaCtrl)
|
|
|
|
|
|
#setup set driven keys for the orientation options
|
|
cmds.select(control)
|
|
cmds.addAttr(longName= ( "sticky" ), defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#setup the constraint between the fk finger orient joint and the ctrlGrp
|
|
constraint = cmds.parentConstraint("rig_fkOrient_" + fingers[1] + "_01_" + side, ctrlGrp, mo = True)[0]
|
|
|
|
#set driven keyframes on constraint
|
|
cmds.setAttr(control + ".sticky", 1)
|
|
cmds.setAttr(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", 1)
|
|
cmds.setDrivenKeyframe(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", cd = control + ".sticky", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".sticky", 0)
|
|
cmds.setAttr(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", 0)
|
|
cmds.setDrivenKeyframe(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", cd = control + ".sticky", itt = "linear", ott = "linear")
|
|
|
|
if fingers[1] == "thumb":
|
|
cmds.setAttr(control + ".sticky", 1)
|
|
|
|
else:
|
|
cmds.setAttr(control + ".sticky", 0)
|
|
|
|
ctrlGroups.append(ctrlGrp)
|
|
|
|
|
|
|
|
#if the meta carpal does not exist, simply parent the root group under the base joint
|
|
else:
|
|
ctrlGroups.append(ctrlGrp)
|
|
|
|
constraint = cmds.parentConstraint("rig_fkOrient_" + fingers[1] + "_01_" + side, ctrlGrp, mo = True)[0]
|
|
|
|
#setup set driven keys for the orientation options
|
|
cmds.select(control)
|
|
cmds.addAttr(longName= ( "sticky" ), defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#set driven keyframes on constraint
|
|
cmds.setAttr(control + ".sticky", 1)
|
|
cmds.setAttr(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", 1)
|
|
cmds.setDrivenKeyframe(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", cd = control + ".sticky", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".sticky", 0)
|
|
cmds.setAttr(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", 0)
|
|
cmds.setDrivenKeyframe(constraint + "." + "rig_fkOrient_" + fingers[1] + "_01_" + side + "W0", cd = control + ".sticky", itt = "linear", ott = "linear")
|
|
|
|
#set the control parent for the next ctrl in the chain to the current control
|
|
ctrlParent = control
|
|
|
|
#lock attrs on control that shouldn't be animated
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#color the controls
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
|
|
#setup the hand roll feature
|
|
|
|
#create our 4 locators(pivots) and position
|
|
pinkyPiv = cmds.spaceLocator(name = "hand_" + side + "_pinky_pivot")[0]
|
|
thumbPiv = cmds.spaceLocator(name = "hand_" + side + "_thumb_pivot")[0]
|
|
midPiv = cmds.spaceLocator(name = "hand_" + side + "_mid_pivot")[0]
|
|
tipPiv = cmds.spaceLocator(name = "hand_" + side + "_tip_pivot")[0]
|
|
|
|
for piv in [pinkyPiv, thumbPiv, midPiv, tipPiv]:
|
|
cmds.setAttr(piv + ".v", 0)
|
|
|
|
constraint = cmds.parentConstraint(side + "_hand_pinky_pivot", pinkyPiv)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(side + "_hand_thumb_pivot", thumbPiv)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(side + "_hand_mid_pivot", midPiv)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(side + "_hand_tip_pivot", tipPiv)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create the control groups for the pivots so our values are zeroed
|
|
for each in [pinkyPiv, thumbPiv, midPiv, tipPiv]:
|
|
group = cmds.group(empty = True, name = each + "_grp")
|
|
constraint = cmds.parentConstraint(each, group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(each, group)
|
|
|
|
#setup hierarchy
|
|
cmds.parent(thumbPiv + "_grp", pinkyPiv)
|
|
cmds.parent(tipPiv + "_grp", thumbPiv)
|
|
cmds.parent(midPiv + "_grp", tipPiv)
|
|
|
|
#parent the arm IK handles under the midPiv locator
|
|
cmds.parent(["arm_ikHandle_" + side, "invis_arm_ikHandle_" + side], midPiv)
|
|
cmds.parent(pinkyPiv + "_grp", "ik_wrist_" + side + "_anim")
|
|
|
|
#add attrs to the IK hand control (side, roll, tip pivot)
|
|
cmds.select("ik_wrist_" + side + "_anim")
|
|
cmds.addAttr(longName= ( "side" ), defaultValue=0, keyable = True)
|
|
cmds.addAttr(longName= ( "mid_bend" ), defaultValue=0, keyable = True)
|
|
cmds.addAttr(longName= ( "mid_swivel" ), defaultValue=0, keyable = True)
|
|
cmds.addAttr(longName= ( "tip_pivot" ), defaultValue=0, keyable = True)
|
|
cmds.addAttr(longName= ( "tip_swivel" ), defaultValue=0, keyable = True)
|
|
|
|
|
|
#hook up attrs to pivot locators
|
|
cmds.connectAttr("ik_wrist_" + side + "_anim.mid_bend", midPiv + ".rz")
|
|
cmds.connectAttr("ik_wrist_" + side + "_anim.tip_pivot", tipPiv + ".rz")
|
|
|
|
cmds.connectAttr("ik_wrist_" + side + "_anim.mid_swivel", midPiv + ".ry")
|
|
cmds.connectAttr("ik_wrist_" + side + "_anim.tip_swivel", tipPiv + ".ry")
|
|
|
|
|
|
|
|
#set driven keys for the side to side attr
|
|
|
|
if side == "l":
|
|
thumbVal = 180
|
|
pinkyVal = -180
|
|
|
|
else:
|
|
thumbVal = 180
|
|
pinkyVal = -180
|
|
|
|
cmds.setAttr("ik_wrist_" + side + "_anim.side", 0)
|
|
cmds.setAttr(pinkyPiv + ".rx", 0)
|
|
cmds.setAttr(thumbPiv + ".rx", 0)
|
|
cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd = "ik_wrist_" + side + "_anim.side", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("ik_wrist_" + side + "_anim.side", 180)
|
|
cmds.setAttr(pinkyPiv + ".rx", pinkyVal)
|
|
cmds.setAttr(thumbPiv + ".rx", 0)
|
|
cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd = "ik_wrist_" + side + "_anim.side", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("ik_wrist_" + side + "_anim.side", -180)
|
|
cmds.setAttr(pinkyPiv + ".rx", 0)
|
|
cmds.setAttr(thumbPiv + ".rx", thumbVal)
|
|
cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd = "ik_wrist_" + side + "_anim.side", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("ik_wrist_" + side + "_anim.side", 0)
|
|
|
|
|
|
|
|
|
|
|
|
#If there are enough finger joints on each finger, create IK rig
|
|
ikCtrls = []
|
|
poleVectorLocs = []
|
|
modeGrps = []
|
|
for fingers in [numIndexJoints, numMiddleJoints, numRingJoints, numPinkyJoints, numThumbJoints]:
|
|
|
|
if fingers[0] == 3:
|
|
|
|
#set preferred angles on joints so IK will create properly
|
|
cmds.setAttr("rig_ik_" + fingers[1] + "_01_" + side + ".preferredAngleZ", 45)
|
|
cmds.setAttr("rig_ik_" + fingers[1] + "_02_" + side + ".preferredAngleZ", 45)
|
|
cmds.setAttr("rig_ik_" + fingers[1] + "_03_" + side + ".preferredAngleZ", 45)
|
|
|
|
|
|
#create a tip joint
|
|
tipJoint = cmds.duplicate("rig_ik_" + fingers[1] + "_03_" + side, po = True, name = "rig_ik_" + fingers[1] + "_tip_" + side)[0]
|
|
cmds.parent(tipJoint, "rig_ik_" + fingers[1] + "_03_" + side)
|
|
|
|
#position tip joint
|
|
if side == "l":
|
|
cmds.setAttr(tipJoint + ".tx", 5 * scaleFactor)
|
|
else:
|
|
cmds.setAttr(tipJoint + ".tx", -5 * scaleFactor)
|
|
|
|
#create the IK handle
|
|
ikNodes = cmds.ikHandle(sol = "ikRPsolver", name = fingers[1] + "_" + side + "_ikHandle", sj = "rig_ik_" + fingers[1] + "_01_" + side, ee = "rig_ik_" + fingers[1] + "_03_" + side)[0]
|
|
ikTipNodes = cmds.ikHandle(sol = "ikSCsolver", name = fingers[1] + "_" + side + "_end_ikHandle", sj = "rig_ik_" + fingers[1] + "_03_" + side, ee = tipJoint)[0]
|
|
cmds.setAttr(ikNodes + ".v", 0)
|
|
|
|
cmds.parent(ikTipNodes, ikNodes)
|
|
|
|
#create a pole vector locator and position it
|
|
poleVector = cmds.spaceLocator(name = fingers[1] + "_" + side + "_poleVector")[0]
|
|
constraint = cmds.parentConstraint("rig_ik_" + fingers[1] + "_02_" + side, poleVector)[0]
|
|
cmds.delete(constraint)
|
|
#color the control
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
cmds.setAttr(poleVector + ".overrideEnabled", 1)
|
|
cmds.setAttr(poleVector + ".overrideColor", color)
|
|
|
|
#create a pole vector group
|
|
pvGrp = cmds.group(empty = True, name = poleVector + "_grp")
|
|
constraint = cmds.parentConstraint(poleVector, pvGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#parent to the joint, and move out away from finger
|
|
cmds.parent(poleVector, "rig_ik_" + fingers[1] + "_02_" + side)
|
|
|
|
if side == "l":
|
|
cmds.setAttr(poleVector + ".ty", -20 * scaleFactor)
|
|
|
|
else:
|
|
cmds.setAttr(poleVector + ".ty", 20 * scaleFactor)
|
|
|
|
cmds.makeIdentity(poleVector, t =1, r =1, s = 1, apply = True)
|
|
cmds.parent(poleVector, pvGrp, absolute = True)
|
|
cmds.makeIdentity(poleVector, t =1, r =1, s = 1, apply = True)
|
|
|
|
#lock pole vector attrs
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
if attr == ".v":
|
|
cmds.setAttr(poleVector + attr, keyable = False)
|
|
|
|
else:
|
|
cmds.setAttr(poleVector + attr, lock = True, keyable = False)
|
|
|
|
|
|
#create the IK finger controls
|
|
ctrlName = fingers[1] + "_" + side + "_ik_anim"
|
|
control = self.createControl("circle", 3, ctrlName)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
ikCtrls.append(control)
|
|
|
|
#position control
|
|
constraint = cmds.parentConstraint(tipJoint, control)[0]
|
|
grpConstraint = cmds.parentConstraint(tipJoint, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#parent control to grp
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".ry", -90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(ikNodes, control)
|
|
|
|
#setup the pole vector constraint and add the locator to the poleVectorLocs list
|
|
cmds.poleVectorConstraint(poleVector, ikNodes)
|
|
poleVectorLocs.append(pvGrp)
|
|
|
|
#add attr to show pole vector control
|
|
cmds.select(control)
|
|
cmds.addAttr(longName= ( "poleVectorVis" ), defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
cmds.connectAttr(control + ".poleVectorVis", poleVector + ".v")
|
|
|
|
#create a tip locator with finger mode attrs
|
|
fingerModeCtrl = cmds.spaceLocator(name = fingers[1] + "_finger_" + side + "_mode_anim")[0]
|
|
fingerModeCtrlGrp = cmds.group(empty = True, name = fingers[1] + "_finger_" + side + "_mode_grp")
|
|
modeGrps.append(fingerModeCtrlGrp)
|
|
cmds.setAttr(fingerModeCtrl + ".v", 0)
|
|
|
|
|
|
constraint = cmds.parentConstraint(tipJoint, fingerModeCtrl)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint(tipJoint, fingerModeCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(fingerModeCtrl, fingerModeCtrlGrp)
|
|
|
|
#lock attrs
|
|
for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz", ".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(fingerModeCtrl + attr, lock = True, keyable = False)
|
|
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
|
|
#scale up the fingerModeCtrl
|
|
shape = cmds.listRelatives(fingerModeCtrl, shapes = True)[0]
|
|
cmds.setAttr(shape + ".localScaleX", 3 * scaleFactor)
|
|
cmds.setAttr(shape + ".localScaleY", 3 * scaleFactor)
|
|
cmds.setAttr(shape + ".localScaleZ", 3 * scaleFactor)
|
|
|
|
|
|
|
|
#constrain the fingerModeCtrlGrp to the driver base knuckle
|
|
if cmds.objExists("driver_" + fingers[1] + "_03_" + side):
|
|
cmds.parentConstraint("driver_" + fingers[1] + "_03_" + side, fingerModeCtrlGrp, mo = True)
|
|
|
|
else:
|
|
if cmds.objExists("driver_" + fingers[1] + "_02_" + side):
|
|
cmds.parentConstraint("driver_" + fingers[1] + "_02_" + side, fingerModeCtrlGrp, mo = True)
|
|
|
|
else:
|
|
if cmds.objExists("driver_" + fingers[1] + "_01_" + side):
|
|
cmds.parentConstraint("driver_" + fingers[1] + "_01_" + side, fingerModeCtrlGrp, mo = True)
|
|
|
|
#color the control
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
cmds.setAttr(fingerModeCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(fingerModeCtrl + ".overrideColor", color)
|
|
|
|
|
|
#add attr for finger mode(fk/ik) on both IK and FK control
|
|
cmds.select(fingerModeCtrl)
|
|
cmds.addAttr(longName= "FK_IK", defaultValue = 0, minValue = 0, maxValue = 1, keyable = True)
|
|
|
|
|
|
|
|
|
|
#take all of the pole vector groups and add them to a master pv group
|
|
masterPvGrp = cmds.group(empty = True, name = "fingers_" + side + "_poleVectors_grp")
|
|
for pv in poleVectorLocs:
|
|
cmds.parent(pv, masterPvGrp, absolute = True)
|
|
|
|
|
|
|
|
#create a global IK control if there are any IK fingers
|
|
if ikCtrls:
|
|
ctrlName = side + "_global_ik_anim"
|
|
control = self.createControl("square", 20, ctrlName)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
|
|
#position control
|
|
constraint = cmds.pointConstraint(midPiv, control)[0]
|
|
grpConstraint = cmds.pointConstraint(midPiv, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
|
|
#parent control to grp
|
|
cmds.parent(control, ctrlGrp)
|
|
#cmds.setAttr(control + ".rx", -90)
|
|
|
|
#freeze rots
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#translate down in y 13
|
|
cmds.setAttr(control + ".tz", -13)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.parent(control, world = True)
|
|
constraint = cmds.pointConstraint(control, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#create a space switcher grp
|
|
spaceSwitcherFollow = cmds.duplicate(ctrlGrp, po = True, name = ctrlName + "_space_switcher_follow")[0]
|
|
spaceSwitcher = cmds.duplicate(ctrlGrp, po = True, name = ctrlName + "_space_switcher")[0]
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(ctrlGrp, spaceSwitcher)
|
|
cmds.parent(spaceSwitcherFollow, "ik_wrist_" + side + "_anim")
|
|
|
|
|
|
#parent ik control grps to this global control
|
|
for ctrl in ikCtrls:
|
|
parent = cmds.listRelatives(ctrl, parent = True)[0]
|
|
cmds.parent(parent, control)
|
|
|
|
#parent constrain the master pv group to the global control
|
|
cmds.parentConstraint(control, masterPvGrp, mo = True)
|
|
|
|
#lock attrs
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
#clean up hand rig hierarchy
|
|
jointsGrp = cmds.group(empty = True, name = "hand_fk_joints_grp_" + side)
|
|
handDrivenGrp = cmds.group(empty = True, name = "hand_driven_grp_" + side)
|
|
handDrivenGrpMaster = cmds.group(empty = True, name = "hand_driven_grp_master_" + side)
|
|
fkCtrlGrp = cmds.group(empty = True, name = "fk_finger_controls_" + side + "_grp")
|
|
|
|
constraint = cmds.parentConstraint("ik_wrist_" + side + "_anim", handDrivenGrpMaster)
|
|
cmds.delete(constraint)
|
|
|
|
#create fk hand match node
|
|
fkHandMatchNode = cmds.duplicate(handDrivenGrpMaster, po = True, name = "hand_match_loc_" + side)[0]
|
|
cmds.parent(fkHandMatchNode, handDrivenGrpMaster)
|
|
|
|
#find aim axis of arm chain to determine offset value
|
|
vector1 = cmds.xform("driver_lowerarm_" + side, q = True, ws = True, t = True)
|
|
vector2 = cmds.xform("driver_hand_" + side, q = True, ws = True, t = True)
|
|
aimAxis = self.normalizeSubVector(vector1, vector2)
|
|
|
|
axis = None
|
|
offset = 0
|
|
for item in [ ["X", ".rx"], ["-X", ".rx"], ["Y", ".ry"], ["-Y", ".ry"], ["Z", ".rz"], ["-Z", ".rz"]]:
|
|
if aimAxis == item[0]:
|
|
axis = item[1]
|
|
|
|
if item[0].find("-") == 0:
|
|
offset = 90
|
|
else:
|
|
offset = -90
|
|
|
|
|
|
|
|
|
|
cmds.setAttr(fkHandMatchNode + axis, offset)
|
|
|
|
cmds.parent(handDrivenGrp, handDrivenGrpMaster)
|
|
|
|
for joint in joints:
|
|
cmds.parent(joint, jointsGrp)
|
|
|
|
for control in ctrlGroups:
|
|
parent = cmds.listRelatives(control, parent = True)
|
|
if parent == None:
|
|
cmds.parent(control, fkCtrlGrp)
|
|
|
|
for control in metaJoints:
|
|
cmds.parent(control, handDrivenGrp)
|
|
|
|
for control in fkOrients:
|
|
cmds.parent(control, handDrivenGrp)
|
|
|
|
for joint in ikJoints:
|
|
cmds.parent(joint, handDrivenGrp)
|
|
|
|
|
|
|
|
|
|
#constrain the master grp to the fk and ik hand joints
|
|
fingerSysGrp = cmds.group(empty = True, name = "finger_sys_grp_" + side)
|
|
cmds.parent(fkCtrlGrp, handDrivenGrp)
|
|
cmds.parent([jointsGrp, ikHandlesGrp, masterPvGrp, handDrivenGrpMaster], fingerSysGrp)
|
|
|
|
if len(modeGrps) > 0:
|
|
cmds.parent(modeGrps, fingerSysGrp)
|
|
|
|
|
|
constraint = cmds.parentConstraint(["fk_wrist_" + side + "_anim", "ik_hand_" + side], handDrivenGrpMaster, mo = True)[0]
|
|
|
|
cmds.setAttr("Rig_Settings" + "." + side + "ArmMode", 0)
|
|
cmds.setAttr(constraint + ".fk_wrist_" + side + "_animW0", 1)
|
|
cmds.setAttr(constraint + ".ik_hand_" + side + "W1", 0)
|
|
cmds.setDrivenKeyframe([constraint + ".fk_wrist_" + side + "_animW0", constraint + ".ik_hand_" + side + "W1"], cd = "Rig_Settings" + "." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings" + "." + side + "ArmMode", 1)
|
|
cmds.setAttr(constraint + ".fk_wrist_" + side + "_animW0", 0)
|
|
cmds.setAttr(constraint + ".ik_hand_" + side + "W1", 1)
|
|
cmds.setDrivenKeyframe([constraint + ".fk_wrist_" + side + "_animW0", constraint + ".ik_hand_" + side + "W1"], cd = "Rig_Settings" + "." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
|
|
|
|
#Constrain the driver joints to the fk and ik joints
|
|
for fingers in [numIndexJoints, numMiddleJoints, numRingJoints, numPinkyJoints, numThumbJoints]:
|
|
for i in range(int(fingers[0])):
|
|
|
|
driverJoint = "driver_" + fingers[1] + "_0" + str(i + 1) + "_" + side
|
|
fkJoint = "rig_fk_" + fingers[1] + "_0" + str(i + 1) + "_" + side
|
|
ikJoint = "rig_ik_" + fingers[1] + "_0" + str(i + 1) + "_" + side
|
|
|
|
#set driven keys on constraint
|
|
if cmds.objExists(fingers[1] + "_" + side + "_ik_anim"):
|
|
constraint = cmds.parentConstraint([fkJoint, ikJoint], driverJoint)[0]
|
|
ikCtrl = fingers[1] + "_finger_" + side + "_mode_anim"
|
|
|
|
#set driven keyframes on constraint
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 0)
|
|
cmds.setAttr(constraint + "." + fkJoint + "W0", 1)
|
|
cmds.setAttr(constraint + "." + ikJoint + "W1", 0)
|
|
cmds.setDrivenKeyframe([constraint + "." + fkJoint + "W0", constraint + "." + ikJoint + "W1"], cd = ikCtrl + "." + "FK_IK", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 1)
|
|
cmds.setAttr(constraint + "." + fkJoint + "W0", 0)
|
|
cmds.setAttr(constraint + "." + ikJoint + "W1", 1)
|
|
cmds.setDrivenKeyframe([constraint + "." + fkJoint + "W0", constraint + "." + ikJoint + "W1"], cd = ikCtrl + "." + "FK_IK", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 0)
|
|
|
|
|
|
|
|
#setup driven keys for fk/ik control visibility
|
|
ikCtrl = fingers[1] + "_finger_" + side + "_mode_anim"
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 0)
|
|
cmds.setAttr(fingers[1] + "_finger_fk_ctrl_1_" + side + "_grp.v" , 1)
|
|
cmds.setAttr(fingers[1] + "_" + side + "_ik_anim_grp.v", 0)
|
|
cmds.setDrivenKeyframe([fingers[1] + "_finger_fk_ctrl_1_" + side + "_grp.v", fingers[1] + "_" + side + "_ik_anim_grp.v"], cd = ikCtrl + "." + "FK_IK", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 1)
|
|
cmds.setAttr(fingers[1] + "_finger_fk_ctrl_1_" + side + "_grp.v" , 0)
|
|
cmds.setAttr(fingers[1] + "_" + side + "_ik_anim_grp.v", 1)
|
|
cmds.setDrivenKeyframe([fingers[1] + "_finger_fk_ctrl_1_" + side + "_grp.v", fingers[1] + "_" + side + "_ik_anim_grp.v"], cd = ikCtrl + "." + "FK_IK", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 0)
|
|
|
|
|
|
|
|
else:
|
|
constraint = cmds.parentConstraint([fkJoint], driverJoint)[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#constrain the driver metacarpals(if they exist) to the ik and fk ones
|
|
for metacarpal in [thumbMeta, indexMeta, middleMeta, ringMeta, pinkyMeta]:
|
|
if metacarpal[0] == True:
|
|
driverJoint = "driver_" + metacarpal[1] + "_metacarpal_" + side
|
|
fkJoint = "rig_fk_" + metacarpal[1] + "_metacarpal_" + side
|
|
ikJoint = "rig_ik_" + metacarpal[1] + "_metacarpal_" + side
|
|
|
|
if cmds.objExists(metacarpal[1] + "_" + side + "_ik_anim"):
|
|
constraint = cmds.parentConstraint([fkJoint, ikJoint], driverJoint)[0]
|
|
ikCtrl = metacarpal[1] + "_finger_" + side + "_mode_anim"
|
|
|
|
constraint = cmds.parentConstraint([fkJoint, ikJoint], driverJoint)[0]
|
|
|
|
#set driven keyframes on constraint
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 0)
|
|
cmds.setAttr(constraint + "." + fkJoint + "W0", 1)
|
|
cmds.setAttr(constraint + "." + ikJoint + "W1", 0)
|
|
cmds.setDrivenKeyframe([constraint + "." + fkJoint + "W0", constraint + "." + ikJoint + "W1"], cd = ikCtrl + "." + "FK_IK", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 1)
|
|
cmds.setAttr(constraint + "." + fkJoint + "W0", 0)
|
|
cmds.setAttr(constraint + "." + ikJoint + "W1", 1)
|
|
cmds.setDrivenKeyframe([constraint + "." + fkJoint + "W0", constraint + "." + ikJoint + "W1"], cd = ikCtrl + "." + "FK_IK", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(ikCtrl + "." + "FK_IK", 0)
|
|
|
|
else:
|
|
constraint = cmds.parentConstraint([fkJoint], driverJoint)[0]
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildToes(self):
|
|
|
|
#find out which toe joints need to be rigged
|
|
for side in ["l", "r"]:
|
|
|
|
|
|
#create a list to hold all ctrl groups that are created
|
|
ctrlGroups = []
|
|
ikGrps = []
|
|
joints = []
|
|
|
|
|
|
if cmds.objExists("driver_ball_" + side):
|
|
children = cmds.listRelatives("driver_ball_" + side, children = True, type = 'joint')
|
|
allToes = cmds.listRelatives("driver_ball_" + side, allDescendents = True, type = 'joint')
|
|
|
|
#find out how many toe joints we have for each toe
|
|
bigToeMeta = [False, None]
|
|
indexMeta = [False, None]
|
|
middleMeta = [False, None]
|
|
ringMeta = [False, None]
|
|
pinkyMeta = [False, None]
|
|
numBigToes = 0
|
|
numIndexToes = [0, "index"]
|
|
numMiddleToes = [0, "middle"]
|
|
numRingToes = [0, "ring"]
|
|
numPinkyToes = [0, "pinky"]
|
|
|
|
if allToes:
|
|
for toe in allToes:
|
|
#find if metatarsals exist
|
|
if toe.find("meta") != -1:
|
|
if toe.partition("driver_")[2].find("bigtoe") == 0:
|
|
bigToeMeta = [True, "bigtoe"]
|
|
if toe.partition("driver_")[2].find("index") == 0:
|
|
indexMeta = [True, "index"]
|
|
if toe.partition("driver_")[2].find("middle") == 0:
|
|
middleMeta = [True, "middle"]
|
|
if toe.partition("driver_")[2].find("ring") == 0:
|
|
ringMeta = [True, "ring"]
|
|
if toe.partition("driver_")[2].find("pinky") == 0:
|
|
pinkyMeta = [True, "pinky"]
|
|
|
|
#get num toes -meta
|
|
if toe.partition("driver_")[2].find("bigtoe") == 0:
|
|
numBigToes += 1
|
|
if toe.partition("driver_")[2].find("index") == 0:
|
|
numIndexToes[0] += 1
|
|
if toe.partition("driver_")[2].find("middle") == 0:
|
|
numMiddleToes[0] += 1
|
|
if toe.partition("driver_")[2].find("ring") == 0:
|
|
numRingToes[0] += 1
|
|
if toe.partition("driver_")[2].find("pinky") == 0:
|
|
numPinkyToes[0] += 1
|
|
|
|
|
|
#subtract metatarsals (only if they exist!)
|
|
if bigToeMeta[0] == True:
|
|
numBigToes -= 1
|
|
if indexMeta[0] == True:
|
|
numIndexToes[0] -= 1
|
|
if middleMeta[0] == True:
|
|
numMiddleToes[0] -= 1
|
|
if ringMeta[0] == True:
|
|
numRingToes[0] -= 1
|
|
if pinkyMeta[0] == True:
|
|
numPinkyToes[0] -= 1
|
|
|
|
|
|
|
|
|
|
#duplicate the driver joints to be used as the rig joints
|
|
if children:
|
|
for child in children:
|
|
dupeChildNodes = cmds.duplicate(child, name = "temp")
|
|
|
|
#parent root joint of each toe to world if not already child of world
|
|
parent = cmds.listRelatives(dupeChildNodes[0], parent = True)[0]
|
|
if parent != None:
|
|
cmds.parent(dupeChildNodes[0], world = True)
|
|
|
|
#rename duped joints
|
|
for node in dupeChildNodes:
|
|
if node == "temp":
|
|
niceName = child.partition("driver_")[2]
|
|
joint = cmds.rename(node, "rig_" + niceName)
|
|
joints.append(joint)
|
|
|
|
else:
|
|
niceName = node.partition("driver_")[2]
|
|
cmds.rename("rig_*|" + node, "rig_" + niceName)
|
|
|
|
|
|
|
|
|
|
#if the metacarpal toes exist, create a control for them
|
|
for meta in [bigToeMeta, indexMeta, middleMeta, ringMeta, pinkyMeta]:
|
|
if meta[0] == True:
|
|
#create the control object for the metacarpal
|
|
ctrlName = meta[1]
|
|
ctrlName = ctrlName + "_metatarsal_ctrl_" + side
|
|
control = self.createControl("square", 1, ctrlName)
|
|
|
|
constraint = cmds.parentConstraint("rig_" + meta[1] + "_metatarsal_" + side, control)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".rz", -90)
|
|
cmds.setAttr(control + ".sz", 15)
|
|
|
|
#create the group node and parent ctrl to it
|
|
ctrlGrp = cmds.group(empty = True, name = ctrlName + "_grp")
|
|
ctrlGroups.append(ctrlGrp)
|
|
constraint = cmds.parentConstraint("rig_" + meta[1] + "_metatarsal_" + side, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.setAttr(control + ".sz", 0)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#parent the rig joint to the control
|
|
cmds.parentConstraint(control, "rig_" + meta[1] + "_metatarsal_" + side, mo = True)
|
|
|
|
|
|
#lock attrs on control that shouldn't be animated
|
|
cmds.setAttr(control + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#color the controls
|
|
if side == "l":
|
|
color = 5
|
|
|
|
else:
|
|
color = 12
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
|
|
|
|
#if the number of toes(aside from metacarpals) is 1 or 2, just create fk controls for each toe and setup hierarchy
|
|
toeControls = []
|
|
for toes in [numIndexToes, numMiddleToes, numRingToes, numPinkyToes]:
|
|
if toes[0] < 3:
|
|
for i in range(int(toes[0])):
|
|
#create an FK control per toe
|
|
ctrlName = toes[1] + "_toe_fk_ctrl_" + str(i + 1) + "_" + side
|
|
control = self.createControl("circle", 3, ctrlName)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
|
|
metaCtrl = toes[1] + "_metatarsal_ctrl_" + side
|
|
|
|
if cmds.objExists(metaCtrl) == False:
|
|
if (i + 1) == 1:
|
|
ctrlGroups.append(ctrlGrp)
|
|
|
|
|
|
toeControls.append(control)
|
|
|
|
#position control
|
|
if i == 0:
|
|
constraint = cmds.parentConstraint("rig_" + toes[1] + "_proximal_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_" + toes[1] + "_proximal_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.parentConstraint(control, "rig_" + toes[1] + "_proximal_phalange_" + side, mo = True)
|
|
|
|
if i == 1:
|
|
constraint = cmds.parentConstraint("rig_" + toes[1] + "_middle_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_" + toes[1] + "_middle_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.parentConstraint(control, "rig_" + toes[1] + "_middle_phalange_" + side, mo = True)
|
|
|
|
if i == 2:
|
|
constraint = cmds.parentConstraint("rig_" + toes[1] + "_distal_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_" + toes[1] + "_distal_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.parentConstraint(control, "rig_" + toes[1] + "_distal_phalange_" + side, mo = True)
|
|
|
|
|
|
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".rz", -90)
|
|
|
|
#duplicate the ctrl group to create the driven group
|
|
drivenGrp = cmds.duplicate(ctrlGrp, parentOnly = True, name = control + "_driven_grp")[0]
|
|
ctrlGroups.append(drivenGrp)
|
|
cmds.parent(drivenGrp, ctrlGrp)
|
|
|
|
#parent control to grp
|
|
cmds.parent(control, drivenGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#if we aren't the root of the toe chain, then parent our ctrlGrp to the previous fk control
|
|
if i != 0:
|
|
cmds.parent(ctrlGrp, ctrlParent)
|
|
|
|
else:
|
|
if cmds.objExists(toes[1] + "_metatarsal_ctrl_" + side):
|
|
cmds.parent(ctrlGrp, toes[1] + "_metatarsal_ctrl_" + side)
|
|
|
|
|
|
ctrlParent = control
|
|
|
|
|
|
#lock attrs on control that shouldn't be animated
|
|
cmds.setAttr(control + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
#if the number of toes(aside from metacarpals) is 3, setup a singular rp IK chain, and a SC IK chain for toe 3 and a newly created toe tip joint
|
|
else:
|
|
|
|
#take the end joint and duplicate it
|
|
tipJoint = cmds.duplicate("rig_" + toes[1] + "_distal_phalange_" + side, parentOnly = True, name = "rig_" + toes[1] + "_tip_" + side)[0]
|
|
cmds.parent(tipJoint, "rig_" + toes[1] + "_distal_phalange_" + side)
|
|
|
|
#move tip joint out a bit
|
|
if side == "r":
|
|
cmds.setAttr(tipJoint + ".tx", -5)
|
|
|
|
else:
|
|
cmds.setAttr(tipJoint + ".tx", 5)
|
|
|
|
|
|
#create RP IK handle from base knuckle to distal
|
|
toeRpIkNodes = cmds.ikHandle(sol = "ikRPsolver", name = toes[1] + "_RP_ikHandle_" + side, sj = "rig_" + toes[1] + "_proximal_phalange_" + side, ee = "rig_" + toes[1] + "_distal_phalange_" + side)
|
|
toeScIkNodes = cmds.ikHandle(sol = "ikSCsolver", name = toes[1] + "_SC_ikHandle_" + side, sj = "rig_" + toes[1] + "_distal_phalange_" + side, ee = tipJoint)
|
|
cmds.setAttr(toeRpIkNodes[0] + ".v", 0)
|
|
cmds.setAttr(toeScIkNodes[0] + ".v", 0)
|
|
|
|
#parent SC IK to RP IK
|
|
cmds.parent(toeScIkNodes[0], toeRpIkNodes[0])
|
|
|
|
#create an IK control
|
|
control = self.createControl("circle", 3, toes[1] + "_ik_ctrl_" + side)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
ikGrps.append(ctrlGrp)
|
|
toeControls.append(control)
|
|
|
|
#position control
|
|
constraint = cmds.parentConstraint("rig_" + toes[1] + "_distal_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_" + toes[1] + "_distal_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
|
|
#create dummy group so IK controls on both sides behave the same (dummy group will have 180 offset if right side)
|
|
dummyGrp = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_dummy")[0]
|
|
spaceSwitcherFollow = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_space_switcher_follow")[0]
|
|
spaceSwitcher = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_space_switcher")[0]
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(dummyGrp, spaceSwitcher)
|
|
cmds.parent(spaceSwitcherFollow, ctrlGrp)
|
|
|
|
#parent ctrl to group
|
|
if side == "r":
|
|
cmds.setAttr(dummyGrp + ".ry", 180)
|
|
|
|
cmds.parent(control, dummyGrp)
|
|
cmds.setAttr(control + ".ry", -90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(toeRpIkNodes[0], control)
|
|
|
|
|
|
|
|
|
|
#lock attrs on control that should not be animated
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#need to do the bigToe separately since it will only have 3 toes max anyway, and bigToesNum == 2 will mean IK setup, and anything less than 2 == FK setup
|
|
|
|
if numBigToes < 2:
|
|
for i in range(int(numBigToes)):
|
|
#create an FK control per toe
|
|
ctrlName = "bigtoe_toe_fk_ctrl_" + str(i + 1) + "_" + side
|
|
control = self.createControl("circle", 8, ctrlName)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
|
|
toeControls.append(control)
|
|
metaCtrl = "bigtoe_metatarsal_ctrl_" + side
|
|
|
|
if cmds.objExists(metaCtrl) == False:
|
|
if (i + 1) == 1:
|
|
ctrlGroups.append(ctrlGrp)
|
|
|
|
#position control
|
|
if i == 0:
|
|
constraint = cmds.parentConstraint("rig_bigtoe_proximal_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_bigtoe_proximal_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.parentConstraint(control, "rig_bigtoe_proximal_phalange_" + side, mo = True)
|
|
|
|
if i == 1:
|
|
constraint = cmds.parentConstraint("rig_bigtoe_distal_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_bigtoe_distal_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
cmds.parentConstraint(control, "rig_bigtoe_distal_phalange_" + side, mo = True)
|
|
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".rz", -90)
|
|
|
|
#duplicate the ctrl group to create the driven group
|
|
drivenGrp = cmds.duplicate(ctrlGrp, parentOnly = True, name = control + "_driven_grp")[0]
|
|
ctrlGroups.append(drivenGrp)
|
|
cmds.parent(drivenGrp, ctrlGrp)
|
|
|
|
#parent control to grp
|
|
cmds.parent(control, drivenGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#if we aren't the root of the toe chain, then parent our ctrlGrp to the previous fk control
|
|
if i != 0:
|
|
cmds.parent(ctrlGrp, ctrlParent)
|
|
|
|
else:
|
|
if cmds.objExists("bigtoe_metatarsal_ctrl_" + side):
|
|
cmds.parent(ctrlGrp, "bigtoe_metatarsal_ctrl_" + side)
|
|
|
|
|
|
|
|
|
|
ctrlParent = control
|
|
|
|
|
|
#lock attrs on control that shouldn't be animated
|
|
cmds.setAttr(control + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
else:
|
|
#take the end joint and duplicate it
|
|
tipJoint = cmds.duplicate("rig_bigtoe_distal_phalange_" + side, parentOnly = True, name = "rig_bigtoe_tip_" + side)[0]
|
|
cmds.parent(tipJoint, "rig_bigtoe_distal_phalange_" + side)
|
|
|
|
#since the toe has 1 less knuckle, we need another tip
|
|
tipJointEnd = cmds.duplicate(tipJoint, parentOnly = True, name = "rig_bigtoe_tip_end_" + side)[0]
|
|
cmds.parent(tipJointEnd, tipJoint)
|
|
|
|
#move tip joint out a bit
|
|
if side == "r":
|
|
cmds.setAttr(tipJoint + ".tx", -5)
|
|
cmds.setAttr(tipJointEnd + ".tx", -5)
|
|
|
|
else:
|
|
cmds.setAttr(tipJoint + ".tx", 5)
|
|
cmds.setAttr(tipJointEnd + ".tx", 5)
|
|
|
|
#set preferred angles on 1rst and 2nd knuckle
|
|
cmds.setAttr("rig_bigtoe_proximal_phalange_" + side + ".preferredAngleZ", 45)
|
|
cmds.setAttr("rig_bigtoe_distal_phalange_" + side + ".preferredAngleZ", -45)
|
|
|
|
#create RP IK handle from base knuckle to distal
|
|
toeRpIkNodes = cmds.ikHandle(sol = "ikRPsolver", name = "bigtoe_RP_ikHandle_" + side, sj = "rig_bigtoe_proximal_phalange_" + side, ee = tipJoint)
|
|
toeScIkNodes = cmds.ikHandle(sol = "ikSCsolver", name = "bigtoe_SC_ikHandle_" + side, sj = "rig_bigtoe_distal_phalange_" + side, ee = tipJointEnd)
|
|
cmds.setAttr(toeRpIkNodes[0] + ".v", 0)
|
|
cmds.setAttr(toeScIkNodes[0] + ".v", 0)
|
|
|
|
#parent SC IK to RP IK
|
|
cmds.parent(toeScIkNodes[0], toeRpIkNodes[0])
|
|
|
|
#create an IK control
|
|
control = self.createControl("circle", 6, "bigtoe_ik_ctrl_" + side)
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
ikGrps.append(ctrlGrp)
|
|
toeControls.append(control)
|
|
|
|
#position control
|
|
constraint = cmds.parentConstraint("rig_bigtoe_distal_phalange_" + side, control)[0]
|
|
grpConstraint = cmds.parentConstraint("rig_bigtoe_distal_phalange_" + side, ctrlGrp)[0]
|
|
cmds.delete([constraint, grpConstraint])
|
|
|
|
#create dummy group so IK controls on both sides behave the same (dummy group will have 180 offset if right side)
|
|
dummyGrp = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_dummy")[0]
|
|
spaceSwitcherFollow = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_space_switcher_follow")[0]
|
|
spaceSwitcher = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_space_switcher")[0]
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(dummyGrp, spaceSwitcher)
|
|
cmds.parent(spaceSwitcherFollow, ctrlGrp)
|
|
|
|
#parent ctrl to group
|
|
if side == "r":
|
|
cmds.setAttr(dummyGrp + ".ry", 180)
|
|
|
|
cmds.parent(control, dummyGrp)
|
|
cmds.setAttr(control + ".ry", -90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(toeRpIkNodes[0], control)
|
|
|
|
|
|
|
|
|
|
#lock attrs on control that should not be animated
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
#setup global control for toes
|
|
|
|
#if toes < 3, rotation based(spread, curl) (grp node above FK control)
|
|
fkControls = []
|
|
ikControls = []
|
|
for control in toeControls:
|
|
|
|
if control.find("fk") != -1:
|
|
fkControls.append(control)
|
|
|
|
if control.find("ik") != -1:
|
|
ikControls.append(control)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#IF AlL TOES ARE IK TOES
|
|
if len(fkControls) == 0:
|
|
#create a control at the tip of the toes that will globally move the IK controls
|
|
|
|
if joints:
|
|
|
|
control = self.createControl("square", 1, "ik_global_ctrl_" + side)
|
|
constraint = cmds.parentConstraint("ikHandle_toe_" + side, control)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".rz", -90)
|
|
cmds.setAttr(control + ".sz", 5)
|
|
|
|
#add a spread attr to the global control
|
|
cmds.select(control)
|
|
cmds.addAttr(longName='spread', defaultValue=0, minValue=0, maxValue=10, keyable = True)
|
|
|
|
|
|
#create the group node and parent ctrl to it
|
|
ctrlGrp = cmds.group(empty = True, name = "ik_global_ctrl_" + side + "_grp")
|
|
ctrlGroups.append(ctrlGrp)
|
|
constraint = cmds.parentConstraint("ikHandle_toe_" + side, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create a space switcher node
|
|
spaceSwitcherFollow = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_space_switcher_follow")[0]
|
|
spaceSwitcher = cmds.duplicate(ctrlGrp, parentOnly = True, name = ctrlGrp + "_space_switcher")[0]
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(spaceSwitcherFollow, ctrlGrp)
|
|
|
|
|
|
cmds.parent(control, spaceSwitcher)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.setAttr(control + ".rx", 90)
|
|
cmds.setAttr(control + ".scale", 2.5, 2.5, 2.5, type = 'double3')
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#set the pivot to be at the base of the toes
|
|
pivPos = cmds.xform("jointmover_knuckle_base_" + side, q = True, ws = True, t = True)
|
|
cmds.xform(control, ws = True, piv = (pivPos[0], pivPos[1], pivPos[2]))
|
|
cmds.xform(ctrlGrp, ws = True, piv = (pivPos[0], pivPos[1], pivPos[2]))
|
|
cmds.xform(spaceSwitcher, ws = True, piv = (pivPos[0], pivPos[1], pivPos[2]))
|
|
|
|
|
|
#lock attrs on control that are not needed to be animated
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
#parent the IK groups to the global grp and also set driven keys for toe spread
|
|
for grp in ikGrps:
|
|
#create a driven group
|
|
group = cmds.group(empty = True, name = grp + "_driven")
|
|
|
|
if grp.find("index") != -1:
|
|
constraint = cmds.parentConstraint("rig_index_proximal_phalange_" + side, group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(group, "index_ik_ctrl_" + side + "_grp_space_switcher")
|
|
cmds.parent("index_ik_ctrl_" + side + "_grp_dummy", group)
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", -9)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
if grp.find("middle") != -1:
|
|
constraint = cmds.parentConstraint("rig_middle_proximal_phalange_" + side, group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(group, "middle_ik_ctrl_" + side + "_grp_space_switcher")
|
|
cmds.parent("middle_ik_ctrl_" + side + "_grp_dummy", group)
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", 9.5)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
|
|
if grp.find("ring") != -1:
|
|
constraint = cmds.parentConstraint("rig_ring_proximal_phalange_" + side, group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(group, "ring_ik_ctrl_" + side + "_grp_space_switcher")
|
|
cmds.parent("ring_ik_ctrl_" + side + "_grp_dummy", group)
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", 17)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
|
|
if grp.find("pinky") != -1:
|
|
constraint = cmds.parentConstraint("rig_pinky_proximal_phalange_" + side, group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(group, "pinky_ik_ctrl_" + side + "_grp_space_switcher")
|
|
cmds.parent("pinky_ik_ctrl_" + side + "_grp_dummy", group)
|
|
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", 32)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
if grp.find("bigtoe") != -1:
|
|
constraint = cmds.parentConstraint("rig_bigtoe_proximal_phalange_" + side, group)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(group, "bigtoe_ik_ctrl_" + side + "_grp_space_switcher")
|
|
cmds.parent("bigtoe_ik_ctrl_" + side + "_grp_dummy", group)
|
|
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", -15)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
cmds.parent(grp, control)
|
|
|
|
#color the control
|
|
if side == "l":
|
|
color = 5
|
|
|
|
else:
|
|
color = 12
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
|
|
|
|
|
|
#IF ALL TOES ARE FK TOES
|
|
if len(ikControls) == 0:
|
|
if joints:
|
|
|
|
#create a control at the tip of the toes that will give the user some handy global controls, like curl, spread, etc.
|
|
control = self.createControl("square", 1, "fk_global_ctrl_" + side)
|
|
constraint = cmds.parentConstraint("ikHandle_toe_" + side, control)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.setAttr(control + ".rz", -90)
|
|
cmds.setAttr(control + ".sz", 5)
|
|
|
|
#create the group node and parent ctrl to it
|
|
ctrlGrp = cmds.group(empty = True, name = "fk_global_ctrl_" + side + "_grp")
|
|
ctrlGroups.append(ctrlGrp)
|
|
constraint = cmds.parentConstraint("ikHandle_toe_" + side, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.setAttr(control + ".rx", 90)
|
|
cmds.setAttr(control + ".scale", 2.5, 2.5, 2.5, type = 'double3')
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#lock attrs on control that are not needed to be animated
|
|
cmds.setAttr(control + ".tx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ty", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".tz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#find all driven fk grps
|
|
drivenGroups = []
|
|
for group in ctrlGroups:
|
|
if group.find("driven") != -1:
|
|
if group.find("fk") != -1:
|
|
drivenGroups.append(group)
|
|
|
|
|
|
|
|
#add a spread attr to the global control
|
|
cmds.select(control)
|
|
cmds.addAttr(longName='spread', defaultValue=0, minValue=0, maxValue=10, keyable = True)
|
|
|
|
#setup driven keys for the fk group nodes
|
|
for group in drivenGroups:
|
|
|
|
|
|
#Curl
|
|
cmds.setAttr(control + ".rz", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rz", -180)
|
|
cmds.setAttr(group + ".rz", -90)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rz", 90)
|
|
cmds.setAttr(group + ".rz", 45)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rz", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rz", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
#Toe Lean
|
|
|
|
#only the base knuckle
|
|
if group.partition("ctrl_")[2].find("1") == 0:
|
|
|
|
cmds.setAttr(control + ".ry", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".ry", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".ry", 45)
|
|
cmds.setAttr(group + ".ry", 45)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".ry", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".ry", -45)
|
|
cmds.setAttr(group + ".ry", -45)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".ry", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".ry", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
#Toe Tilt
|
|
|
|
if group.find("pinky") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", 65)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", -65)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("2") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", -60)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", 60)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("ring") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", 45)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", -45)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("2") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", -30)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", 30)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("middle") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", 50)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", -50)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("2") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", -40)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", 40)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("index") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", 35)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", -35)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
if group.find("2") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", -25)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", 25)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
|
|
|
|
if group.find("bigtoe") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 60)
|
|
cmds.setAttr(group + ".rz", 5)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", -60)
|
|
cmds.setAttr(group + ".rz", -5)
|
|
cmds.setDrivenKeyframe(group + ".rz", cd = control + ".rx", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".rx", 0)
|
|
cmds.setAttr(group + ".rz", 0)
|
|
|
|
#toe spread
|
|
if group.find("bigtoe") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", -15)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
if group.find("index") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", -9)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
if group.find("middle") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", 9.5)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
if group.find("ring") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", 17)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
if group.find("pinky") != -1:
|
|
if group.find("1") != -1:
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 10)
|
|
cmds.setAttr(group + ".ry", 32)
|
|
cmds.setDrivenKeyframe(group + ".ry", cd = control + ".spread", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(control + ".spread", 0)
|
|
cmds.setAttr(group + ".ry", 0)
|
|
|
|
|
|
|
|
if len(ikControls) and len(fkControls) > 0:
|
|
for group in ikGrps:
|
|
ctrlGroups.append(group)
|
|
|
|
|
|
|
|
#need to hook into foot rig, both fk and ik. To do this, we'll group up the toe controls for each side, and parent under the driver ball
|
|
if joints:
|
|
masterGrp = cmds.group(empty = True, name = "toe_rig_" + side + "_grp")
|
|
jointsGrp = cmds.group(empty = True, name = "toe_rig_joints_" + side + "_grp")
|
|
cmds.parent(joints, jointsGrp)
|
|
cmds.parent(jointsGrp, masterGrp)
|
|
for group in ctrlGroups:
|
|
if group.find("driven") == -1:
|
|
cmds.parent(group, masterGrp)
|
|
|
|
cmds.parentConstraint("driver_ball_" + side, masterGrp, mo = True)
|
|
|
|
#parent toe groups to leg sys grp
|
|
cmds.parent(masterGrp, "leg_sys_grp")
|
|
|
|
|
|
#Need to constrain driver joints to rig joints
|
|
for toe in allToes:
|
|
rigToe = toe.partition("driver_")[2]
|
|
rigToe = "rig_" + rigToe
|
|
|
|
cmds.parentConstraint(rigToe, toe)
|
|
|
|
|
|
|
|
#color the controls
|
|
for control in toeControls:
|
|
if side == "l":
|
|
color = 5
|
|
|
|
else:
|
|
color = 12
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
#lastly, hook up toe control visibility to foot control attribute
|
|
cmds.connectAttr("ik_foot_anim_" + side + ".toeCtrlVis", masterGrp + ".v")
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def finishLegs(self):
|
|
ball = False
|
|
|
|
legMasterGrp = cmds.group(empty = True, name = "leg_sys_grp")
|
|
|
|
for side in ["l", "r"]:
|
|
|
|
#organize joints
|
|
legJointGrp = cmds.group(empty = True, name = "leg_joints_grp_" + side)
|
|
constraint = cmds.parentConstraint("driver_thigh_" + side, legJointGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(["fk_leg_thigh_" + side, "ik_leg_thigh_" + side, "fk_thigh_" + side + "_orient_grp"], legJointGrp)
|
|
cmds.parent(legJointGrp, "leg_group_" + side)
|
|
|
|
|
|
|
|
#create invisible legs that will drive the hips
|
|
filePath = self.mayaToolsDir + "/General/ART/invis_legs.mb"
|
|
cmds.select("leg_group_" + side, replace = True)
|
|
cmds.file(filePath, es = True, type = "mayaBinary", force = True)
|
|
|
|
|
|
invisLegNodes = cmds.file(filePath, i = True, returnNewNodes = True, renameAll = True)
|
|
|
|
#clean up import
|
|
for node in invisLegNodes:
|
|
if node.find("body_anim_space") != -1:
|
|
if cmds.objExists(node):
|
|
cmds.delete(node)
|
|
|
|
|
|
#constrain the no flip begin joint to the driver pelvis
|
|
cmds.parentConstraint("driver_pelvis", "noflip_begin_joint_" + side, mo = True)
|
|
cmds.parentConstraint("hip_anim", "invis_legs_leg_group_" + side, mo = True)
|
|
|
|
#connect real knee vector to invis knee vector
|
|
cmds.connectAttr("noflip_pv_loc_" + side + ".translate", ("invis_legs_noflip_pv_loc_" + side + ".translate"))
|
|
cmds.delete("invis_legs_ik_knee_anim_grp_" + side)
|
|
if cmds.objExists("invis_legs_ik_leg_" + side + "_twistMultNode"):
|
|
cmds.delete("invis_legs_ik_leg_" + side + "_twistMultNode")
|
|
|
|
if side == "r":
|
|
cmds.disconnectAttr("invis_legs_ik_foot_anim_" + side + ".knee_twist", "invis_legs_foot_ikHandle_" + side + ".twist")
|
|
cmds.connectAttr("foot_ikHandle_" + side + ".twist", "invis_legs_foot_ikHandle_" + side + ".twist")
|
|
|
|
|
|
#make sure leg orients are good
|
|
tempConstraint = cmds.orientConstraint("fk_thigh_" + side + "_orient_grp", "invis_legs_fk_thigh_" + side + "_orient_grp")[0]
|
|
cmds.delete(tempConstraint)
|
|
|
|
#point constraint invis target loc to real foot control so invis IK goes with real foot. delete invis foot
|
|
cmds.parentConstraint("ik_foot_anim_" + side, ("invis_legs_ik_foot_anim_" + side))
|
|
|
|
#drive invis fk thigh with real
|
|
cmds.connectAttr("fk_thigh_" + side + "_anim.rotate", "invis_legs_fk_thigh_" + side + "_anim.rotate")
|
|
cmds.connectAttr("fk_calf_" + side + "_anim.rotate", "invis_legs_fk_calf_" + side + "_anim.rotate")
|
|
|
|
|
|
#hide invisible legs
|
|
cmds.setAttr("invis_legs_leg_group_" + side + ".v", 0)
|
|
parent = cmds.listRelatives("invis_legs_leg_group_" + side, parent = True)
|
|
cmds.parent("invis_legs_leg_group_" + side, "leg_group_" + side)
|
|
|
|
if parent:
|
|
cmds.delete(parent)
|
|
|
|
|
|
#create result joints
|
|
thighJoint = cmds.duplicate("driver_thigh_" + side, name = "result_leg_thigh_" + side, parentOnly = True)[0]
|
|
calfJoint = cmds.duplicate("driver_calf_" + side, name = "result_leg_calf_" + side, parentOnly = True)[0]
|
|
footJoint = cmds.duplicate("driver_foot_" + side, name = "result_leg_foot_" + side, parentOnly = True)[0]
|
|
|
|
if cmds.objExists("driver_ball_" + side):
|
|
ball = True
|
|
ballJoint = cmds.duplicate("driver_ball_" + side, name = "result_leg_ball_" + side, parentOnly = True)[0]
|
|
|
|
for joint in [thighJoint, calfJoint, footJoint]:
|
|
cmds.parent(joint, world = True)
|
|
|
|
if ball:
|
|
cmds.parent(ballJoint, world = True)
|
|
|
|
|
|
cmds.parent(footJoint, calfJoint)
|
|
cmds.parent(calfJoint, thighJoint)
|
|
|
|
if ball:
|
|
cmds.parent(ballJoint, footJoint)
|
|
|
|
cmds.makeIdentity(thighJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
|
|
|
|
|
|
#create IK fix joints so that all the orients of the leg systems match up
|
|
ikFixThighJoint = cmds.duplicate("driver_thigh_" + side, name = "ikFix_leg_thigh_" + side, parentOnly = True)[0]
|
|
ikFixCalfJoint = cmds.duplicate("driver_calf_" + side, name = "ikFix_leg_calf_" + side, parentOnly = True)[0]
|
|
ikFixFootJoint = cmds.duplicate("driver_foot_" + side, name = "ikFix_leg_foot_" + side, parentOnly = True)[0]
|
|
|
|
if cmds.objExists("driver_ball_" + side):
|
|
ball = True
|
|
ikFixBallJoint = cmds.duplicate("driver_ball_" + side, name = "ikFix_leg_ball_" + side, parentOnly = True)[0]
|
|
|
|
for joint in [ikFixThighJoint, ikFixCalfJoint, ikFixFootJoint]:
|
|
cmds.parent(joint, world = True)
|
|
|
|
if ball:
|
|
cmds.parent(ikFixBallJoint, world = True)
|
|
|
|
|
|
cmds.parent(ikFixFootJoint, ikFixCalfJoint)
|
|
cmds.parent(ikFixCalfJoint, ikFixThighJoint)
|
|
|
|
if ball:
|
|
cmds.parent(ikFixBallJoint, ikFixFootJoint)
|
|
|
|
cmds.makeIdentity(ikFixThighJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
|
|
cmds.parentConstraint("ik_leg_thigh_" + side, ikFixThighJoint, mo = True)
|
|
cmds.parentConstraint("ik_leg_calf_" + side, ikFixCalfJoint, mo = True)
|
|
cmds.parentConstraint("ik_leg_foot_" + side, ikFixFootJoint, mo = True)
|
|
|
|
|
|
if ball:
|
|
cmds.parentConstraint("ik_leg_ball_" + side, ikFixBallJoint, mo = True)
|
|
|
|
|
|
|
|
|
|
|
|
#constrain result joints to fk and ik joints
|
|
thighConstraint = cmds.parentConstraint(["fk_leg_thigh_" + side, ikFixThighJoint], thighJoint, mo = True)[0]
|
|
calfConstraint = cmds.parentConstraint(["fk_leg_calf_" + side, ikFixCalfJoint], calfJoint, mo = True)[0]
|
|
footConstraint = cmds.parentConstraint(["fk_leg_foot_" + side, ikFixFootJoint], footJoint, mo = True)[0]
|
|
|
|
if ball:
|
|
ballConstraint = cmds.parentConstraint(["fk_leg_ball_" + side, ikFixBallJoint], ballJoint, mo = True)[0]
|
|
|
|
#add switch attr
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName=(side + "LegMode"), at = 'enum', en = "fk:ik:", keyable = True)
|
|
|
|
#connect up attr to constraints
|
|
constraints =[thighConstraint, calfConstraint, footConstraint]
|
|
if ball:
|
|
constraints.append(ballConstraint)
|
|
|
|
reverseNode = cmds.shadingNode("reverse", asUtility = True, name = "legSwitcher_reverse_node_" + side)
|
|
cmds.connectAttr("Rig_Settings" + "." + side + "LegMode", reverseNode + ".inputX")
|
|
|
|
|
|
for constraint in constraints:
|
|
targets = cmds.parentConstraint(constraint, q = True, weightAliasList = True)
|
|
cmds.connectAttr("Rig_Settings" + "." + side + "LegMode", constraint + "." + targets[1])
|
|
cmds.connectAttr(reverseNode + ".outputX", constraint + "." + targets[0])
|
|
|
|
|
|
#connect up visibility of controls to leg mode
|
|
cmds.connectAttr("Rig_Settings" + "." + side + "LegMode", "ik_leg_grp_" + side + ".v")
|
|
cmds.connectAttr(reverseNode + ".outputX", "fk_thigh_" + side + "_anim_grp.v")
|
|
|
|
|
|
|
|
#set default to IK
|
|
cmds.setAttr("Rig_Settings" + "." + side + "LegMode", 1)
|
|
|
|
|
|
#constrain driver legs to result legs
|
|
cmds.parentConstraint(thighJoint, "driver_thigh_" + side, mo = True)
|
|
cmds.parentConstraint(calfJoint, "driver_calf_" + side, mo = True)
|
|
cmds.parentConstraint(footJoint, "driver_foot_" + side, mo = True)
|
|
|
|
if ball:
|
|
cmds.parentConstraint(ballJoint, "driver_ball_" + side, mo = True)
|
|
|
|
|
|
#create blend nodes for the scale
|
|
scaleBlendColors_UpLeg = cmds.shadingNode("blendColors", asUtility = True, name = side + "_up_leg_scale_blend")
|
|
cmds.connectAttr("ik_leg_thigh_" + side + ".scale", scaleBlendColors_UpLeg + ".color1")
|
|
cmds.connectAttr("fk_thigh_" + side + "_anim.scale", scaleBlendColors_UpLeg + ".color2")
|
|
cmds.connectAttr(scaleBlendColors_UpLeg + ".output", "driver_thigh_" + side + ".scale")
|
|
|
|
|
|
scaleBlendColors_LoLeg = cmds.shadingNode("blendColors", asUtility = True, name = side + "_lo_leg_scale_blend")
|
|
cmds.connectAttr("ik_leg_calf_" + side + ".scale", scaleBlendColors_LoLeg + ".color1")
|
|
cmds.connectAttr("fk_calf_" + side + "_anim.scale", scaleBlendColors_LoLeg + ".color2")
|
|
cmds.connectAttr(scaleBlendColors_LoLeg + ".output", "driver_calf_" + side + ".scale")
|
|
|
|
scaleBlendColors_Foot = cmds.shadingNode("blendColors", asUtility = True, name = side + "_foot_scale_blend")
|
|
cmds.connectAttr("ik_leg_foot_" + side + ".scale", scaleBlendColors_Foot + ".color1")
|
|
cmds.connectAttr("fk_foot_" + side + "_anim.scale", scaleBlendColors_Foot + ".color2")
|
|
cmds.connectAttr(scaleBlendColors_Foot + ".output", "driver_foot_" + side + ".scale")
|
|
|
|
|
|
|
|
|
|
#set limits
|
|
cmds.select("driver_thigh_" + side)
|
|
cmds.transformLimits(sy = (.05, 2.0), sz = (.05, 2.0), esy = [False, True], esz = [False, True])
|
|
cmds.select("driver_calf_" + side)
|
|
cmds.transformLimits(sy = (.05, 2.0), sz = (.05, 2.0), esy = [False, True], esz = [False, True])
|
|
|
|
|
|
|
|
#clean up legs hiearchy
|
|
cmds.parent([thighJoint, ikFixThighJoint], legJointGrp)
|
|
cmds.setAttr("leg_ctrl_grp_" + side + ".v", 0)
|
|
|
|
|
|
#hide stuff
|
|
cmds.setAttr(ikFixThighJoint + ".v", 0)
|
|
cmds.setAttr("fk_leg_thigh_" + side + ".v", 0)
|
|
|
|
|
|
#CRA CODE CHANGES
|
|
|
|
#Setup Twist Joints if the user selected them
|
|
if side == "l":
|
|
if cmds.getAttr("Skeleton_Settings.leftUpperLegTwist") > 0:
|
|
self.buildThighTwist("l")
|
|
#uplegik.upperIKTwist(6, "_l", "", "", "thigh", "calf", "leg_sys_grp")
|
|
|
|
if cmds.getAttr("Skeleton_Settings.leftLowerLegTwist") > 0:
|
|
self.buildCalfTwist("l")
|
|
|
|
if side == "r":
|
|
if cmds.getAttr("Skeleton_Settings.rightUpperLegTwist") > 0:
|
|
self.buildThighTwist("r")
|
|
#uplegik.upperIKTwist(6, "_r", "", "", "thigh", "calf", "leg_sys_grp")
|
|
|
|
if cmds.getAttr("Skeleton_Settings.rightLowerLegTwist") > 0:
|
|
self.buildCalfTwist("r")
|
|
#CRA CODE CHANGES END
|
|
|
|
#clean up the leg hierarchy. group all leg systems under 1 group
|
|
cmds.parent(["leg_group_l", "leg_group_r"], legMasterGrp)
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildCalfTwist(self, side):
|
|
|
|
|
|
if side == "l":
|
|
color = 5
|
|
|
|
else:
|
|
color = 12
|
|
|
|
|
|
#create our roll group
|
|
rollGrp = cmds.group(empty = True, name = "calf_" + side + "_roll_grp")
|
|
cmds.parentConstraint("driver_calf_" + side, rollGrp)
|
|
|
|
#create our twist joint and twist mod joint
|
|
cmds.select(clear = True)
|
|
twistJoint = cmds.joint(name = "calf_" + side + "_twist_joint")
|
|
cmds.select(clear = True)
|
|
|
|
constraint = cmds.parentConstraint("driver_calf_twist_01_" + side, twistJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistJoint, rollGrp)
|
|
cmds.makeIdentity(twistJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#twist mod joint
|
|
twistMod = cmds.duplicate(twistJoint, po = True, name = "calf_" + side + "_twist_mod")[0]
|
|
cmds.parent(twistMod, twistJoint)
|
|
|
|
|
|
#create the manual twist control
|
|
twistCtrl = self.createControl("circle", 15, "calf_" + side + "_twist_anim")
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
twistCtrlGrp = cmds.group(empty = True, name = "calf_" + side + "_twist_anim_grp")
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, twistCtrlGrp)
|
|
cmds.parent(twistCtrlGrp, twistMod)
|
|
cmds.makeIdentity(twistCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
for attr in [".sx", ".sy", ".sz"]:
|
|
cmds.setAttr(twistCtrl + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
|
|
#add attr on clavicle anim for manual twist control visibility
|
|
cmds.select("hip_anim")
|
|
cmds.addAttr(longName=(side + "CalfTwistCtrlVis"), at = 'bool', dv = 0, keyable = True)
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistCtrl + ".v")
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistMod + ".v")
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistJoint + ".v")
|
|
cmds.setAttr(twistMod + ".radius", .01)
|
|
cmds.setAttr(twistJoint + ".radius", .01)
|
|
|
|
|
|
#setup a simple relationship of foot rotateX value into mult node. input2X is driven by an attr on rig settings for twist amt(default is .5). Output into twist joint
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "calf_twist_" + side + "_mult_node")
|
|
|
|
#add attr to rig settings
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "CalfTwistAmount" ), defaultValue=.5, minValue=0, maxValue=1, keyable = True)
|
|
|
|
|
|
#connect output of driver hand into input1x
|
|
cmds.connectAttr("driver_foot_" + side + ".rx", twistMultNode + ".input1X")
|
|
|
|
#connect attr into input2x
|
|
cmds.connectAttr("Rig_Settings." + side + "CalfTwistAmount", twistMultNode + ".input2X")
|
|
|
|
#connect output into driver calf twist
|
|
cmds.connectAttr(twistMultNode + ".outputX", twistJoint + ".rx")
|
|
|
|
#constrain driver joint to twist joint
|
|
cmds.parentConstraint(twistCtrl, "driver_calf_twist_01_" + side, mo = True)
|
|
|
|
|
|
#if there is more than 1 roll bone, set those up now:
|
|
if side == "l":
|
|
sideName = "left"
|
|
else:
|
|
sideName = "right"
|
|
|
|
data = cmds.getAttr("SkeletonSettings_Cache." + sideName + "LegOptions_numCalfTwistBones")
|
|
numRolls = ast.literal_eval(data)[0]
|
|
|
|
|
|
if numRolls > 1:
|
|
for i in range(int(numRolls)):
|
|
|
|
if i == 1:
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "CalfTwistAmount", .75)
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "CalfTwist2Amount" ), defaultValue=.5, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#create the manual twist control setup
|
|
twistMod = cmds.duplicate("driver_calf_twist_0" + str(i + 1) + "_" + side , po = True, name = "calf_" + side + "_twist2_mod")[0]
|
|
cmds.parent(twistMod, rollGrp)
|
|
|
|
|
|
#create the manual twist control
|
|
twistCtrl = self.createControl("circle", 15, "calf_" + side + "_twist2_anim")
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
twistCtrlGrp = cmds.group(empty = True, name = "calf_" + side + "_twist2_anim_grp")
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, twistCtrlGrp)
|
|
cmds.parent(twistCtrlGrp, twistMod)
|
|
cmds.makeIdentity(twistCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistCtrl + ".v")
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistMod + ".v")
|
|
for attr in [".sx", ".sy", ".sz"]:
|
|
cmds.setAttr(twistCtrl + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
|
|
#drive the twist joint
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "calf_twist_2_" + side + "_mult_node")
|
|
cmds.connectAttr("driver_calf_twist_01_" + side + ".rx", twistMultNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + side + "CalfTwist2Amount", twistMultNode + ".input2X")
|
|
cmds.connectAttr(twistMultNode + ".outputX", twistCtrlGrp + ".rx")
|
|
cmds.parentConstraint(twistCtrl, "driver_calf_twist_0" + str(i + 1) + "_" + side, mo = True)
|
|
|
|
|
|
|
|
|
|
if i == 2:
|
|
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "CalfTwist3Amount" ), defaultValue=.25, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#create the manual twist control setup
|
|
twistMod = cmds.duplicate("driver_calf_twist_0" + str(i + 1) + "_" + side , po = True, name = "calf_" + side + "_twist3_mod")[0]
|
|
cmds.parent(twistMod, rollGrp)
|
|
|
|
|
|
#create the manual twist control
|
|
twistCtrl = self.createControl("circle", 15, "calf_" + side + "_twist3_anim")
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
twistCtrlGrp = cmds.group(empty = True, name = "calf_" + side + "_twist3_anim_grp")
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, twistCtrlGrp)
|
|
cmds.parent(twistCtrlGrp, twistMod)
|
|
cmds.makeIdentity(twistCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistCtrl + ".v")
|
|
cmds.connectAttr("hip_anim." + side + "CalfTwistCtrlVis", twistMod + ".v")
|
|
for attr in [".sx", ".sy", ".sz"]:
|
|
cmds.setAttr(twistCtrl + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
|
|
#drive the twist joint
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "calf_twist_3_" + side + "_mult_node")
|
|
cmds.connectAttr("driver_calf_twist_01_" + side + ".rx", twistMultNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + side + "CalfTwist3Amount", twistMultNode + ".input2X")
|
|
cmds.connectAttr(twistMultNode + ".outputX", twistCtrlGrp + ".rx")
|
|
cmds.parentConstraint(twistCtrl, "driver_calf_twist_0" + str(i + 1) + "_" + side, mo = True)
|
|
|
|
|
|
|
|
#clean up hierarchy
|
|
cmds.parent(rollGrp, "leg_group_" + side)
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildForearmTwist(self, side):
|
|
|
|
if side == "l":
|
|
color = 5
|
|
|
|
else:
|
|
color = 12
|
|
|
|
|
|
#create our roll group
|
|
rollGrp = cmds.group(empty = True, name = "lowerarm_" + side + "_roll_grp")
|
|
cmds.parentConstraint("driver_lowerarm_" + side, rollGrp)
|
|
|
|
#create our twist joint and twist mod joint
|
|
cmds.select(clear = True)
|
|
twistJoint = cmds.joint(name = "lowerarm_" + side + "_twist_joint")
|
|
cmds.select(clear = True)
|
|
|
|
constraint = cmds.parentConstraint("driver_lowerarm_twist_01_" + side, twistJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistJoint, rollGrp)
|
|
|
|
#twist mod joint
|
|
twistMod = cmds.duplicate(twistJoint, po = True, name = "lowerarm_" + side + "_twist_mod")[0]
|
|
cmds.parent(twistMod, twistJoint)
|
|
|
|
|
|
#create the manual twist control
|
|
twistCtrl = self.createControl("circle", 15, "lowerarm_" + side + "_twist_anim")
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
twistCtrlGrp = cmds.group(empty = True, name = "lowerarm_" + side + "_twist_anim_grp")
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, twistCtrlGrp)
|
|
cmds.parent(twistCtrlGrp, twistMod)
|
|
cmds.makeIdentity(twistCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
for attr in [".sx", ".sy", ".sz"]:
|
|
cmds.setAttr(twistCtrl + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
|
|
#add attr on clavicle anim for manual twist control visibility
|
|
cmds.select("clavicle_" + side + "_anim")
|
|
cmds.addAttr(longName=("twistCtrlVisLower"), at = 'bool', dv = 0, keyable = True)
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistCtrl + ".v")
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistMod + ".v")
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistJoint + ".v")
|
|
cmds.setAttr(twistMod + ".radius", .01)
|
|
cmds.setAttr(twistJoint + ".radius", .01)
|
|
|
|
|
|
#setup a simple relationship of foot rotateX value into mult node. input2X is driven by an attr on rig settings for twist amt(default is .5). Output into twist joint
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "forearm_twist_" + side + "_mult_node")
|
|
|
|
#add attr to rig settings
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "ForearmTwistAmount" ), defaultValue=.5, minValue=0, maxValue=1, keyable = True)
|
|
|
|
|
|
#connect output of driver hand into input1x
|
|
cmds.connectAttr("driver_hand_" + side + ".rx", twistMultNode + ".input1X")
|
|
|
|
#connect attr into input2x
|
|
cmds.connectAttr("Rig_Settings." + side + "ForearmTwistAmount", twistMultNode + ".input2X")
|
|
|
|
#connect output into driver calf twist
|
|
cmds.connectAttr(twistMultNode + ".outputX", twistJoint + ".rx")
|
|
|
|
#constrain driver joint to twist joint
|
|
cmds.parentConstraint(twistCtrl, "driver_lowerarm_twist_01_" + side, mo = True)
|
|
|
|
|
|
#if there is more than 1 roll bone, set those up now:
|
|
if side == "l":
|
|
sideName = "left"
|
|
else:
|
|
sideName = "right"
|
|
|
|
data = cmds.getAttr("SkeletonSettings_Cache." + sideName + "ArmOptions_numLowArmTwistBones")
|
|
numRolls = ast.literal_eval(data)[0]
|
|
|
|
|
|
if numRolls > 1:
|
|
for i in range(int(numRolls)):
|
|
|
|
if i == 1:
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ForearmTwistAmount", .75)
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "ForearmTwist2Amount" ), defaultValue=.5, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#create the manual twist control setup
|
|
twistMod = cmds.duplicate("driver_lowerarm_twist_0" + str(i + 1) + "_" + side , po = True, name = "lowerarm_" + side + "_twist2_mod")[0]
|
|
cmds.parent(twistMod, rollGrp)
|
|
|
|
|
|
#create the manual twist control
|
|
twistCtrl = self.createControl("circle", 15, "lowerarm_" + side + "_twist2_anim")
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
twistCtrlGrp = cmds.group(empty = True, name = "lowerarm_" + side + "_twist2_anim_grp")
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, twistCtrlGrp)
|
|
cmds.parent(twistCtrlGrp, twistMod)
|
|
cmds.makeIdentity(twistCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistCtrl + ".v")
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistMod + ".v")
|
|
for attr in [".sx", ".sy", ".sz"]:
|
|
cmds.setAttr(twistCtrl + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
|
|
#drive the twist joint
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "forearm_twist_2_" + side + "_mult_node")
|
|
cmds.connectAttr("driver_lowerarm_twist_01_" + side + ".rx", twistMultNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + side + "ForearmTwist2Amount", twistMultNode + ".input2X")
|
|
cmds.connectAttr(twistMultNode + ".outputX", twistCtrlGrp + ".rx")
|
|
cmds.parentConstraint(twistCtrl, "driver_lowerarm_twist_0" + str(i + 1) + "_" + side, mo = True)
|
|
|
|
|
|
|
|
|
|
if i == 2:
|
|
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "ForearmTwist3Amount" ), defaultValue=.25, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#create the manual twist control setup
|
|
twistMod = cmds.duplicate("driver_lowerarm_twist_0" + str(i + 1) + "_" + side , po = True, name = "lowerarm_" + side + "_twist3_mod")[0]
|
|
cmds.parent(twistMod, rollGrp)
|
|
|
|
|
|
#create the manual twist control
|
|
twistCtrl = self.createControl("circle", 15, "lowerarm_" + side + "_twist3_anim")
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
twistCtrlGrp = cmds.group(empty = True, name = "lowerarm_" + side + "_twist3_anim_grp")
|
|
constraint = cmds.parentConstraint(twistMod, twistCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, twistCtrlGrp)
|
|
cmds.parent(twistCtrlGrp, twistMod)
|
|
cmds.makeIdentity(twistCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistCtrl + ".v")
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVisLower", twistMod + ".v")
|
|
for attr in [".sx", ".sy", ".sz"]:
|
|
cmds.setAttr(twistCtrl + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
|
|
#drive the twist joint
|
|
twistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "forearm_twist_3_" + side + "_mult_node")
|
|
cmds.connectAttr("driver_lowerarm_twist_01_" + side + ".rx", twistMultNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + side + "ForearmTwist3Amount", twistMultNode + ".input2X")
|
|
cmds.connectAttr(twistMultNode + ".outputX", twistCtrlGrp + ".rx")
|
|
cmds.parentConstraint(twistCtrl, "driver_lowerarm_twist_0" + str(i + 1) + "_" + side, mo = True)
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildArmRoll(self, side):
|
|
|
|
if side == "l":
|
|
color = 5
|
|
sideName = "left"
|
|
|
|
else:
|
|
color = 12
|
|
sideName = "right"
|
|
|
|
|
|
#get number of roll bones
|
|
data = cmds.getAttr("SkeletonSettings_Cache." + sideName + "ArmOptions_numUpArmTwistBones")
|
|
numRolls = ast.literal_eval(data)[0]
|
|
|
|
|
|
#create a nurbs plane for our ribbon
|
|
ribbon = cmds.nurbsPlane(ax = [0,0,1], lr = numRolls, width = 10, d = 3, u = 1, v = numRolls, ch = True, name = "upperarm_twist_ribbon_" + side)[0]
|
|
|
|
#rebuild the ribbon with 1 U span
|
|
ribbon = cmds.rebuildSurface(ribbon, su = 1, du = 1, sv = numRolls, dv = 1, ch = 1)[0]
|
|
cmds.setAttr(ribbon + ".rz", -90)
|
|
cmds.makeIdentity(ribbon, apply = True, t = 1, r = 1, s = 1)
|
|
|
|
#create 2 temporary skin joints
|
|
moveVal = 0
|
|
for i in range(numRolls - 1):
|
|
moveVal += 10
|
|
|
|
cmds.select(clear = True)
|
|
topSkinJoint = cmds.joint(name = "top_skinJoint_temp")
|
|
cmds.move(moveVal, 0, 0, r = True, os = True, wd = True)
|
|
cmds.select(clear = True)
|
|
|
|
cmds.select(clear = True)
|
|
bottomSkinJoint = cmds.joint(name = "bottom_skinJoint_temp")
|
|
cmds.move(moveVal * -1, 0, 0, r = True, os = True, wd = True)
|
|
cmds.select(clear = True)
|
|
|
|
|
|
#skin ribbon
|
|
cmds.select([ribbon, topSkinJoint, bottomSkinJoint])
|
|
skin = cmds.skinCluster(tsb = True, mi = 2, omi = True, dr = 5, sm = 0)
|
|
|
|
|
|
#position the joints, thus moving the ribbon
|
|
constraint = cmds.parentConstraint("driver_upperarm_" + side, topSkinJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint("driver_lowerarm_" + side, bottomSkinJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#delete ribbon history and skin joints
|
|
cmds.delete(ribbon, ch = True)
|
|
cmds.delete([bottomSkinJoint, topSkinJoint])
|
|
|
|
|
|
#create hair system on ribbon
|
|
cmds.select(ribbon)
|
|
mel.eval("createHair 1 3 10 0 0 0 0 5 0 2 1 1;")
|
|
|
|
|
|
#figure out which follicles created represent which areas on the ribbon
|
|
hairs = cmds.ls(type = "hairSystem")
|
|
|
|
if len(hairs) > 0:
|
|
hairSys = hairs[0]
|
|
parent = cmds.listRelatives(hairs[0], parent = True)[0]
|
|
hairSys = cmds.rename(parent, "upperarm_twist_" + side + "_hairSys")
|
|
|
|
follicles = cmds.listConnections(hairSys + "Shape", type = "follicle")
|
|
follicles = set(follicles)
|
|
hairFollicles = follicles
|
|
|
|
|
|
|
|
#delete outputCurves
|
|
cmds.delete(parent + "OutputCurves")
|
|
|
|
|
|
#create a joint per follicle
|
|
for follicle in hairFollicles:
|
|
cmds.select(clear = True)
|
|
joint = cmds.joint(name = follicle + "_joint")
|
|
cmds.select(clear = True)
|
|
constraint = cmds.parentConstraint(follicle, joint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(joint, follicle)
|
|
cmds.makeIdentity(joint, apply = True, t = 0, r = 1, s = 0)
|
|
|
|
|
|
|
|
#create the skin joints (final)
|
|
skinJoints = []
|
|
for i in range(numRolls + 1):
|
|
cmds.select(clear = True)
|
|
skinJoint = cmds.joint(name = "skin_upperarm_twist_joint_" + side + str(i))
|
|
cmds.select(clear = True)
|
|
skinJoints.append(skinJoint)
|
|
|
|
for i in range(numRolls):
|
|
constraint = cmds.parentConstraint("driver_upperarm_twist_0" + str(i + 1) + "_" + side, "skin_upperarm_twist_joint_" + side + str(i))[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint("driver_lowerarm_" + side, skinJoint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
|
|
#create our manual control curves
|
|
x = 1
|
|
groups = []
|
|
for joint in skinJoints:
|
|
|
|
if joint != skinJoints[-1]:
|
|
if joint == skinJoints[0]:
|
|
name = "upperarm_" + side + "_twist_anim_grp"
|
|
else:
|
|
name = "upperarm_" + side + "_twist" + str(x) + "_anim_grp"
|
|
|
|
group = cmds.group(empty = True, name = name)
|
|
groups.append(group)
|
|
constraint = cmds.parentConstraint(joint, group)[0]
|
|
cmds.delete(constraint)
|
|
x = x + 1
|
|
|
|
for i in range(int(len(groups))):
|
|
name = groups[i].partition("_grp")[0]
|
|
twistCtrl = self.createControl("circle", 20, name)
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(groups[i], twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(twistCtrl, groups[i])
|
|
cmds.parent(skinJoints[i], twistCtrl)
|
|
cmds.makeIdentity(skinJoints[i], apply = True, t = 0, r = 1, s = 0)
|
|
|
|
#clean up control
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
|
|
|
|
#organize groups
|
|
masterGrp = cmds.group(empty = True, name = "upperarm_twist_master_grp_" + side)
|
|
constraint = cmds.parentConstraint("rig_clavicle_" + side, masterGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
rollGrp = cmds.duplicate(masterGrp, name = "upperarm_twist_roll_grp_" + side)[0]
|
|
constraint = cmds.parentConstraint("driver_upperarm_" + side, rollGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(rollGrp, masterGrp)
|
|
|
|
#set rotate order on roll grp (xzy)
|
|
cmds.setAttr(rollGrp + ".rotateOrder", 3)
|
|
|
|
|
|
for group in groups:
|
|
cmds.parent(group, rollGrp)
|
|
|
|
|
|
#skin ribbon to skin joints
|
|
cmds.select(ribbon)
|
|
for joint in skinJoints:
|
|
cmds.select(joint, add = True)
|
|
|
|
skin = cmds.skinCluster(tsb = True, mi = 2, omi = True, dr = 5, sm = 0)
|
|
|
|
|
|
#orient roll grp to both fk/ik arm joints and set driven keys between them
|
|
upArmConstOrient = cmds.orientConstraint(["fk_upperarm_" + side, "ik_upperarm_" + side], rollGrp, mo = True, skip = "x")[0]
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ArmMode", 0)
|
|
cmds.setAttr(upArmConstOrient + "." + "fk_upperarm_" + side + "W0", 1)
|
|
cmds.setAttr(upArmConstOrient + "." + "ik_upperarm_" + side + "W1", 0)
|
|
cmds.setDrivenKeyframe([upArmConstOrient + "." + "fk_upperarm_" + side + "W0", upArmConstOrient + "." + "ik_upperarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ArmMode", 1)
|
|
cmds.setAttr(upArmConstOrient + "." + "fk_upperarm_" + side + "W0", 0)
|
|
cmds.setAttr(upArmConstOrient + "." + "ik_upperarm_" + side + "W1", 1)
|
|
cmds.setDrivenKeyframe([upArmConstOrient + "." + "fk_upperarm_" + side + "W0", upArmConstOrient + "." + "ik_upperarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ArmMode", 0)
|
|
|
|
|
|
#parent end skin joint to masterGrp and orientConstrain twist to driver upper arm
|
|
cmds.parent(skinJoints[-1], rollGrp)
|
|
cmds.orientConstraint("driver_upperarm_" + side, skinJoints[-1], skip = ["y", "z"])
|
|
|
|
|
|
#parentConstraint master roll grp to driver clavicle
|
|
cmds.parentConstraint("driver_clavicle_" + side, masterGrp, mo = True)
|
|
|
|
#hook up driver joints
|
|
hairFollicles = sorted(hairFollicles)
|
|
hairFollicles = hairFollicles[::-1]
|
|
num = 1
|
|
|
|
for i in range(len(hairFollicles)):
|
|
if cmds.objExists("driver_upperarm_twist_0" + str(num) + "_" + side):
|
|
cmds.orientConstraint(skinJoints[i], "driver_upperarm_twist_0" + str(num) + "_" + side)
|
|
cmds.pointConstraint(skinJoints[i], "driver_upperarm_twist_0" + str(num) + "_" + side, mo = True)
|
|
cmds.scaleConstraint(skinJoints[i], "driver_upperarm_twist_0" + str(num) + "_" + side)
|
|
num = num + 1
|
|
|
|
|
|
|
|
|
|
#add attr on clavicle anim for manual twist control visibility
|
|
cmds.select("clavicle_" + side + "_anim")
|
|
cmds.addAttr(longName=("twistCtrlVis"), at = 'bool', dv = 0, keyable = True)
|
|
cmds.connectAttr("clavicle_" + side + "_anim.twistCtrlVis", rollGrp + ".v")
|
|
|
|
|
|
#hook up multiply nodes so that twistAmount values from rig settings affect the ribbon twist
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "UpperarmTwistAmount" ), defaultValue= .9, minValue= 0 , maxValue= 1, keyable = True)
|
|
|
|
|
|
#take twist ammount attr, multiply by -1, and feed into upperarm twist joint 1
|
|
multNodeA = cmds.shadingNode("multiplyDivide", asUtility = True, name = "upperarm_twist_" + side + "_multNodeA")
|
|
cmds.connectAttr("Rig_Settings." + side + "UpperarmTwistAmount", multNodeA+ ".input1X")
|
|
cmds.setAttr(multNodeA + ".input2X", -1)
|
|
|
|
multNodeB = cmds.shadingNode("multiplyDivide", asUtility = True, name = "upperarm_twist_" + side + "_multNodeB")
|
|
cmds.connectAttr(rollGrp + ".rx", multNodeB+ ".input1X")
|
|
cmds.connectAttr(multNodeA + ".outputX", multNodeB + ".input2X")
|
|
cmds.connectAttr(multNodeB + ".outputX", groups[0] + ".rx")
|
|
|
|
|
|
#any twist joints over the initial, setup simply mult nodes for carry down values
|
|
if numRolls > 1:
|
|
for i in range(int(numRolls)):
|
|
if i == 1:
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "UpperarmTwist2Amount" ), defaultValue=.5, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#hook up multiply nodes so that twistAmount values from rig settings affect the ribbon twist
|
|
multNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "upperarm_twist2_" + side + "_multNode")
|
|
blendNode = cmds.shadingNode("blendColors", asUtility = True, name = "upperarm_twist2_" + side + "_multNode")
|
|
|
|
#hook up blendnode to take in fk and ik upperarm rx values
|
|
cmds.connectAttr( "ik_upperarm_" + side + ".rx", blendNode + ".color1R")
|
|
cmds.connectAttr( "fk_upperarm_" + side + ".rx", blendNode + ".color2R")
|
|
|
|
#take output of that and plug into multNode. multiply by the twist ammount attribute value
|
|
cmds.connectAttr(blendNode + ".outputR", multNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + side + "UpperarmTwist2Amount" , multNode + ".input2X")
|
|
cmds.connectAttr(multNode + ".outputX", groups[i] + ".rx")
|
|
|
|
#connect blendNode.blender to rig settings arm mode
|
|
cmds.connectAttr("Rig_Settings." + side + "ArmMode", blendNode + ".blender")
|
|
|
|
|
|
if i == 2:
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= ( side + "UpperarmTwist3Amount" ), defaultValue=.5, minValue=0, maxValue=1, keyable = True)
|
|
|
|
#hook up multiply nodes so that twistAmount values from rig settings affect the ribbon twist
|
|
multNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "upperarm_twist3_" + side + "_multNode")
|
|
blendNode = cmds.shadingNode("blendColors", asUtility = True, name = "upperarm_twist3_" + side + "_multNode")
|
|
|
|
#hook up blendnode to take in fk and ik upperarm rx values
|
|
cmds.connectAttr( "ik_upperarm_" + side + ".rx", blendNode + ".color1R")
|
|
cmds.connectAttr( "fk_upperarm_" + side + ".rx", blendNode + ".color2R")
|
|
|
|
#take output of that and plug into multNode. multiply by the twist ammount attribute value
|
|
cmds.connectAttr(blendNode + ".outputR", multNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + side + "UpperarmTwist3Amount" , multNode + ".input2X")
|
|
cmds.connectAttr(multNode + ".outputX", groups[i] + ".rx")
|
|
|
|
#connect blendNode.blender to rig settings arm mode
|
|
cmds.connectAttr("Rig_Settings." + side + "ArmMode", blendNode + ".blender")
|
|
|
|
|
|
#Group up and parent into rig
|
|
twistGrp = cmds.group(empty = True, name = "upperarm_twist_grp_" + side)
|
|
cmds.parent([ribbon, hairSys, masterGrp], twistGrp)
|
|
|
|
#find follicles grp
|
|
for follicle in hairFollicles:
|
|
folliclesGrp = cmds.listRelatives(follicle, parent = True)
|
|
cmds.parent(folliclesGrp[0], twistGrp)
|
|
|
|
if cmds.objExists("nucleus1"):
|
|
cmds.parent("nucleus1", twistGrp)
|
|
|
|
#turn inherits transforms off
|
|
cmds.setAttr(folliclesGrp[0] + ".inheritsTransform", 0)
|
|
cmds.setAttr(ribbon + ".inheritsTransform", 0)
|
|
|
|
#hide nodes
|
|
for node in [folliclesGrp[0], ribbon, hairSys, skinJoints[0]]:
|
|
cmds.setAttr(node + ".v", 0)
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildThighTwist(self, side):
|
|
|
|
|
|
if side == "l":
|
|
color = 5
|
|
sideName = "left"
|
|
|
|
else:
|
|
color = 12
|
|
sideName = "right"
|
|
|
|
#get the number of roll bones
|
|
data = cmds.getAttr("SkeletonSettings_Cache." + sideName + "LegOptions_numThighTwistBones")
|
|
numRolls = ast.literal_eval(data)[0]
|
|
|
|
#create our manual control curves and groups
|
|
groups = []
|
|
for i in range(numRolls):
|
|
if i == 0:
|
|
grpName = side + "_thigh_twist_01_driven_grp"
|
|
else:
|
|
grpName = side + "_thigh_twist_0" + str(i + 1) + "_driven_grp"
|
|
|
|
group = cmds.group(empty = True, name = grpName)
|
|
groups.append(group)
|
|
constraint = cmds.parentConstraint("driver_thigh_twist_0" + str(i+1) + "_" + side, group)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
|
|
for i in range(int(len(groups))):
|
|
grpName = groups[i].partition("_grp")[0]
|
|
grpName = grpName.replace("driven", "anim")
|
|
|
|
twistCtrl = utils.createControl("circle", 30, grpName)
|
|
cmds.setAttr(twistCtrl + ".ry", -90)
|
|
cmds.makeIdentity(twistCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(groups[i], twistCtrl)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(twistCtrl, groups[i])
|
|
|
|
#clean up control
|
|
cmds.setAttr(twistCtrl + ".v", keyable = False)
|
|
cmds.setAttr(twistCtrl + ".overrideEnabled", 1)
|
|
cmds.setAttr(twistCtrl + ".overrideColor", color)
|
|
|
|
#constrain driver joint to twist joint
|
|
cmds.parentConstraint(twistCtrl, "driver_thigh_twist_0" + str(i+1) + "_" + side, mo = True)
|
|
|
|
|
|
#create ik twist bone chain
|
|
ikTwistUpper = cmds.createNode("joint", name = "thigh_twist_" + side + "_ik")
|
|
ikTwistLower = cmds.createNode("joint", name = "thigh_twist_" + side + "end_ik")
|
|
|
|
cmds.parent(ikTwistLower, ikTwistUpper)
|
|
|
|
#parent twist ik joints under result leg
|
|
cmds.parent(ikTwistUpper, "leg_joints_grp_" + side)
|
|
|
|
|
|
constraint = cmds.parentConstraint("result_leg_thigh_" + side, ikTwistUpper)[0]
|
|
cmds.delete(constraint)
|
|
constraint = cmds.parentConstraint("result_leg_calf_" + side, ikTwistLower)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
#add rp ik to those joints
|
|
twistIK = cmds.ikHandle(sol = "ikRPsolver", name = "thigh_twist_" + side + "_IK", sj = ikTwistUpper, ee = ikTwistLower)[0]
|
|
cmds.parent(twistIK, "result_leg_thigh_" + side)
|
|
|
|
ikWorldPos = cmds.xform(twistIK, q = True, ws = True, t = True)[0]
|
|
if ikWorldPos < 0:
|
|
cmds.setAttr(twistIK + ".twist", 180)
|
|
|
|
#create ik pole vector
|
|
twistVector = cmds.spaceLocator(name = "thight_twist_" + side + "_PoleVector")[0]
|
|
constraint = cmds.parentConstraint("result_leg_thigh_" + side, twistVector)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(twistVector, "result_leg_thigh_" + side)
|
|
|
|
#create pole vector constraint
|
|
cmds.poleVectorConstraint(twistVector, twistIK)
|
|
|
|
|
|
#create roll locator (locator that actually will drive the roll amount)
|
|
rollLoc = cmds.spaceLocator(name = "thigh_twist_" + side + "_Tracker")[0]
|
|
constraint = cmds.parentConstraint("result_leg_thigh_" + side, rollLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(rollLoc, "leg_joints_grp_" + side)
|
|
cmds.makeIdentity(rollLoc, t = 0, r = 1, s = 0, apply = True)
|
|
cmds.orientConstraint("result_leg_thigh_" + side, rollLoc, skip = ["y", "z"])
|
|
|
|
|
|
#Group up and parent into rig
|
|
twistGrp = cmds.group(empty = True, name = "thigh_twist_grp_" + side)
|
|
|
|
|
|
#add twist grp to arm_sys_grp
|
|
cmds.parent(twistGrp, "leg_group_" + side)
|
|
for group in groups:
|
|
grpName = group.replace("driven", "anim")
|
|
animGrp = cmds.group(empty = True, name = grpName)
|
|
constraint = cmds.parentConstraint(group, animGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(group, animGrp)
|
|
cmds.parent(animGrp, twistGrp)
|
|
|
|
#constrain animGrp to driver upper arm
|
|
cmds.parentConstraint("result_leg_thigh_" + side, animGrp, mo = True)
|
|
|
|
|
|
|
|
#hook up multiply divide nodes
|
|
|
|
#first one takes rollLoc rotateX and multiplies it by -1 to get the counter
|
|
counterMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "thigh_twist_" + side + "_counterNode")
|
|
cmds.connectAttr(rollLoc + ".rotateX", counterMultNode + ".input1X")
|
|
cmds.setAttr(counterMultNode + ".input2X", -1)
|
|
|
|
#second one takes the output of the counterMultNode and multiplies it with the twist amount
|
|
for i in range(numRolls):
|
|
attrName = side + "ThighTwist" + str(i + 1) + "Amount"
|
|
grpName = side + "_thigh_twist_0" + str(i + 1) + "_driven_grp"
|
|
|
|
if i == 0:
|
|
cmds.addAttr("Rig_Settings", ln = side + "ThighTwistAmount", dv = 1, keyable = True)
|
|
attrName = side + "ThighTwistAmount"
|
|
grpName = side + "_thigh_twist_01_driven_grp"
|
|
|
|
else:
|
|
if i == 1:
|
|
dv = 0.6
|
|
if i == 2:
|
|
dv = 0.3
|
|
|
|
cmds.addAttr("Rig_Settings", ln = side + "ThighTwist" + str(i + 1) + "Amount", dv = dv, keyable = True)
|
|
|
|
#multNode creation
|
|
rollMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = side + "_thigh_rollNode")
|
|
cmds.connectAttr(counterMultNode + ".outputX", rollMultNode + ".input1X")
|
|
cmds.connectAttr("Rig_Settings." + attrName, rollMultNode + ".input2X")
|
|
|
|
#connect output of roll node to driven group
|
|
cmds.connectAttr(rollMultNode + ".outputX", grpName + ".rotateX")
|
|
|
|
#add attr on rig settings node for manual twist control visibility
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName=(side + "legTwistCtrlVis"), at = 'bool', dv = 0, keyable = True)
|
|
cmds.connectAttr("Rig_Settings." + side + "legTwistCtrlVis", twistGrp + ".v")
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildAutoHips(self):
|
|
|
|
hipWorld = cmds.group(empty = True, name = "auto_hip_world")
|
|
yzRot = cmds.group(empty = True, name = "auto_hip_yz_rot_solver")
|
|
xRot = cmds.group(empty = True, name = "auto_hip_x_rot_solver")
|
|
legSys = cmds.group(empty = True, name = "auto_hip_legs_system")
|
|
switchNode = cmds.spaceLocator(name = "auto_hip_on_off")[0]
|
|
hipRedirect = cmds.spaceLocator(name = "hip_ctrl_redirect")[0]
|
|
|
|
#hide locators
|
|
for node in [switchNode, hipRedirect]:
|
|
shape = cmds.listRelatives(node, children = True)[0]
|
|
try:
|
|
cmds.setAttr(shape + ".v", 0)
|
|
cmds.setAttr(shape + ".v", lock = True)
|
|
except:
|
|
pass
|
|
|
|
for node in [hipWorld, yzRot, xRot, legSys, switchNode, hipRedirect]:
|
|
constraint = cmds.parentConstraint("driver_pelvis", node)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#setup hierarchy
|
|
cmds.parent("hip_anim", hipWorld)
|
|
cmds.parent([yzRot, xRot, legSys], "hip_anim")
|
|
cmds.parent(switchNode, yzRot)
|
|
cmds.parent(hipRedirect, switchNode)
|
|
|
|
|
|
#create the fk knee space locators
|
|
pelvisPos = cmds.xform("driver_pelvis", q = True, t = True, ws = True)
|
|
height = pelvisPos[2]
|
|
|
|
|
|
leftKneeLoc = cmds.spaceLocator(name = "auto_hips_knee_loc_l")[0]
|
|
rightKneeLoc = cmds.spaceLocator(name = "auto_hips_knee_loc_r")[0]
|
|
|
|
constraint = cmds.pointConstraint("ik_leg_calf_l", leftKneeLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.pointConstraint("ik_leg_calf_r", rightKneeLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.makeIdentity([leftKneeLoc, rightKneeLoc], t = 1, r = 1, s = 1, apply = True)
|
|
|
|
leftKneeLocConstraint = cmds.pointConstraint(["invis_legs_ik_leg_calf_l", "invis_legs_fk_calf_l_anim"], leftKneeLoc)[0]
|
|
rightKneeLocConstraint = cmds.pointConstraint(["invis_legs_ik_leg_calf_r","invis_legs_fk_calf_r_anim"], rightKneeLoc)[0]
|
|
|
|
leftTargets = cmds.pointConstraint(leftKneeLocConstraint, q = True, weightAliasList = True)
|
|
rightTargets = cmds.pointConstraint(rightKneeLocConstraint, q = True, weightAliasList = True)
|
|
|
|
cmds.setAttr(leftKneeLocConstraint + "." + leftTargets[1], 0)
|
|
cmds.setAttr(rightKneeLocConstraint + "." + rightTargets[1], 0)
|
|
|
|
|
|
#create the thigh locators for solving x (twist)
|
|
leftThighLoc = cmds.spaceLocator(name = "auto_hips_x_rot_solv_l")[0]
|
|
rightThighLoc = cmds.spaceLocator(name = "auto_hips_x_rot_solv_r")[0]
|
|
|
|
constraint = cmds.pointConstraint("driver_thigh_l", leftThighLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.pointConstraint("driver_thigh_r", rightThighLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.setAttr(leftThighLoc + ".tz", height)
|
|
cmds.setAttr(rightThighLoc + ".tz", height)
|
|
|
|
|
|
#create the x rotation solver joint chain
|
|
cmds.select(clear = True)
|
|
xRotJointStart = cmds.joint(name = "auto_hips_x_rot_solv_joint_start")
|
|
cmds.select(clear = True)
|
|
|
|
constraint = cmds.pointConstraint(leftThighLoc, xRotJointStart)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.orientConstraint("driver_pelvis", xRotJointStart)[0]
|
|
cmds.delete(constraint)
|
|
|
|
xRotJointEnd = cmds.duplicate(xRotJointStart, name = "auto_hips_x_rot_solv_joint_end")[0]
|
|
cmds.parent(xRotJointEnd, xRotJointStart)
|
|
cmds.xform(xRotJointEnd, ws = True, t = (pelvisPos[0], pelvisPos[1], pelvisPos[2]))
|
|
|
|
cmds.makeIdentity(xRotJointStart, r = 1, apply = True)
|
|
cmds.pointConstraint(leftThighLoc, xRotJointStart)
|
|
|
|
xRotIKNodes = cmds.ikHandle(sol = "ikSCsolver", name = "auto_hips_x_rot_solver_ik", sj = xRotJointStart, ee = xRotJointEnd)
|
|
cmds.pointConstraint(rightThighLoc, xRotIKNodes[0])
|
|
|
|
|
|
#hookup x rot solver
|
|
upAxis = self.getUpAxis("hip_anim")
|
|
cmds.connectAttr(xRotJointStart + ".rotate" + upAxis, legSys + ".rotate" + upAxis)
|
|
|
|
#hookup motion of thigh locators
|
|
rotXikHipL = cmds.spaceLocator(name = "auto_hips_ik_x_rot_solv_loc_l")[0]
|
|
rotXikHipR = cmds.spaceLocator(name = "auto_hips_ik_x_rot_solv_loc_r")[0]
|
|
|
|
constraint = cmds.pointConstraint("noflip_pv_loc_l", rotXikHipL)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.pointConstraint("noflip_pv_loc_r", rotXikHipR)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.pointConstraint(leftKneeLoc, leftThighLoc, mo = True, skip = ["x", "z"])
|
|
cmds.pointConstraint(rightKneeLoc, rightThighLoc, mo = True, skip = ["x", "z"])
|
|
|
|
|
|
#create the multiply node for our x rot solver node to halve the results
|
|
xRotMult = cmds.shadingNode("multiplyDivide", name = "auto_hips_x_rot_mult_node", asUtility = True)
|
|
cmds.connectAttr(legSys + ".rotate" + upAxis, xRotMult + ".input1X")
|
|
cmds.setAttr(xRotMult + ".input2X", .5)
|
|
cmds.connectAttr(xRotMult + ".outputX", xRot + ".rotate" + upAxis)
|
|
|
|
|
|
#create the joints for the yz rotations
|
|
cmds.select(clear = True)
|
|
yzRotStartJoint = cmds.joint(name = "auto_hips_yz_rot_solv_joint_start")
|
|
|
|
constraint = cmds.parentConstraint("driver_pelvis", yzRotStartJoint)[0]
|
|
cmds.delete(constraint)
|
|
yzRotEndJoint = cmds.duplicate(yzRotStartJoint, name = "auto_hips_yz_rot_solv_joint_end")[0]
|
|
cmds.parent(yzRotEndJoint, yzRotStartJoint)
|
|
cmds.setAttr(yzRotEndJoint + ".tx", (height/2)* -1)
|
|
|
|
cmds.makeIdentity(yzRotStartJoint, r = 1, apply = True)
|
|
|
|
yzRotikNodes = cmds.ikHandle(sol = "ikRPsolver", name = "auto_hips_yz_rot_solv_ik", sj = yzRotStartJoint, ee = yzRotEndJoint)
|
|
yzRotTargetLoc = cmds.spaceLocator(name = "auto_hips_yz_target_loc")[0]
|
|
constraint = cmds.pointConstraint([leftKneeLoc, rightKneeLoc], yzRotTargetLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.makeIdentity(yzRotTargetLoc, t = 1, apply = True)
|
|
cmds.parent(yzRotikNodes[0], yzRotTargetLoc)
|
|
|
|
|
|
#setup motion for yz solver
|
|
cmds.pointConstraint([leftKneeLoc, rightKneeLoc], yzRotTargetLoc)
|
|
yzSolvConst = cmds.orientConstraint(yzRotStartJoint, yzRot)[0]
|
|
|
|
|
|
#setup distance tools for reducing popping when foot gets close to pelvis
|
|
cmds.select(clear = True)
|
|
yzRotFlipCtrlNodesL = cmds.duplicate("noflip_begin_joint_l", name = "auto_hips_dist_ctrl_begin_joint_l", rc = True)
|
|
yzRotFlipCtrlBeginL = yzRotFlipCtrlNodesL[0]
|
|
yzRotFlipCtrlEndL = cmds.rename(yzRotFlipCtrlNodesL[1], "auto_hips_dist_ctrl_end_joint_l")
|
|
|
|
|
|
#now for the right side
|
|
cmds.select(clear = True)
|
|
yzRotFlipCtrlNodesR = cmds.duplicate("noflip_begin_joint_r", name = "auto_hips_dist_ctrl_begin_joint_r", rc = True)
|
|
yzRotFlipCtrlBeginR = yzRotFlipCtrlNodesR[0]
|
|
yzRotFlipCtrlEndR = cmds.rename(yzRotFlipCtrlNodesR[1], "auto_hips_dist_ctrl_end_joint_r")
|
|
|
|
|
|
#setup the distance mover joint
|
|
distMoverL = cmds.duplicate(yzRotFlipCtrlEndL, name = "distance_mover_joint_l")[0]
|
|
distMoverR = cmds.duplicate(yzRotFlipCtrlEndR, name = "distance_mover_joint_r")[0]
|
|
|
|
cmds.pointConstraint("ik_foot_anim_l", distMoverL, mo = True)
|
|
cmds.pointConstraint("ik_foot_anim_r", distMoverR, mo = True)
|
|
|
|
|
|
#setup system for fixing flipping when foot gets too close to pelvis
|
|
originalLen = cmds.getAttr(yzRotFlipCtrlEndL + ".tz")
|
|
conditionNodeL = cmds.shadingNode("condition", asUtility = True, name = "autoHips_flipFix_condition_l")
|
|
conditionNodeR = cmds.shadingNode("condition", asUtility = True, name = "autoHips_flipFix_condition_r")
|
|
|
|
cmds.setAttr(conditionNodeL + ".secondTerm", originalLen)
|
|
cmds.setAttr(conditionNodeR + ".secondTerm", originalLen)
|
|
|
|
cmds.connectAttr(distMoverL + ".tz", conditionNodeL + ".firstTerm")
|
|
cmds.connectAttr(distMoverR + ".tz", conditionNodeR + ".firstTerm")
|
|
|
|
scaleFactor = self.getScaleFactor()
|
|
|
|
cmds.setAttr(conditionNodeL + ".operation", 2)
|
|
cmds.setAttr(conditionNodeR + ".operation", 2)
|
|
cmds.setAttr(conditionNodeL + ".colorIfFalseR", 0)
|
|
cmds.setAttr(conditionNodeR + ".colorIfFalseR", 0)
|
|
cmds.setAttr(conditionNodeL + ".colorIfTrueR", -60 * scaleFactor)
|
|
cmds.setAttr(conditionNodeR + ".colorIfTrueR", -60 * scaleFactor)
|
|
|
|
cmds.connectAttr(conditionNodeL + ".outColorR", "noflip_aim_soft_grp_l.tz")
|
|
cmds.connectAttr(conditionNodeR + ".outColorR", "noflip_aim_soft_grp_r.tz")
|
|
|
|
|
|
|
|
#hookup the hips to use the x and yz rot solver data
|
|
cmds.connectAttr(xRot + ".rotate" + upAxis, yzSolvConst + ".offset" + upAxis)
|
|
cmds.connectAttr("hip_anim.rotate", hipRedirect + ".rotate")
|
|
|
|
#orient constrain the on/off node to the world control and the yz rot solver
|
|
onOffConstraint = cmds.orientConstraint([hipWorld, yzSolvConst], switchNode)[0]
|
|
|
|
#add auto on/off attr to hip control. hookup connections to constraint
|
|
cmds.select("hip_anim")
|
|
cmds.addAttr(longName='autoHips', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
|
|
orientTargets = cmds.orientConstraint(onOffConstraint, q = True, weightAliasList = True)
|
|
|
|
cmds.connectAttr("hip_anim.autoHips", onOffConstraint + "." + orientTargets[1])
|
|
reverseNode = cmds.shadingNode("reverse", asUtility = True, name = "autoHips_reverse_node_onOff")
|
|
cmds.connectAttr("hip_anim.autoHips", reverseNode + ".inputX")
|
|
cmds.connectAttr(reverseNode + ".outputX", onOffConstraint + "." + orientTargets[0])
|
|
|
|
|
|
|
|
#plug the body anim's rotates into the onOffConstraint's offsets
|
|
|
|
bodyMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "autoHips_body_rotation_fix")
|
|
cmds.connectAttr("body_anim.rotateX", bodyMultNode + ".input1X")
|
|
cmds.connectAttr("body_anim.rotateY", bodyMultNode + ".input1Y")
|
|
cmds.connectAttr("body_anim.rotateZ", bodyMultNode + ".input1Z")
|
|
|
|
cmds.connectAttr("hip_anim.autoHips", bodyMultNode + ".input2X")
|
|
cmds.connectAttr("hip_anim.autoHips", bodyMultNode + ".input2Y")
|
|
cmds.connectAttr("hip_anim.autoHips", bodyMultNode + ".input2Z")
|
|
|
|
#cmds.connectAttr(bodyMultNode + ".outputX", onOffConstraint + ".offsetX")
|
|
#cmds.connectAttr(bodyMultNode + ".outputY", onOffConstraint + ".offsetY")
|
|
#cmds.connectAttr(bodyMultNode + ".outputZ", onOffConstraint + ".offsetZ")
|
|
|
|
#update invisible leg IK joints
|
|
cmds.setToolTo('moveSuperContext')
|
|
cmds.select("invis_legs_ik_leg_thigh_l", hi = True)
|
|
cmds.setToolTo('RotateSuperContext')
|
|
cmds.select(clear = True)
|
|
|
|
|
|
#constrain driver joint to control
|
|
cmds.parentConstraint(hipRedirect, "driver_pelvis", mo = True)
|
|
|
|
#parent hip world to body anim
|
|
cmds.parent(hipWorld, "body_anim")
|
|
|
|
#clean up hierarchy
|
|
autoHipsMasterGrp = cmds.group(empty = True, name = "autoHips_sys_grp")
|
|
cmds.parent([leftKneeLoc, rightKneeLoc, leftThighLoc, rightThighLoc, xRotJointStart, rotXikHipL, rotXikHipR, yzRotStartJoint,xRotIKNodes[0], yzRotTargetLoc], autoHipsMasterGrp)
|
|
|
|
#cosntrain ik leg bones(thighs) to the hip ctrl redirect
|
|
cmds.parentConstraint(hipRedirect, "leg_joints_grp_l", mo = True)
|
|
cmds.parentConstraint(hipRedirect, "leg_joints_grp_r", mo = True)
|
|
|
|
#parent the bottom of the spline ik spine bone to the hip redirect
|
|
if cmds.objExists("spine_splineIK_bottom_joint"):
|
|
cmds.parent("spine_splineIK_bottom_joint", hipRedirect)
|
|
|
|
#hide stuff
|
|
cmds.setAttr("autoHips_sys_grp.v", 0)
|
|
|
|
|
|
#hook up autohips to leg mode
|
|
|
|
reverseNodeL = "legSwitcher_reverse_node_l"
|
|
reverseNodeR = "legSwitcher_reverse_node_r"
|
|
|
|
targets = cmds.pointConstraint(leftKneeLocConstraint, q = True, weightAliasList = True)
|
|
cmds.connectAttr("Rig_Settings" + ".lLegMode", leftKneeLocConstraint + "." + targets[0])
|
|
cmds.connectAttr(reverseNodeL + ".outputX", leftKneeLocConstraint + "." + targets[1])
|
|
|
|
|
|
targets = cmds.pointConstraint(rightKneeLocConstraint, q = True, weightAliasList = True)
|
|
cmds.connectAttr("Rig_Settings" + ".rLegMode", rightKneeLocConstraint + "." + targets[0])
|
|
cmds.connectAttr(reverseNodeR + ".outputX", rightKneeLocConstraint + "." + targets[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def autoSpine(self):
|
|
|
|
numSpineBones = cmds.getAttr("Skeleton_Settings.numSpineBones")
|
|
|
|
if numSpineBones > 2:
|
|
|
|
#drive the mid IK spine control based on what the upper spine control is doing
|
|
|
|
|
|
#drives the ik spine controls based on auto hip attr and hip motion
|
|
yzRotSolver = "auto_hip_yz_rot_solver"
|
|
midDriver = "mid_ik_anim_driver_grp"
|
|
midDriverTop = "mid_ik_anim_translate_driver_grp"
|
|
|
|
|
|
#add auto on/off attr to hip control. hookup connections to constraint
|
|
cmds.select("chest_ik_anim")
|
|
cmds.addAttr(longName='autoSpine', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
cmds.addAttr(longName='rotationInfluence', defaultValue=.25, minValue=0, maxValue=1, keyable = True)
|
|
|
|
topCtrlMultRY = cmds.shadingNode("multiplyDivide", asUtility = True, name = "autoSpine_top_driver_mult_ry")
|
|
topCtrlMultRZ = cmds.shadingNode("multiplyDivide", asUtility = True, name = "autoSpine_top_driver_mult_rz")
|
|
topCtrlMultSwitchRY = cmds.shadingNode("multiplyDivide", asUtility = True, name = "autoSpine_top_mult_switch_ry")
|
|
topCtrlMultSwitchRZ = cmds.shadingNode("multiplyDivide", asUtility = True, name = "autoSpine_top_mult_switch_rz")
|
|
|
|
|
|
#create a node that will track all world space translations and rotations on the chest IK anim
|
|
chestMasterTrackNode = cmds.spaceLocator(name = "chest_ik_track_parent")[0]
|
|
constraint = cmds.parentConstraint("chest_ik_anim", chestMasterTrackNode)[0]
|
|
cmds.delete(constraint)
|
|
|
|
chestTrackNode = cmds.spaceLocator(name = "chest_ik_tracker")[0]
|
|
constraint = cmds.parentConstraint("chest_ik_anim", chestTrackNode)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(chestTrackNode, chestMasterTrackNode)
|
|
cmds.parentConstraint("chest_ik_anim", chestTrackNode)
|
|
|
|
cmds.parent(chestMasterTrackNode, "body_anim")
|
|
|
|
#hide locator
|
|
cmds.setAttr(chestMasterTrackNode + ".v", 0)
|
|
|
|
|
|
|
|
|
|
|
|
#Rotate Y
|
|
cmds.connectAttr(chestTrackNode + ".ry", topCtrlMultRY + ".input1X")
|
|
cmds.connectAttr("chest_ik_anim.rotationInfluence", topCtrlMultRY + ".input2X")
|
|
|
|
cmds.connectAttr(topCtrlMultRY + ".outputX", topCtrlMultSwitchRY + ".input1X")
|
|
cmds.connectAttr("chest_ik_anim.autoSpine", topCtrlMultSwitchRY + ".input2X")
|
|
cmds.connectAttr(topCtrlMultSwitchRY + ".outputX", midDriver + ".tz")
|
|
|
|
|
|
#Rotate Z
|
|
multInverse = cmds.shadingNode("multiplyDivide", asUtility = True, name = "autoSpine_mult_rz_inverse")
|
|
cmds.connectAttr("chest_ik_anim.rotationInfluence", multInverse + ".input1X")
|
|
cmds.setAttr(multInverse + ".input2X", -1)
|
|
|
|
|
|
cmds.connectAttr(chestTrackNode + ".rz", topCtrlMultRZ + ".input1X")
|
|
cmds.connectAttr(multInverse + ".outputX", topCtrlMultRZ + ".input2X")
|
|
|
|
cmds.connectAttr(topCtrlMultRZ + ".outputX", topCtrlMultSwitchRZ + ".input1X")
|
|
cmds.connectAttr("chest_ik_anim.autoSpine", topCtrlMultSwitchRZ + ".input2X")
|
|
cmds.connectAttr(topCtrlMultSwitchRZ + ".outputX", midDriver + ".ty")
|
|
|
|
|
|
#Translate X
|
|
#Chest Control Translate X + Hip Control Translate X / 2 * autpSpine
|
|
autoSpineTXNode = cmds.shadingNode("plusMinusAverage", asUtility = True, name = midDriverTop + "_TX_Avg")
|
|
cmds.setAttr(autoSpineTXNode + ".operation", 3)
|
|
autoSpineTX_MultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = midDriverTop + "_TX_Mult")
|
|
|
|
cmds.connectAttr("chest_ik_anim.translateX", autoSpineTXNode + ".input1D[0]")
|
|
cmds.connectAttr("hip_anim.translateX", autoSpineTXNode + ".input1D[1]")
|
|
cmds.connectAttr(autoSpineTXNode + ".output1D", autoSpineTX_MultNode + ".input1X")
|
|
cmds.connectAttr("chest_ik_anim.autoSpine", autoSpineTX_MultNode + ".input2X")
|
|
cmds.connectAttr(autoSpineTX_MultNode + ".outputX", midDriverTop + ".translateX")
|
|
|
|
|
|
|
|
#Translate Y
|
|
autoSpineTYNode = cmds.shadingNode("plusMinusAverage", asUtility = True, name = midDriverTop + "_TY_Avg")
|
|
cmds.setAttr(autoSpineTYNode + ".operation", 3)
|
|
autoSpineTY_MultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = midDriverTop + "_TY_Mult")
|
|
|
|
cmds.connectAttr(chestTrackNode + ".translateY", autoSpineTYNode + ".input1D[0]")
|
|
cmds.connectAttr("hip_anim.translateY", autoSpineTYNode + ".input1D[1]")
|
|
cmds.connectAttr(autoSpineTYNode + ".output1D", autoSpineTY_MultNode + ".input1X")
|
|
cmds.connectAttr("chest_ik_anim.autoSpine", autoSpineTY_MultNode + ".input2X")
|
|
cmds.connectAttr(autoSpineTY_MultNode + ".outputX", midDriverTop + ".translateY")
|
|
|
|
|
|
|
|
#Translate Z
|
|
autoSpineTZNode = cmds.shadingNode("plusMinusAverage", asUtility = True, name = midDriverTop + "_TZ_Avg")
|
|
cmds.setAttr(autoSpineTZNode + ".operation", 3)
|
|
autoSpineTZ_MultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = midDriverTop + "_TZ_Mult")
|
|
|
|
cmds.connectAttr(chestTrackNode + ".translateZ", autoSpineTZNode + ".input1D[0]")
|
|
cmds.connectAttr("hip_anim.translateZ", autoSpineTZNode + ".input1D[1]")
|
|
cmds.connectAttr(autoSpineTZNode + ".output1D", autoSpineTZ_MultNode + ".input1X")
|
|
cmds.connectAttr("chest_ik_anim.autoSpine", autoSpineTZ_MultNode + ".input2X")
|
|
cmds.connectAttr(autoSpineTZ_MultNode + ".outputX", midDriverTop + ".translateZ")
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def hookupSpine(self, ikControls, fkControls):
|
|
|
|
#constrain the driver joints to the FK and IK controls
|
|
i = 0
|
|
upAxis = "X"
|
|
|
|
for joint in ikControls:
|
|
|
|
driverJoint = joint.partition("splineIK_")[2]
|
|
driverJoint = "driver_" + driverJoint
|
|
|
|
|
|
if joint == ikControls[0]:
|
|
upAxis = self.getUpAxis(driverJoint)
|
|
|
|
if upAxis == "X":
|
|
axisB = "Y"
|
|
axisC = "Z"
|
|
|
|
if upAxis == "Y":
|
|
axisB = "X"
|
|
axisC = "Z"
|
|
|
|
if upAxis == "Z":
|
|
axisB = "X"
|
|
axisC = "Y"
|
|
|
|
|
|
twistJoint = "twist_" + joint
|
|
cmds.parentConstraint([twistJoint, fkControls[i]], driverJoint, mo = True)
|
|
cmds.scaleConstraint([twistJoint, fkControls[i]], driverJoint, mo = True)
|
|
scaleDriverJoint = driverJoint
|
|
|
|
|
|
if joint != ikControls[len(ikControls) - 1] and joint != ikControls[0]:
|
|
twistJoint = "twist_" + joint
|
|
cmds.parentConstraint([twistJoint, fkControls[i]], driverJoint, mo = True)
|
|
|
|
#create blendColors nodes for scale
|
|
blenderNodeScale = cmds.shadingNode("blendColors", asUtility = True, name = driverJoint + "_blenderNodeScale")
|
|
cmds.connectAttr(twistJoint + ".scale" + axisB, blenderNodeScale + ".color1R")
|
|
cmds.connectAttr(fkControls[i] + ".scale" + axisB, blenderNodeScale + ".color2R")
|
|
cmds.connectAttr(twistJoint + ".scale" + axisC, blenderNodeScale + ".color1G")
|
|
cmds.connectAttr(fkControls[i] + ".scale" + axisC, blenderNodeScale + ".color2G")
|
|
cmds.connectAttr(blenderNodeScale + ".outputR", driverJoint + ".scale" + axisB)
|
|
cmds.connectAttr(blenderNodeScale + ".outputG", driverJoint + ".scale" + axisC)
|
|
|
|
|
|
if joint == ikControls[len(ikControls) - 1]:
|
|
topJoint = "spine_splineIK_top_joint"
|
|
twistJoint = "twist_" + joint
|
|
|
|
cmds.orientConstraint([topJoint, fkControls[i]], driverJoint, mo = True)
|
|
cmds.pointConstraint([twistJoint, fkControls[i]], driverJoint, mo = True)
|
|
|
|
i = i + 1
|
|
|
|
|
|
|
|
#add attributes to the Rig_Settings node
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName='spine_ik', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
cmds.addAttr(longName='spine_fk', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
|
|
#hookup Rig_Settings attrs to the parentConstraint weights
|
|
|
|
#find connection targets
|
|
for ctrl in ikControls:
|
|
|
|
driverJoint = ctrl.partition("splineIK_")[2]
|
|
driverJoint = "driver_" + driverJoint
|
|
constraint = driverJoint + "_parentConstraint1"
|
|
|
|
#hook up blendColors scale node
|
|
try:
|
|
blenderNodeScale = driverJoint + "_blenderNodeScale"
|
|
cmds.connectAttr("Rig_Settings" + ".spine_ik", blenderNodeScale + ".blender")
|
|
except:
|
|
pass
|
|
|
|
|
|
|
|
if cmds.objExists(constraint):
|
|
targets = cmds.parentConstraint(constraint, q = True, weightAliasList = True)
|
|
|
|
for target in targets:
|
|
if target.find("IK") != -1:
|
|
cmds.connectAttr("Rig_Settings" + ".spine_ik", constraint + "." + target)
|
|
|
|
else:
|
|
cmds.connectAttr("Rig_Settings" + ".spine_fk", constraint + "." + target)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
pointConstraint = driverJoint + "_pointConstraint1"
|
|
orientConstraint = driverJoint + "_orientConstraint1"
|
|
|
|
pointTargets = cmds.pointConstraint(pointConstraint, q = True, weightAliasList = True)
|
|
orientTargets = cmds.orientConstraint(orientConstraint, q = True, weightAliasList = True)
|
|
|
|
for target in pointTargets:
|
|
if target.find("IK") != -1:
|
|
cmds.connectAttr("Rig_Settings" + ".spine_ik", pointConstraint + "." + target)
|
|
|
|
else:
|
|
cmds.connectAttr("Rig_Settings" + ".spine_fk", pointConstraint + "." + target)
|
|
|
|
|
|
for target in orientTargets:
|
|
if target.find("IK") != -1:
|
|
cmds.connectAttr("Rig_Settings" + ".spine_ik", orientConstraint + "." + target)
|
|
|
|
|
|
else:
|
|
cmds.connectAttr("Rig_Settings" + ".spine_fk", orientConstraint + "." + target)
|
|
|
|
|
|
#hook up spine control vis to the rig settings
|
|
cmds.connectAttr("Rig_Settings" + ".spine_fk", "spine_01_anim_grp.v")
|
|
cmds.connectAttr("Rig_Settings" + ".spine_ik", "mid_ik_anim_grp.v")
|
|
cmds.connectAttr("Rig_Settings" + ".spine_ik", "chest_ik_anim_grp.v")
|
|
|
|
|
|
#set spine rig to be IK by default
|
|
cmds.setAttr("Rig_Settings" + ".spine_ik", 1)
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildFKArms(self):
|
|
|
|
#duplicate our driver joints to create our FK arm skeleton
|
|
for side in ["l", "r"]:
|
|
|
|
#if the side has an arm, create the fk joints
|
|
if cmds.objExists("driver_upperarm_" + side):
|
|
autoClavJointStart = cmds.duplicate("driver_clavicle_" + side, po = True, name = "auto_clavicle_" + side)[0]
|
|
clavJoint = cmds.duplicate("driver_clavicle_" + side, po = True, name = "rig_clavicle_" + side)[0]
|
|
fkArmJoint = cmds.duplicate("driver_upperarm_" + side, po = True, name = "fk_upperarm_" + side)[0]
|
|
fkElbowJoint = cmds.duplicate("driver_lowerarm_" + side, po = True, name = "fk_lowerarm_" + side)[0]
|
|
fkWristJoint = cmds.duplicate("driver_hand_" + side, po = True, name = "fk_hand_" + side)[0]
|
|
|
|
#parent the fk upperarm to the world
|
|
parent = cmds.listRelatives(clavJoint, parent = True)
|
|
if parent != None:
|
|
cmds.parent(clavJoint, world = True)
|
|
|
|
#recreate the fk arm hierarchy
|
|
cmds.parent(fkArmJoint, clavJoint)
|
|
cmds.parent(fkElbowJoint, fkArmJoint)
|
|
cmds.parent(fkWristJoint, fkElbowJoint)
|
|
cmds.makeIdentity(fkArmJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#set rotation order on fk arm joint
|
|
cmds.setAttr(fkArmJoint + ".rotateOrder", 3)
|
|
|
|
#create the shoulder hierarchy
|
|
parent = cmds.listRelatives(autoClavJointStart, parent = True)
|
|
if parent != None:
|
|
cmds.parent(autoClavJointStart, world = True)
|
|
|
|
autoClavEndJoint = cmds.duplicate(fkArmJoint, parentOnly = True, name = "auto_clavicle_end_" + side)[0]
|
|
pos = cmds.xform(autoClavEndJoint, q = True, ws = True, t = True)
|
|
zPos = cmds.xform(autoClavJointStart, q = True, ws = True, t = True)[2]
|
|
cmds.xform(autoClavEndJoint, ws = True, t = [pos[0], pos[1], zPos])
|
|
cmds.parent(autoClavEndJoint, autoClavJointStart)
|
|
|
|
|
|
#create the IK for the clavicle
|
|
ikNodes = cmds.ikHandle(sj = autoClavJointStart, ee = autoClavEndJoint, sol = "ikSCsolver", name = "auto_clav_to_elbow_ikHandle_" + side)[0]
|
|
|
|
#position the IK handle at the elbow joint
|
|
constraint = cmds.pointConstraint(fkElbowJoint, ikNodes)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create our autoClav world grp
|
|
autoClavWorld = cmds.group(empty = True, name = "auto_clav_world_grp_" + side)
|
|
constraint = cmds.pointConstraint(autoClavEndJoint, autoClavWorld)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.makeIdentity(autoClavWorld, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#duplicate the FK arm to create our invisible arm
|
|
invisUpArm = cmds.duplicate(fkArmJoint, po = True, name = "invis_upperarm_" + side)[0]
|
|
invisLowArm = cmds.duplicate(fkElbowJoint, po = True, name = "invis_lowerarm_" + side)[0]
|
|
invisHand = cmds.duplicate(fkWristJoint, po = True, name = "invis_hand_" + side)[0]
|
|
|
|
cmds.parent(invisHand, invisLowArm)
|
|
cmds.parent(invisLowArm, invisUpArm)
|
|
cmds.parent(invisUpArm, autoClavWorld)
|
|
|
|
|
|
#create our upperarm orient locator
|
|
invisArmOrient = cmds.spaceLocator(name = "invis_arm_orient_loc_" + side)[0]
|
|
invisArmOrientGrp = cmds.group(empty = True, name = "invis_arm_orient_loc_grp_" + side)
|
|
|
|
constraint = cmds.parentConstraint(fkArmJoint, invisArmOrient)[0]
|
|
cmds.delete(constraint)
|
|
|
|
constraint = cmds.parentConstraint(fkArmJoint, invisArmOrientGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(invisArmOrient, invisArmOrientGrp)
|
|
|
|
|
|
|
|
#create the invis arm fk control (to derive autoClav info)
|
|
invisFkArmCtrl = self.createControl("circle", 20, "invis_fk_arm_" + side + "_anim")
|
|
cmds.setAttr(invisFkArmCtrl + ".ry", -90)
|
|
cmds.makeIdentity(invisFkArmCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(fkArmJoint, invisFkArmCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
invisFkArmCtrlGrp = cmds.group(empty = True, name = "invis_fk_arm_" + side + "_grp")
|
|
constraint = cmds.parentConstraint(fkArmJoint, invisFkArmCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(invisFkArmCtrl, invisFkArmCtrlGrp)
|
|
|
|
|
|
|
|
#position the arm FK control so that it is about halfway down the arm length
|
|
dist = (cmds.getAttr(fkElbowJoint + ".tx")) / 2
|
|
cmds.setAttr(invisFkArmCtrl + ".translateX", dist)
|
|
|
|
|
|
#set the pivot of the arm control back to the arm joint
|
|
piv = cmds.xform(fkArmJoint, q = True, ws = True, rotatePivot = True)
|
|
cmds.xform(invisFkArmCtrl, ws = True, piv = [piv[0], piv[1], piv[2]])
|
|
|
|
#freeze transforms on the control
|
|
cmds.makeIdentity(invisFkArmCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
|
|
#parent the orient arm grp to the fk ctrl
|
|
cmds.parent(invisArmOrientGrp, invisFkArmCtrl)
|
|
|
|
#duplicate the invis arm fk control setup for the real fk control(upper arm)
|
|
dupeNodes = cmds.duplicate(invisFkArmCtrlGrp, rc = True)
|
|
|
|
for node in dupeNodes:
|
|
name = node.partition("invis_")[2]
|
|
if name.find("1") != -1:
|
|
name = name.partition("1")[0]
|
|
|
|
cmds.rename(node, name)
|
|
|
|
|
|
#orient constrain the invis fk up arm to the invis up arm orient loc. Also do this for the real arm
|
|
cmds.orientConstraint(invisArmOrient, invisUpArm)
|
|
cmds.orientConstraint("arm_orient_loc_" + side, fkArmJoint)
|
|
|
|
|
|
#connect invis arm ctrl rotates to be driven by real arm control rotates
|
|
cmds.connectAttr("fk_arm_" + side + "_anim.rotate", invisFkArmCtrl + ".rotate")
|
|
|
|
|
|
#the following section of code will essentially give us a vector from the clav joint to the elbow. This will help to drive the rotations of the auto clav
|
|
#create our locators to determine elbow's position in space (will drive the ik handle on the auto clav)
|
|
autoTransLoc = cmds.spaceLocator(name = "elbow_auto_trans_loc_" + side)[0]
|
|
constraint = cmds.pointConstraint(fkElbowJoint, autoTransLoc)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#duplicate the locator to create a parent loc
|
|
autoTransLocParent = cmds.duplicate(autoTransLoc, po = True, name = "elbow_auto_trans_loc_parent_" + side)[0]
|
|
cmds.pointConstraint(autoTransLoc, ikNodes)
|
|
cmds.parent(autoTransLoc, autoTransLocParent)
|
|
cmds.parent(autoTransLocParent, autoClavWorld)
|
|
|
|
cmds.makeIdentity(autoTransLocParent, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#constrain the parent trans loc(elbow) to the invis elbow joint
|
|
cmds.pointConstraint(invisLowArm, autoTransLocParent, mo = True)
|
|
|
|
|
|
#create our locator that will handle switching between auto clav and manual clav. position at end joint (autoClavEndJoint)
|
|
autoClavSwitchLoc = cmds.spaceLocator(name = "auto_clav_switch_loc_" + side)[0]
|
|
|
|
constraint = cmds.pointConstraint(autoClavEndJoint, autoClavSwitchLoc)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(autoClavSwitchLoc, autoClavWorld)
|
|
cmds.makeIdentity(autoClavSwitchLoc, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(autoClavJointStart, autoClavWorld)
|
|
|
|
|
|
#setup constraint for switching between auto/manual
|
|
autoClavSwitchConstraint = cmds.pointConstraint([autoClavEndJoint, autoClavWorld], autoClavSwitchLoc, mo = True)[0]
|
|
cmds.setAttr(autoClavSwitchConstraint + "." + autoClavWorld + "W1", 0)
|
|
|
|
|
|
#create our IK for the auto clav to move
|
|
autoClavIK = cmds.ikHandle(sj = clavJoint, ee = fkArmJoint, sol = "ikSCsolver", name = "auto_clav_ikHandle_" + side)[0]
|
|
autoClavIKGrp = cmds.group(empty = True, name = "auto_clav_ikHandle_grp_" + side)
|
|
constraint = cmds.pointConstraint(autoClavIK, autoClavIKGrp)[0]
|
|
cmds.delete(constraint)
|
|
autoClavIKGrpMaster = cmds.duplicate(po = True, name = "auto_clav_ikHandle_grp_master_" + side)[0]
|
|
|
|
|
|
cmds.parent(autoClavIKGrpMaster, autoClavSwitchLoc)
|
|
cmds.parent(autoClavIKGrp, autoClavIKGrpMaster)
|
|
cmds.parent(autoClavIK, autoClavIKGrp)
|
|
#cmds.makeIdentity(autoClavIKGrp, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
|
|
#create the shoulder control
|
|
shoulderCtrl = self.createControl("pin", 1.5, "clavicle_" + side + "_anim")
|
|
cmds.setAttr(shoulderCtrl + ".ry", 90)
|
|
cmds.setAttr(shoulderCtrl + ".rx", 90)
|
|
|
|
constraint = cmds.pointConstraint(fkArmJoint, shoulderCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
shoulderCtrlGrp = cmds.group(empty = True, name = "clavicle_" + side + "_anim_grp")
|
|
constraint = cmds.pointConstraint(fkArmJoint, shoulderCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(shoulderCtrl, shoulderCtrlGrp)
|
|
cmds.parent(shoulderCtrlGrp, autoClavWorld)
|
|
|
|
cmds.makeIdentity(shoulderCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.setAttr(shoulderCtrl + ".sx", .65)
|
|
cmds.setAttr(shoulderCtrl + ".sy", 1.2)
|
|
cmds.setAttr(shoulderCtrl + ".sz", 1.2)
|
|
cmds.makeIdentity(shoulderCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
|
|
|
|
|
|
#connect shoulder ctrl translate to the autoClavIKGrp translate
|
|
cmds.connectAttr(shoulderCtrl + ".translate", autoClavIKGrp + ".translate")
|
|
cmds.connectAttr(autoClavSwitchLoc + ".translate", shoulderCtrl + ".rotatePivotTranslate")
|
|
|
|
|
|
#set limits on shoulder control
|
|
cmds.select(shoulderCtrl)
|
|
|
|
if side == "l":
|
|
cmds.transformLimits(tx = (-1,0), etx = (False, True))
|
|
else:
|
|
cmds.transformLimits(tx = (0,1), etx = (True, False))
|
|
|
|
|
|
#create FK elbow control
|
|
fkElbowCtrl = self.createControl("circle", 18, "fk_elbow_" + side + "_anim")
|
|
cmds.setAttr(fkElbowCtrl + ".ry", -90)
|
|
cmds.makeIdentity(fkElbowCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(fkElbowJoint, fkElbowCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
fkElbowCtrlGrp = cmds.group(empty = True, name = "fk_elbow_" + side + "_anim_grp")
|
|
constraint = cmds.parentConstraint(fkElbowJoint, fkElbowCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(fkElbowCtrl, fkElbowCtrlGrp)
|
|
cmds.makeIdentity(fkElbowCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(fkElbowCtrlGrp, "fk_arm_" + side + "_anim")
|
|
|
|
#constrain elbow joint to ctrl
|
|
cmds.parentConstraint(fkElbowCtrl, fkElbowJoint)
|
|
|
|
|
|
#create FK wrist control
|
|
fkWristCtrl = self.createControl("circle", 15, "fk_wrist_" + side + "_anim")
|
|
cmds.setAttr(fkWristCtrl + ".ry", -90)
|
|
cmds.makeIdentity(fkWristCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.parentConstraint(fkWristJoint, fkWristCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
fkWristCtrlGrp = cmds.group(empty = True, name = "fk_wrist_" + side + "_anim_grp")
|
|
constraint = cmds.parentConstraint(fkWristJoint, fkWristCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(fkWristCtrl, fkWristCtrlGrp)
|
|
cmds.makeIdentity(fkWristCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
cmds.parent(fkWristCtrlGrp, fkElbowCtrl)
|
|
|
|
#constrain wrist joint to ctrl
|
|
cmds.parentConstraint(fkWristCtrl, fkWristJoint)
|
|
|
|
|
|
#point constrain the fk arm grp to the fk upper arm joint
|
|
cmds.pointConstraint(fkArmJoint, "fk_arm_" + side + "_grp")
|
|
|
|
|
|
#clean up FK rig in scene
|
|
cmds.parent(invisFkArmCtrlGrp, autoClavWorld)
|
|
|
|
|
|
#find children under autoClavWorld
|
|
children = cmds.listRelatives(autoClavWorld, children = True)
|
|
dntGrp = cmds.group(empty = True, name = "auto_clav_sys_grp_" + side)
|
|
cmds.parent(dntGrp, autoClavWorld)
|
|
|
|
for child in children:
|
|
cmds.parent(child, dntGrp)
|
|
|
|
cmds.parent(shoulderCtrlGrp, autoClavWorld)
|
|
|
|
|
|
#group up the groups!
|
|
jointsGrp = cmds.group(empty = True, name = "joints_" + side + "_grp")
|
|
cmds.parent(clavJoint, jointsGrp)
|
|
|
|
masterGrp = cmds.group(empty = True, name = "arm_rig_master_grp_" + side)
|
|
constraint = cmds.pointConstraint(fkArmJoint, masterGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent([ikNodes, jointsGrp, autoClavWorld], masterGrp)
|
|
|
|
cmds.setAttr(dntGrp + ".v", 0)
|
|
cmds.setAttr(ikNodes + ".v", 0)
|
|
|
|
|
|
#add fk orientation options(normal, body, world)
|
|
fkOrient = cmds.spaceLocator(name = "fk_orient_master_loc_" + side)[0]
|
|
shape = cmds.listRelatives(fkOrient, shapes = True)[0]
|
|
cmds.setAttr(shape + ".v", 0)
|
|
|
|
constraint = cmds.parentConstraint(autoClavWorld, fkOrient)[0]
|
|
cmds.delete(constraint)
|
|
|
|
fkNormalOrient = cmds.duplicate(fkOrient, po = True, name = "fk_orient_normal_loc_" + side)[0]
|
|
fkBodyOrient = cmds.duplicate(fkOrient, po = True, name = "fk_orient_body_loc_" + side)[0]
|
|
fkWorldOrient = cmds.duplicate(fkOrient, po = True, name = "fk_orient_world_loc_" + side)[0]
|
|
|
|
fkOrientConstraint = cmds.orientConstraint([fkNormalOrient, fkBodyOrient, fkWorldOrient], fkOrient)[0]
|
|
|
|
cmds.parent(fkBodyOrient, "body_anim")
|
|
cmds.parent(fkNormalOrient, shoulderCtrl)
|
|
cmds.parent(fkOrient, masterGrp)
|
|
|
|
#parent FK arm ctrl grp to shoulder ctrl
|
|
cmds.parent("fk_arm_" + side + "_grp", fkOrient)
|
|
|
|
|
|
#put mode into default fk operation
|
|
cmds.setAttr(fkOrientConstraint + "." + fkBodyOrient + "W1", 0)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkWorldOrient + "W2", 0)
|
|
|
|
|
|
#get the number of spine bones and constrain the master grp to the last spine joint
|
|
numSpineBones = self.getSpineJoints()
|
|
cmds.parentConstraint("driver_spine_0" + str(len(numSpineBones)), masterGrp, mo = True)
|
|
|
|
|
|
|
|
|
|
|
|
#setup autoShoulder attr
|
|
cmds.select(shoulderCtrl)
|
|
cmds.addAttr(longName='autoShoulders', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
cmds.setAttr(shoulderCtrl + ".autoShoulders", 0)
|
|
cmds.setAttr(autoClavSwitchConstraint + "." + autoClavEndJoint + "W0", 0)
|
|
cmds.setAttr(autoClavSwitchConstraint + "." + autoClavWorld + "W1", 1)
|
|
cmds.setDrivenKeyframe([autoClavSwitchConstraint + "." + autoClavEndJoint + "W0", autoClavSwitchConstraint + "." + autoClavWorld + "W1"], cd = shoulderCtrl + ".autoShoulders", itt = "linear", ott = "linear")
|
|
|
|
|
|
cmds.setAttr(shoulderCtrl + ".autoShoulders", 1)
|
|
cmds.setAttr(autoClavSwitchConstraint + "." + autoClavEndJoint + "W0", 1)
|
|
cmds.setAttr(autoClavSwitchConstraint + "." + autoClavWorld + "W1", 0)
|
|
cmds.setDrivenKeyframe([autoClavSwitchConstraint + "." + autoClavEndJoint + "W0", autoClavSwitchConstraint + "." + autoClavWorld + "W1"], cd = shoulderCtrl + ".autoShoulders", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(shoulderCtrl + ".autoShoulders", 0)
|
|
|
|
|
|
|
|
|
|
|
|
#setup FK arm orient attr
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= side + "FkArmOrient", at = 'enum', en = "fk:body:world:", keyable = True)
|
|
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "FkArmOrient", 0)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkNormalOrient + "W0", 1)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkBodyOrient + "W1", 0)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkWorldOrient + "W2", 0)
|
|
cmds.setDrivenKeyframe([fkOrientConstraint + "." + fkNormalOrient + "W0", fkOrientConstraint + "." + fkBodyOrient + "W1", fkOrientConstraint + "." + fkWorldOrient + "W2"], cd = "Rig_Settings." + side + "FkArmOrient", itt = "linear", ott = "linear")
|
|
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "FkArmOrient", 1)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkNormalOrient + "W0", 0)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkBodyOrient + "W1", 1)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkWorldOrient + "W2", 0)
|
|
cmds.setDrivenKeyframe([fkOrientConstraint + "." + fkNormalOrient + "W0", fkOrientConstraint + "." + fkBodyOrient + "W1", fkOrientConstraint + "." + fkWorldOrient + "W2"], cd = "Rig_Settings." + side + "FkArmOrient", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "FkArmOrient", 2)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkNormalOrient + "W0", 0)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkBodyOrient + "W1", 0)
|
|
cmds.setAttr(fkOrientConstraint + "." + fkWorldOrient + "W2", 1)
|
|
cmds.setDrivenKeyframe([fkOrientConstraint + "." + fkNormalOrient + "W0", fkOrientConstraint + "." + fkBodyOrient + "W1", fkOrientConstraint + "." + fkWorldOrient + "W2"], cd = "Rig_Settings." + side + "FkArmOrient", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "FkArmOrient", 0)
|
|
|
|
|
|
#setup limits on auto clavicle
|
|
|
|
|
|
cmds.setAttr(shoulderCtrl + ".autoShoulders", 1)
|
|
#cmds.setAttr("fk_arm_" + side + "_anim.ry", -60)
|
|
#grrr. need to force update since maya is not getting the info correctly
|
|
cmds.select("fk_arm_" + side + "_anim")
|
|
cmds.setToolTo( 'moveSuperContext' )
|
|
cmds.refresh(force = True)
|
|
cmds.select(clear = True)
|
|
#limitInfo = cmds.xform(autoClavSwitchLoc, q = True, t = True)
|
|
#cmds.setAttr("fk_arm_" + side + "_anim.ry", 0)
|
|
cmds.setAttr(shoulderCtrl + ".autoShoulders", 0)
|
|
cmds.select("fk_arm_" + side + "_anim")
|
|
cmds.setToolTo( 'moveSuperContext' )
|
|
cmds.refresh(force = True)
|
|
cmds.select(clear = True)
|
|
|
|
|
|
|
|
|
|
|
|
#lock attrs that should not be animated and colorize controls
|
|
for control in [shoulderCtrl, "fk_arm_" + side + "_anim", fkElbowCtrl, fkWristCtrl]:
|
|
|
|
if control == shoulderCtrl:
|
|
|
|
for attr in [".rx", ".ry", ".rz", ".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
else:
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
#parent fkWorldOrient to master anim
|
|
cmds.parent(fkWorldOrient, "master_anim")
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildIkArms(self):
|
|
|
|
#duplicate the fk arm joints and create our ik arm chain
|
|
for side in ["l", "r"]:
|
|
if cmds.objExists("fk_upperarm_" + side):
|
|
ikUpArmJoint = cmds.duplicate("fk_upperarm_" + side, po = True, name = "ik_upperarm_" + side)[0]
|
|
ikLowArmJoint = cmds.duplicate("fk_lowerarm_" + side, po = True, name = "ik_lowerarm_" + side)[0]
|
|
ikWristJoint = cmds.duplicate("fk_hand_" + side, po = True, name = "ik_hand_" + side)[0]
|
|
ikWristEndJoint = cmds.duplicate("fk_hand_" + side, po = True, name = "ik_hand_end_" + side)[0]
|
|
|
|
cmds.parent([ikWristEndJoint], ikWristJoint)
|
|
cmds.parent(ikWristJoint, ikLowArmJoint)
|
|
cmds.parent(ikLowArmJoint, ikUpArmJoint)
|
|
|
|
|
|
#create fk matching joints
|
|
fkMatchUpArm = cmds.duplicate(ikUpArmJoint, po = True, name = "ik_upperarm_fk_matcher_" + side)[0]
|
|
fkMatchLowArm = cmds.duplicate(ikLowArmJoint, po = True, name = "ik_lowerarm_fk_matcher_" + side)[0]
|
|
fkMatchWrist = cmds.duplicate(ikWristJoint, po = True, name = "ik_wrist_fk_matcher_" + side)[0]
|
|
|
|
cmds.parent(fkMatchWrist, fkMatchLowArm)
|
|
cmds.parent(fkMatchLowArm, fkMatchUpArm)
|
|
|
|
cmds.parentConstraint(ikUpArmJoint, fkMatchUpArm, mo = True)
|
|
cmds.parentConstraint(ikLowArmJoint, fkMatchLowArm, mo = True)
|
|
cmds.parentConstraint(ikWristJoint, fkMatchWrist, mo = True)
|
|
|
|
#move wrist end joint out a bit
|
|
scaleFactor = self.getScaleFactor()
|
|
|
|
if side == "l":
|
|
cmds.setAttr(ikWristEndJoint + ".tx", 15 * scaleFactor)
|
|
|
|
else:
|
|
cmds.setAttr(ikWristEndJoint + ".tx", -15 * scaleFactor)
|
|
|
|
|
|
cmds.makeIdentity(ikUpArmJoint, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#set rotate order on ikUpArm
|
|
cmds.setAttr(ikUpArmJoint + ".rotateOrder", 3)
|
|
|
|
|
|
#set preferred angle on arm
|
|
cmds.setAttr(ikLowArmJoint + ".preferredAngleZ", -90)
|
|
|
|
|
|
#create ik control
|
|
ikCtrl = self.createControl("circle", 15, "ik_wrist_" + side + "_anim")
|
|
cmds.setAttr(ikCtrl + ".ry", -90)
|
|
cmds.makeIdentity(ikCtrl, r = 1, apply =True)
|
|
|
|
constraint = cmds.pointConstraint(ikWristJoint, ikCtrl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
ikCtrlGrp = cmds.group(empty = True, name = "ik_wrist_" + side + "_anim_grp")
|
|
constraint = cmds.pointConstraint(ikWristJoint, ikCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
|
|
ikCtrlSpaceSwitchFollow = cmds.duplicate(ikCtrlGrp, po = True, n = "ik_wrist_" + side + "_anim_space_switcher_follow")[0]
|
|
ikCtrlSpaceSwitch = cmds.duplicate(ikCtrlGrp, po = True, n = "ik_wrist_" + side + "_anim_space_switcher")[0]
|
|
|
|
cmds.parent(ikCtrlSpaceSwitch, ikCtrlSpaceSwitchFollow)
|
|
cmds.parent(ikCtrlGrp, ikCtrlSpaceSwitch)
|
|
|
|
cmds.parent(ikCtrl, ikCtrlGrp)
|
|
cmds.makeIdentity(ikCtrlGrp, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#create RP IK on arm and SC ik from wrist to wrist end
|
|
rpIkHandle = cmds.ikHandle(name = "arm_ikHandle_" + side, solver = "ikRPsolver", sj = ikUpArmJoint, ee = ikWristJoint)[0]
|
|
scIkHandle = cmds.ikHandle(name = "hand_ikHandle_" + side, solver = "ikSCsolver", sj = ikWristJoint, ee = ikWristEndJoint)[0]
|
|
|
|
cmds.parent(scIkHandle, rpIkHandle)
|
|
cmds.setAttr(rpIkHandle + ".v", 0)
|
|
cmds.setAttr(scIkHandle + ".v", 0)
|
|
|
|
|
|
#parent IK to ik control
|
|
cmds.parent(rpIkHandle, ikCtrl)
|
|
|
|
|
|
#create a pole vector control
|
|
ikPvCtrl = self.createControl("sphere", 6, "ik_elbow_" + side + "_anim")
|
|
constraint = cmds.pointConstraint(ikLowArmJoint, ikPvCtrl)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(ikPvCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#move out a bit
|
|
cmds.setAttr(ikPvCtrl + ".ty", (30 * scaleFactor))
|
|
cmds.makeIdentity(ikPvCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
|
|
|
|
|
|
#create group for control
|
|
ikPvCtrlGrp = cmds.group(empty = True, name = "ik_elbow_" + side + "_anim_grp")
|
|
constraint = cmds.parentConstraint(ikPvCtrl, ikPvCtrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
ikPvSpaceSwitchFollow = cmds.duplicate(ikPvCtrlGrp, po = True, name = "ik_elbow_" + side + "_anim_space_switcher_follow")[0]
|
|
ikPvSpaceSwitch = cmds.duplicate(ikPvCtrlGrp, po = True, name = "ik_elbow_" + side + "_anim_space_switcher")[0]
|
|
|
|
cmds.parent(ikPvSpaceSwitch, ikPvSpaceSwitchFollow)
|
|
cmds.parent(ikPvCtrlGrp, ikPvSpaceSwitch)
|
|
cmds.parent(ikPvCtrl, ikPvCtrlGrp)
|
|
cmds.parent(ikPvSpaceSwitchFollow, "offset_anim")
|
|
cmds.makeIdentity(ikPvCtrl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#setup pole vector constraint
|
|
cmds.poleVectorConstraint(ikPvCtrl, rpIkHandle)
|
|
|
|
|
|
#create IK for invisible arm
|
|
invisRpIkHandle = cmds.ikHandle(name = "invis_arm_ikHandle_" + side, solver = "ikRPsolver", sj = "invis_upperarm_" + side, ee = "invis_hand_" + side)[0]
|
|
cmds.parent(invisRpIkHandle, ikCtrl)
|
|
cmds.poleVectorConstraint(ikPvCtrl, invisRpIkHandle)
|
|
cmds.setAttr(invisRpIkHandle + ".v", 0)
|
|
|
|
|
|
|
|
#constrain driver joints to both fk and ik chains
|
|
cmds.parentConstraint("rig_clavicle_" + side, "driver_clavicle_" + side, mo = True)
|
|
upArmConstPoint = cmds.pointConstraint(["fk_arm_" + side + "_anim", "ik_upperarm_" + side], "driver_upperarm_" + side)[0]
|
|
upArmConstOrient = cmds.orientConstraint(["fk_upperarm_" + side, "ik_upperarm_" + side], "driver_upperarm_" + side)[0]
|
|
lowArmConst = cmds.parentConstraint(["fk_lowerarm_" + side, "ik_lowerarm_" + side], "driver_lowerarm_" + side)[0]
|
|
handConst = cmds.parentConstraint(["fk_hand_" + side, "ik_hand_" + side], "driver_hand_" + side, mo = True)[0]
|
|
|
|
|
|
#create blend nodes for the scale
|
|
scaleBlendColors_UpArm = cmds.shadingNode("blendColors", asUtility = True, name = side + "_up_arm_scale_blend")
|
|
cmds.connectAttr(ikUpArmJoint + ".scale", scaleBlendColors_UpArm + ".color1")
|
|
cmds.connectAttr("fk_arm_" + side + "_anim.scale", scaleBlendColors_UpArm + ".color2")
|
|
cmds.connectAttr(scaleBlendColors_UpArm + ".output", "driver_upperarm_" + side + ".scale")
|
|
|
|
|
|
scaleBlendColors_LoArm = cmds.shadingNode("blendColors", asUtility = True, name = side + "_lo_arm_scale_blend")
|
|
cmds.connectAttr(ikLowArmJoint + ".scale", scaleBlendColors_LoArm + ".color1")
|
|
cmds.connectAttr("fk_elbow_" + side + "_anim.scale", scaleBlendColors_LoArm + ".color2")
|
|
cmds.connectAttr(scaleBlendColors_LoArm + ".output", "driver_lowerarm_" + side + ".scale")
|
|
|
|
scaleBlendColors_Wrist = cmds.shadingNode("blendColors", asUtility = True, name = side + "_wrist_scale_blend")
|
|
cmds.connectAttr(ikWristJoint + ".scale", scaleBlendColors_Wrist + ".color1")
|
|
cmds.connectAttr("fk_wrist_" + side + "_anim.scale", scaleBlendColors_Wrist + ".color2")
|
|
cmds.connectAttr(scaleBlendColors_Wrist + ".output", "driver_hand_" + side + ".scale")
|
|
|
|
|
|
|
|
|
|
#set limits
|
|
cmds.select("driver_upperarm_" + side)
|
|
cmds.transformLimits(sy = (.05, 1.25), sz = (.05, 1.25), esy = [False, True], esz = [False, True])
|
|
cmds.select("driver_lowerarm_" + side)
|
|
cmds.transformLimits(sy = (.05, 1.25), sz = (.05, 1.25), esy = [False, True], esz = [False, True])
|
|
|
|
|
|
|
|
#create the IK/FK switch
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= side + "ArmMode", at = 'enum', en = "fk:ik:", keyable = True)
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ArmMode", 0)
|
|
|
|
cmds.setAttr(upArmConstPoint + "." + "fk_arm_" + side + "_anim" + "W0", 1)
|
|
cmds.setAttr(upArmConstPoint + "." + "ik_upperarm_" + side + "W1", 0)
|
|
cmds.setAttr(upArmConstOrient + "." + "fk_upperarm_" + side + "W0", 1)
|
|
cmds.setAttr(upArmConstOrient + "." + "ik_upperarm_" + side + "W1", 0)
|
|
cmds.setAttr(scaleBlendColors_UpArm + "." + "blender", 0)
|
|
|
|
cmds.setAttr(lowArmConst + "." + "fk_lowerarm_" + side + "W0", 1)
|
|
cmds.setAttr(lowArmConst + "." + "ik_lowerarm_" + side + "W1", 0)
|
|
cmds.setAttr(scaleBlendColors_LoArm + "." + "blender", 0)
|
|
|
|
cmds.setAttr(handConst + "." + "fk_hand_" + side + "W0", 1)
|
|
cmds.setAttr(handConst + "." + "ik_hand_" + side + "W1", 0)
|
|
cmds.setAttr(scaleBlendColors_Wrist + "." + "blender", 0)
|
|
|
|
cmds.setAttr(invisRpIkHandle + ".ikBlend", 0)
|
|
cmds.setAttr("fk_arm_" + side + "_grp.v", 1)
|
|
cmds.setAttr("ik_wrist_" + side + "_anim_space_switcher.v", 0)
|
|
cmds.setAttr("ik_elbow_" + side + "_anim_space_switcher.v", 0)
|
|
|
|
|
|
cmds.setDrivenKeyframe([scaleBlendColors_UpArm + "." + "blender", scaleBlendColors_LoArm + "." + "blender", scaleBlendColors_Wrist + "." + "blender", upArmConstPoint + "." + "fk_arm_" + side + "_anim" + "W0", upArmConstPoint + "." + "ik_upperarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([upArmConstOrient + "." + "fk_upperarm_" + side + "W0", upArmConstOrient + "." + "ik_upperarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([lowArmConst + "." + "fk_lowerarm_" + side + "W0", lowArmConst + "." + "ik_lowerarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([handConst + "." + "fk_hand_" + side + "W0", handConst + "." + "ik_hand_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([invisRpIkHandle + ".ikBlend", "fk_arm_" + side + "_grp.v"], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe(["ik_wrist_" + side + "_anim_space_switcher.v", "ik_elbow_" + side + "_anim_space_switcher.v"], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ArmMode", 1)
|
|
|
|
cmds.setAttr(upArmConstPoint + "." + "fk_arm_" + side + "_anim" "W0", 0)
|
|
cmds.setAttr(upArmConstPoint + "." + "ik_upperarm_" + side + "W1", 1)
|
|
cmds.setAttr(upArmConstOrient + "." + "fk_upperarm_" + side + "W0", 0)
|
|
cmds.setAttr(upArmConstOrient + "." + "ik_upperarm_" + side + "W1", 1)
|
|
cmds.setAttr(scaleBlendColors_UpArm + "." + "blender", 1)
|
|
|
|
cmds.setAttr(lowArmConst + "." + "fk_lowerarm_" + side + "W0", 0)
|
|
cmds.setAttr(lowArmConst + "." + "ik_lowerarm_" + side + "W1", 1)
|
|
cmds.setAttr(scaleBlendColors_LoArm + "." + "blender", 1)
|
|
|
|
cmds.setAttr(handConst + "." + "fk_hand_" + side + "W0", 0)
|
|
cmds.setAttr(handConst + "." + "ik_hand_" + side + "W1", 1)
|
|
cmds.setAttr(scaleBlendColors_Wrist + "." + "blender", 1)
|
|
|
|
cmds.setAttr(invisRpIkHandle + ".ikBlend", 1)
|
|
cmds.setAttr("fk_arm_" + side + "_grp.v", 0)
|
|
cmds.setAttr("ik_wrist_" + side + "_anim_space_switcher.v", 1)
|
|
cmds.setAttr("ik_elbow_" + side + "_anim_space_switcher.v", 1)
|
|
|
|
cmds.setDrivenKeyframe([scaleBlendColors_UpArm + "." + "blender", scaleBlendColors_LoArm + "." + "blender", scaleBlendColors_Wrist + "." + "blender", upArmConstPoint + "." + "fk_arm_" + side + "_anim" + "W0", upArmConstPoint + "." + "ik_upperarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([upArmConstOrient + "." + "fk_upperarm_" + side + "W0", upArmConstOrient + "." + "ik_upperarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([lowArmConst + "." + "fk_lowerarm_" + side + "W0", lowArmConst + "." + "ik_lowerarm_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([handConst + "." + "fk_hand_" + side + "W0", handConst + "." + "ik_hand_" + side + "W1", ], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe([invisRpIkHandle + ".ikBlend", "fk_arm_" + side + "_grp.v"], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
cmds.setDrivenKeyframe(["ik_wrist_" + side + "_anim_space_switcher.v", "ik_elbow_" + side + "_anim_space_switcher.v"], cd = "Rig_Settings." + side + "ArmMode", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr("Rig_Settings." + side + "ArmMode", 0)
|
|
|
|
|
|
|
|
#setup stretch on IK
|
|
cmds.select(ikCtrl)
|
|
cmds.addAttr(longName=("stretch"), at = 'double',min = 0, max = 1, dv = 0, keyable = True)
|
|
cmds.addAttr(longName=("squash"), at = 'double',min = 0, max = 1, dv = 0, keyable = True)
|
|
stretchMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "ikHand_stretchToggleMultNode_" + side)
|
|
|
|
#need to get the total length of the arm chain
|
|
totalDist = abs(cmds.getAttr(ikLowArmJoint + ".tx" ) + cmds.getAttr(ikWristJoint + ".tx"))
|
|
|
|
|
|
#create a distanceBetween node
|
|
distBetween = cmds.shadingNode("distanceBetween", asUtility = True, name = side + "_ik_arm_distBetween")
|
|
|
|
#get world positions of upper arm and ik
|
|
baseGrp = cmds.group(empty = True, name = "ik_arm_base_grp_" + side)
|
|
endGrp = cmds.group(empty = True, name = "ik_arm_end_grp_" + side)
|
|
cmds.pointConstraint(ikUpArmJoint, baseGrp)
|
|
cmds.pointConstraint(ikCtrl, endGrp)
|
|
|
|
#hook in group translates into distanceBetween node inputs
|
|
cmds.connectAttr(baseGrp + ".translate", distBetween + ".point1")
|
|
cmds.connectAttr(endGrp + ".translate", distBetween + ".point2")
|
|
|
|
#create a condition node that will compare original length to current length
|
|
#if second term is greater than, or equal to the first term, the chain needs to stretch
|
|
ikArmCondition = cmds.shadingNode("condition", asUtility = True, name = side + "_ik_arm_stretch_condition")
|
|
cmds.setAttr(ikArmCondition + ".operation", 3)
|
|
cmds.connectAttr(distBetween + ".distance", ikArmCondition + ".secondTerm")
|
|
cmds.setAttr(ikArmCondition + ".firstTerm", totalDist)
|
|
|
|
#hook up the condition node's return colors
|
|
cmds.setAttr(ikArmCondition + ".colorIfTrueR", totalDist)
|
|
cmds.connectAttr(distBetween + ".distance", ikArmCondition + ".colorIfFalseR")
|
|
|
|
|
|
#create the mult/divide node(set to divide) that will take the original creation length as a static value in input2x, and the connected length into 1x.
|
|
armDistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = "arm_dist_multNode_" + side)
|
|
cmds.setAttr(armDistMultNode + ".operation", 2) #divide
|
|
cmds.setAttr(armDistMultNode + ".input2X", totalDist)
|
|
cmds.connectAttr(ikArmCondition + ".outColorR", armDistMultNode + ".input1X")
|
|
|
|
#create a stretch toggle mult node that multiplies the stretch factor by the bool of the stretch attr. (0 or 1), this way our condition reads
|
|
#if this result is greater than the original length(impossible if stretch bool is off, since result will be 0), than take this result and plug it
|
|
#into the scale of our IK arm joints
|
|
stretchToggleCondition = cmds.shadingNode("condition", asUtility = True, name = "arm_stretch_toggle_condition_" + side)
|
|
cmds.setAttr(stretchToggleCondition + ".operation", 0)
|
|
cmds.connectAttr(ikCtrl + ".stretch", stretchToggleCondition + ".firstTerm")
|
|
cmds.setAttr(stretchToggleCondition + ".secondTerm", 1)
|
|
cmds.connectAttr(armDistMultNode + ".outputX", stretchToggleCondition + ".colorIfTrueR")
|
|
cmds.setAttr(stretchToggleCondition + ".colorIfFalseR", 1)
|
|
|
|
|
|
#set up the squash nodes
|
|
squashMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = side + "_ik_arm_squash_mult")
|
|
cmds.setAttr(squashMultNode + ".operation", 2)
|
|
cmds.setAttr(squashMultNode + ".input1X", totalDist)
|
|
cmds.connectAttr(ikArmCondition + ".outColorR", squashMultNode + ".input2X")
|
|
|
|
|
|
#create a stretch toggle mult node that multiplies the stretch factor by the bool of the stretch attr. (0 or 1), this way our condition reads
|
|
#if this result is greater than the original length(impossible if stretch bool is off, since result will be 0), than take this result and plug it
|
|
#into the scale of our IK arm joints
|
|
squashToggleCondition = cmds.shadingNode("condition", asUtility = True, name = "arm_squash_toggle_condition_" + side)
|
|
cmds.setAttr(squashToggleCondition + ".operation", 0)
|
|
cmds.connectAttr(ikCtrl + ".squash", squashToggleCondition + ".firstTerm")
|
|
cmds.setAttr(squashToggleCondition + ".secondTerm", 1)
|
|
cmds.connectAttr(squashMultNode + ".outputX", squashToggleCondition + ".colorIfTrueR")
|
|
cmds.setAttr(squashToggleCondition + ".colorIfFalseR", 1)
|
|
|
|
|
|
|
|
#connect to arm scale
|
|
cmds.connectAttr(stretchToggleCondition + ".outColorR", ikUpArmJoint + ".sx")
|
|
cmds.connectAttr(stretchToggleCondition + ".outColorR", ikLowArmJoint + ".sx")
|
|
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikLowArmJoint + ".sy")
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikLowArmJoint + ".sz")
|
|
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikUpArmJoint + ".sy")
|
|
cmds.connectAttr(squashToggleCondition + ".outColorR", ikUpArmJoint + ".sz")
|
|
|
|
|
|
#add base and end groups to arm grp
|
|
cmds.parent([baseGrp, endGrp], "arm_rig_master_grp_" + side)
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
|
|
#setup roll bones if obj Exists
|
|
if cmds.objExists("driver_upperarm_twist_01_" + side):
|
|
self.buildArmRoll(side)
|
|
|
|
if cmds.objExists("driver_lowerarm_twist_01_" + side):
|
|
self.buildForearmTwist(side)
|
|
|
|
#colorize controls, cleanup attrs, and cleanup hierarchy
|
|
for attr in [".sx", ".sy", ".sz", ".v"]:
|
|
cmds.setAttr(ikCtrl + attr, lock = True, keyable = False)
|
|
|
|
for attr in [".sx", ".sy", ".sz", ".rx", ".ry", ".rz", ".v"]:
|
|
cmds.setAttr(ikPvCtrl + attr, lock = True, keyable = False)
|
|
|
|
|
|
for control in [ikCtrl, ikPvCtrl]:
|
|
if side == "l":
|
|
color = 6
|
|
|
|
else:
|
|
color = 13
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", color)
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def buildNeckAndHead(self):
|
|
|
|
numNeckBones = cmds.getAttr("Skeleton_Settings.numNeckBones")
|
|
|
|
if numNeckBones == 1:
|
|
#create the FK control for the neck
|
|
neckControl = self.createControl("circle", 25, "neck_01_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_neck_01", neckControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
neckControlGrp = cmds.group(empty = True, name = "neck_01_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_neck_01", neckControlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(neckControl, neckControlGrp)
|
|
cmds.setAttr(neckControl + ".ry", -90)
|
|
cmds.makeIdentity(neckControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#create the FK control for the head
|
|
headControl = self.createControl("circle", 30, "head_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_head", headControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
headControlGrp = cmds.group(empty = True, name = "head_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_head", headControlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(headControl, headControlGrp)
|
|
cmds.setAttr(headControl + ".ry", 90)
|
|
cmds.setAttr(headControl + ".rz", -35)
|
|
cmds.makeIdentity(headControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#setup head orientation
|
|
orientNodes = self.setupHeadOrientation(neckControl, headControl)
|
|
neckOrientNodes = self.setupNeckOrientation(neckControl)
|
|
|
|
#hook into spine
|
|
cmds.parent(headControlGrp, orientNodes[0])
|
|
cmds.parent(orientNodes[0], neckControl)
|
|
numSpineBones = self.getSpineJoints()
|
|
cmds.parent(neckOrientNodes[0], neckControlGrp)
|
|
cmds.parent(neckControl, neckOrientNodes[0])
|
|
cmds.parentConstraint("driver_spine_0" + str(len(numSpineBones)), neckControlGrp, mo = True)
|
|
|
|
#constrain driver joints to controls
|
|
cmds.parentConstraint(neckControl, "driver_neck_01", mo = True)
|
|
cmds.parentConstraint(headControl, "driver_head", mo = True)
|
|
cmds.connectAttr(neckControl + ".scale", "driver_neck_01.scale")
|
|
cmds.connectAttr(headControl + ".scale", "driver_head.scale")
|
|
|
|
|
|
#lock attrs, color controls, and clean up hierarchy
|
|
for control in [neckControl, headControl]:
|
|
for attr in [".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
cmds.setAttr(neckControl + ".overrideEnabled", 1)
|
|
cmds.setAttr(neckControl + ".overrideColor", 18)
|
|
cmds.setAttr(headControl + ".overrideEnabled", 1)
|
|
cmds.setAttr(headControl + ".overrideColor", 17)
|
|
|
|
masterGrp = cmds.group(empty = True, name = "head_sys_grp")
|
|
cmds.parent(orientNodes[4], masterGrp)
|
|
cmds.parent(neckOrientNodes[3], masterGrp)
|
|
#cmds.parent(neckOrientNodes[0], masterGrp)
|
|
|
|
|
|
else:
|
|
neckControlMid = ""
|
|
if numNeckBones == 2:
|
|
#create the FK controls for the neck
|
|
neckControl = self.createControl("circle", 25, "neck_01_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_neck_01", neckControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
neckControlGrp = cmds.group(empty = True, name = "neck_01_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_neck_01", neckControlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(neckControl, neckControlGrp)
|
|
cmds.setAttr(neckControl + ".ry", -90)
|
|
cmds.makeIdentity(neckControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
neckControlEnd = self.createControl("circle", 25, "neck_02_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_neck_02", neckControlEnd)[0]
|
|
cmds.delete(constraint)
|
|
|
|
neckControlEndGrp = cmds.group(empty = True, name = "neck_02_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_neck_02", neckControlEndGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(neckControlEnd, neckControlEndGrp)
|
|
cmds.setAttr(neckControlEnd + ".ry", -90)
|
|
cmds.makeIdentity(neckControlEnd, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#setup neck hiearchy
|
|
cmds.parent(neckControlEndGrp, neckControl)
|
|
|
|
|
|
if numNeckBones == 3:
|
|
|
|
#create the FK controls for the neck
|
|
neckControl = self.createControl("circle", 25, "neck_01_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_neck_01", neckControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
neckControlGrp = cmds.group(empty = True, name = "neck_01_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_neck_01", neckControlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(neckControl, neckControlGrp)
|
|
cmds.setAttr(neckControl + ".ry", -90)
|
|
cmds.makeIdentity(neckControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
neckControlMid = self.createControl("circle", 25, "neck_02_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_neck_02", neckControlMid)[0]
|
|
cmds.delete(constraint)
|
|
|
|
neckControlMidGrp = cmds.group(empty = True, name = "neck_02_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_neck_02", neckControlMidGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(neckControlMid, neckControlMidGrp)
|
|
cmds.setAttr(neckControlMid + ".ry", -90)
|
|
cmds.makeIdentity(neckControlMid, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
|
|
neckControlEnd = self.createControl("circle", 25, "neck_03_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_neck_03", neckControlEnd)[0]
|
|
cmds.delete(constraint)
|
|
|
|
neckControlEndGrp = cmds.group(empty = True, name = "neck_03_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_neck_03", neckControlEndGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(neckControlEnd, neckControlEndGrp)
|
|
cmds.setAttr(neckControlEnd + ".ry", -90)
|
|
cmds.makeIdentity(neckControlEnd, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#setup neck hiearchy
|
|
cmds.parent(neckControlEndGrp, neckControlMid)
|
|
cmds.parent(neckControlMidGrp, neckControl)
|
|
|
|
|
|
|
|
#create the FK control for the head
|
|
headControl = self.createControl("circle", 30, "head_fk_anim")
|
|
constraint = cmds.parentConstraint("driver_head", headControl)[0]
|
|
cmds.delete(constraint)
|
|
|
|
headControlGrp = cmds.group(empty = True, name = "head_fk_anim_grp")
|
|
constraint = cmds.parentConstraint("driver_head", headControlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(headControl, headControlGrp)
|
|
cmds.setAttr(headControl + ".ry", 90)
|
|
cmds.setAttr(headControl + ".rz", -35)
|
|
cmds.makeIdentity(headControl, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
|
|
#setup head orientation
|
|
orientNodes = self.setupHeadOrientation(neckControlEnd, headControl)
|
|
neckOrientNodes = self.setupNeckOrientation(neckControl)
|
|
|
|
#hook into spine
|
|
cmds.parent(headControlGrp, orientNodes[0])
|
|
cmds.parent(orientNodes[0], neckControlEnd)
|
|
numSpineBones = self.getSpineJoints()
|
|
cmds.parent(neckOrientNodes[0], neckControlGrp)
|
|
cmds.parent(neckControl, neckOrientNodes[0])
|
|
cmds.parentConstraint("driver_spine_0" + str(len(numSpineBones)), neckControlGrp, mo = True)
|
|
|
|
|
|
#constrain driver joints to controls
|
|
if numNeckBones == 2:
|
|
cmds.parentConstraint(neckControl, "driver_neck_01", mo = True)
|
|
cmds.parentConstraint(neckControlEnd, "driver_neck_02", mo = True)
|
|
cmds.connectAttr(neckControl + ".scale", "driver_neck_01.scale")
|
|
cmds.connectAttr(neckControlEnd + ".scale", "driver_neck_02.scale")
|
|
|
|
|
|
if numNeckBones == 3:
|
|
cmds.parentConstraint(neckControl, "driver_neck_01", mo = True)
|
|
cmds.parentConstraint(neckControlMid, "driver_neck_02", mo = True)
|
|
cmds.parentConstraint(neckControlEnd, "driver_neck_03", mo = True)
|
|
cmds.connectAttr(neckControl + ".scale", "driver_neck_01.scale")
|
|
cmds.connectAttr(neckControlMid + ".scale", "driver_neck_02.scale")
|
|
cmds.connectAttr(neckControlEnd + ".scale", "driver_neck_03.scale")
|
|
|
|
cmds.parentConstraint(headControl, "driver_head", mo = True)
|
|
cmds.connectAttr(headControl + ".scale", "driver_head.scale")
|
|
|
|
|
|
#lock attrs, color controls, and clean up hierarchy
|
|
for control in [neckControl, neckControlEnd, neckControlMid, headControl]:
|
|
if cmds.objExists(control):
|
|
for attr in [".v"]:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
|
|
for control in [neckControl, neckControlEnd, neckControlMid]:
|
|
if cmds.objExists(control):
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
cmds.setAttr(headControl + ".overrideEnabled", 1)
|
|
cmds.setAttr(headControl + ".overrideColor", 17)
|
|
|
|
masterGrp = cmds.group(empty = True, name = "head_sys_grp")
|
|
cmds.parent(orientNodes[4], masterGrp)
|
|
cmds.parent(neckOrientNodes[3], masterGrp)
|
|
#cmds.parent(neckOrientNodes[0], masterGrp)
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def setupHeadOrientation(self, neckControl, headControl):
|
|
|
|
#create head orient controls (neck, shoulder, body, world)
|
|
orientMaster = cmds.group(empty = True, name = "head_fk_orient_master")
|
|
constraint = cmds.parentConstraint("driver_head", orientMaster)[0]
|
|
cmds.delete(constraint)
|
|
|
|
orientNeck = cmds.duplicate(orientMaster, po = True, name = "head_fk_orient_neck")[0]
|
|
orientShoulder = cmds.duplicate(orientMaster, po = True, name = "head_fk_orient_shoulder")[0]
|
|
orientBody = cmds.duplicate(orientMaster, po = True, name = "head_fk_orient_body")[0]
|
|
orientWorld = cmds.duplicate(orientMaster, po = True, name = "head_fk_orient_world")[0]
|
|
|
|
fkHeadOrientConstraint = cmds.orientConstraint([orientNeck, orientShoulder, orientBody, orientWorld], orientMaster)[0]
|
|
|
|
numSpineBones = self.getSpineJoints()
|
|
|
|
cmds.parent(orientNeck, neckControl)
|
|
cmds.parent(orientShoulder, "driver_spine_0" + str(len(numSpineBones)))
|
|
cmds.parent(orientBody, "body_anim")
|
|
|
|
|
|
#add the fk orient attr to the head control
|
|
cmds.select(headControl)
|
|
cmds.addAttr(longName= "fkOrientation", at = 'enum', en = "neck:shoulder:body:world:", keyable = True)
|
|
|
|
|
|
#setup sdks for controlling constraint weight
|
|
cmds.setAttr(headControl + ".fkOrientation", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientNeck + "W0", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W1", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W2", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W3", 0)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientNeck + "W0", fkHeadOrientConstraint + "." + orientShoulder + "W1", fkHeadOrientConstraint + "." + orientBody + "W2", fkHeadOrientConstraint + "." + orientWorld + "W3"], cd = headControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(headControl + ".fkOrientation", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientNeck + "W0", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W1", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W2", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W3", 0)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientNeck + "W0", fkHeadOrientConstraint + "." + orientShoulder + "W1", fkHeadOrientConstraint + "." + orientBody + "W2", fkHeadOrientConstraint + "." + orientWorld + "W3"], cd = headControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(headControl + ".fkOrientation", 2)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientNeck + "W0", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W1", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W2", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W3", 0)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientNeck + "W0", fkHeadOrientConstraint + "." + orientShoulder + "W1", fkHeadOrientConstraint + "." + orientBody + "W2", fkHeadOrientConstraint + "." + orientWorld + "W3"], cd = headControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
|
|
cmds.setAttr(headControl + ".fkOrientation", 3)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientNeck + "W0", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W1", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W2", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W3", 1)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientNeck + "W0", fkHeadOrientConstraint + "." + orientShoulder + "W1", fkHeadOrientConstraint + "." + orientBody + "W2", fkHeadOrientConstraint + "." + orientWorld + "W3"], cd = headControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(headControl + ".fkOrientation", 0)
|
|
|
|
return [orientMaster, orientNeck, orientShoulder, orientBody, orientWorld]
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def setupNeckOrientation(self, neckControl):
|
|
|
|
#create head orient controls (neck, shoulder, body, world)
|
|
orientMaster = cmds.group(empty = True, name = "neck_fk_orient_master")
|
|
constraint = cmds.parentConstraint("driver_neck_01", orientMaster)[0]
|
|
cmds.delete(constraint)
|
|
|
|
orientShoulder = cmds.duplicate(orientMaster, po = True, name = "neck_fk_orient_shoulder")[0]
|
|
orientBody = cmds.duplicate(orientMaster, po = True, name = "neck_fk_orient_body")[0]
|
|
orientWorld = cmds.duplicate(orientMaster, po = True, name = "neck_fk_orient_world")[0]
|
|
|
|
fkHeadOrientConstraint = cmds.orientConstraint([orientShoulder, orientBody, orientWorld], orientMaster)[0]
|
|
|
|
numSpineBones = self.getSpineJoints()
|
|
|
|
cmds.parent(orientShoulder, "driver_spine_0" + str(len(numSpineBones)))
|
|
cmds.parent(orientBody, "body_anim")
|
|
|
|
|
|
#add the fk orient attr to the head control
|
|
cmds.select(neckControl)
|
|
cmds.addAttr(longName= "fkOrientation", at = 'enum', en = "shoulder:body:world:", keyable = True)
|
|
|
|
|
|
#setup sdks for controlling constraint weight
|
|
cmds.setAttr(neckControl + ".fkOrientation", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W0", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W1", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W2", 0)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientShoulder + "W0", fkHeadOrientConstraint + "." + orientBody + "W1", fkHeadOrientConstraint + "." + orientWorld + "W2"], cd = neckControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(neckControl + ".fkOrientation", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W0", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W1", 1)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W2", 0)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientShoulder + "W0", fkHeadOrientConstraint + "." + orientBody + "W1", fkHeadOrientConstraint + "." + orientWorld + "W2"], cd = neckControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(neckControl + ".fkOrientation", 2)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientShoulder + "W0", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientBody + "W1", 0)
|
|
cmds.setAttr(fkHeadOrientConstraint + "." + orientWorld + "W2", 1)
|
|
|
|
cmds.setDrivenKeyframe([fkHeadOrientConstraint + "." + orientShoulder + "W0", fkHeadOrientConstraint + "." + orientBody + "W1", fkHeadOrientConstraint + "." + orientWorld + "W2"], cd = neckControl + ".fkOrientation", itt = "linear", ott = "linear")
|
|
|
|
cmds.setAttr(neckControl + ".fkOrientation", 0)
|
|
|
|
return [orientMaster, orientShoulder, orientBody, orientWorld]
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def rigLeafJoints(self):
|
|
|
|
#find attrs on the skeleton settings node
|
|
createdControls = []
|
|
|
|
attrs = cmds.listAttr("Skeleton_Settings")
|
|
for attr in attrs:
|
|
if attr.find("extraJoint") == 0:
|
|
attribute = cmds.getAttr("Skeleton_Settings." + attr, asString = True)
|
|
jointType = attribute.partition("/")[2].partition("/")[0]
|
|
name = attribute.rpartition("/")[2]
|
|
parent = attribute.partition("/")[0]
|
|
|
|
if parent.find("(") != -1:
|
|
parent = parent.partition(" (")[0]
|
|
|
|
|
|
if jointType == "leaf":
|
|
attrs = name.partition("(")[2].partition(")")[0]
|
|
name = name.partition(" (")[0]
|
|
|
|
#create the control
|
|
control = cmds.curve(name = (name + "_anim"), d = 1, p = [(0, 0, 1), (0, 0.5, 0.866025), (0, 0.866025, 0.5), (0, 1, 0), (0, 0.866025, -0.5), (0, 0.5, -0.866025), (0, 0, -1), (0, -0.5, -0.866025), (0, -0.866025, -0.5), (0, -1, 0), (0, -0.866025, 0.5), (0, -0.5, 0.866025), (0, 0, 1), (0.707107, 0, 0.707107), (1, 0, 0), (0.707107, 0, -0.707107), (0, 0, -1), (-0.707107, 0, -0.707107), (-1, 0, 0), (-0.866025, 0.5, 0), (-0.5, 0.866025, 0), (0, 1, 0), (0.5, 0.866025, 0), (0.866025, 0.5, 0), (1, 0, 0), (0.866025, -0.5, 0), (0.5, -0.866025, 0), (0, -1, 0), (-0.5, -0.866025, 0), (-0.866025, -0.5, 0), (-1, 0, 0), (-0.707107, 0, 0.707107), (0, 0, 1)])
|
|
|
|
#scale up
|
|
cmds.setAttr(control + ".sx", 9)
|
|
cmds.setAttr(control + ".sy", 9)
|
|
cmds.setAttr(control + ".sz", 9)
|
|
|
|
#freeze transforms
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#position control
|
|
constraint = cmds.parentConstraint("driver_" + name, control)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create the control group
|
|
ctrlGrp = cmds.group(empty = True, name = (name + "_anim_grp"))
|
|
constraint = cmds.parentConstraint("driver_" + name, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create space switcher group
|
|
spaceSwitcherFollow = cmds.duplicate(ctrlGrp, po = True, name = (name + "_anim_space_switcher_follow"))[0]
|
|
spaceSwitcher = cmds.duplicate(ctrlGrp, po = True, name = (name + "_anim_space_switcher"))[0]
|
|
|
|
#create the top parent group
|
|
topParent = cmds.duplicate(ctrlGrp, po = True, name = (name + "_parent_grp"))[0]
|
|
#parent control to group
|
|
cmds.parent(spaceSwitcher, spaceSwitcherFollow)
|
|
cmds.parent(spaceSwitcherFollow, topParent)
|
|
cmds.parent(ctrlGrp, spaceSwitcher)
|
|
cmds.parent(control, ctrlGrp)
|
|
|
|
#constrain driver joint to control
|
|
cmds.parentConstraint(control, "driver_" + name)
|
|
cmds.connectAttr(control + ".scale", "driver_" + name + ".scale")
|
|
|
|
#lock attrs depending on type of control
|
|
lockAttrs = []
|
|
if attrs == "TR":
|
|
lockAttrs = [".v"]
|
|
|
|
if attrs == "T":
|
|
lockAttrs = [".v", ".rx", ".ry", ".rz"]
|
|
|
|
if attrs == "R":
|
|
lockAttrs = [".v", ".tx", ".ty", ".tz"]
|
|
|
|
|
|
for attr in lockAttrs:
|
|
cmds.setAttr(control + attr, lock = True, keyable = False)
|
|
|
|
|
|
#parent constrain the topParent to the parent of the control
|
|
cmds.parentConstraint("driver_" + parent, topParent, mo = True)
|
|
|
|
|
|
|
|
#color the control
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
#add the topParent to the createdControls list
|
|
createdControls.append(topParent)
|
|
|
|
return createdControls
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def rigJiggleJoints(self):
|
|
|
|
|
|
#find attrs on the skeleton settings node
|
|
createdControls = []
|
|
|
|
attrs = cmds.listAttr("Skeleton_Settings")
|
|
for attr in attrs:
|
|
if attr.find("extraJoint") == 0:
|
|
attribute = cmds.getAttr("Skeleton_Settings." + attr, asString = True)
|
|
jointType = attribute.partition("/")[2].partition("/")[0]
|
|
name = attribute.rpartition("/")[2]
|
|
parent = attribute.partition("/")[0]
|
|
|
|
if jointType == "jiggle":
|
|
|
|
#duplicate the driver joint
|
|
jiggleStart = cmds.duplicate("driver_" + name, po = True, name = "rig_" + name + "_start")[0]
|
|
cmds.parent(jiggleStart, world = True)
|
|
|
|
jiggleEnd = cmds.duplicate(jiggleStart, po = True, name = "rig_" + name + "_end")[0]
|
|
|
|
cmds.parent(jiggleEnd, jiggleStart)
|
|
|
|
#move jiggleEnd down a bit in up axis
|
|
scaleFactor = self.getScaleFactor()
|
|
jointPos = cmds.xform(jiggleStart, q = True, ws = True, t = True)
|
|
cmds.xform(jiggleEnd, ws = True, t = (jointPos[0], jointPos[1], (jointPos[2] - (25 * scaleFactor))))
|
|
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create curve on joint chain
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
|
|
joints = [jiggleStart, jiggleEnd]
|
|
|
|
positions = []
|
|
|
|
#get the world space positions of each joint, and create a curve using those positions
|
|
for i in range(int(len(joints))):
|
|
pos = cmds.xform(joints[i], q = True, ws = True, t = True)
|
|
positions.append(pos)
|
|
|
|
createCurveCommand = "curve -d 1"
|
|
for pos in positions:
|
|
xPos = pos[0]
|
|
yPos = pos[1]
|
|
zPos = pos[2]
|
|
createCurveCommand += " -p " + str(xPos) + " " + str(yPos) + " " + str(zPos)
|
|
|
|
for i in range(int(len(positions))):
|
|
createCurveCommand += " -k " + str(i)
|
|
|
|
curve = mel.eval(createCurveCommand)
|
|
curve = cmds.rename(curve, name + "_dynCurve")
|
|
cmds.setAttr(curve + ".v", 0)
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create hair system
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
|
|
cmds.select(curve)
|
|
|
|
#find all hair systems in scene
|
|
hairSystems = cmds.ls(type = "hairSystem")
|
|
hairSys = ""
|
|
|
|
|
|
#create the hair system and make the stiffness uniform
|
|
madeHairCurve = True
|
|
if hairSys == "":
|
|
hairSys = cmds.createNode("hairSystem")
|
|
cmds.removeMultiInstance(hairSys + ".stiffnessScale[1]", b = True)
|
|
cmds.setAttr(hairSys + ".clumpWidth", 0.0)
|
|
cmds.connectAttr("time1.outTime", hairSys + ".currentTime")
|
|
|
|
hairSysParent = cmds.listRelatives(hairSys, parent = True)
|
|
hairSysParent = cmds.rename(hairSysParent, name + "_hairSystem")
|
|
cmds.setAttr(hairSysParent + ".v", 0)
|
|
hairSys = name + "_hairSystemShape"
|
|
|
|
#create the hair follicle
|
|
hair = cmds.createNode("follicle")
|
|
cmds.setAttr(hair + ".parameterU", 0)
|
|
cmds.setAttr(hair + ".parameterV", 0)
|
|
hairTransforms = cmds.listRelatives(hair, p = True)
|
|
hairDag = hairTransforms[0]
|
|
hairDag = cmds.rename(hairDag, name + "_follicle")
|
|
hair = name + "_follicleShape"
|
|
|
|
cmds.setAttr(hairDag + ".v", 0)
|
|
cmds.setAttr(hair + ".startDirection", 1)
|
|
|
|
#get the curve CVs and set follicle degree to 1 if CVs are less than 3
|
|
curveCVs = cmds.getAttr(curve + ".cp", size = True)
|
|
if curveCVs < 3:
|
|
cmds.setAttr(hair + ".degree", 1)
|
|
|
|
#parent the curve to the follicle and connect the curve's worldspace[0] to the follicle startPos
|
|
cmds.parent(curve, hairDag, relative = True)
|
|
cmds.connectAttr(curve + ".worldSpace[0]", hair + ".startPosition")
|
|
|
|
#connect the hair follicle to the hair system
|
|
cmds.connectAttr(hair + ".outHair", hairSys + ".inputHair[0]")
|
|
|
|
#create a new curve and connect the follicle's outCurve attr to the new curve
|
|
cmds.connectAttr(hairSys + ".outputHair[0]", hair + ".currentPosition")
|
|
crv = cmds.createNode("nurbsCurve")
|
|
crvParent = cmds.listRelatives(crv, parent = True)[0]
|
|
crvParent = cmds.rename(crvParent, name + "_track_rt_curve")
|
|
crv = name + "_track_rt_curveShape"
|
|
cmds.setAttr(crvParent + ".v", 0)
|
|
|
|
cmds.connectAttr(hair + ".outCurve", crv + ".create")
|
|
|
|
#set the hair follicle attrs
|
|
if len(hairDag) > 0:
|
|
cmds.setAttr(hairDag + ".pointLock", 3)
|
|
cmds.setAttr(hairDag + ".restPose", 1)
|
|
|
|
cmds.select(hairSys)
|
|
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create Spline Handle for the selected chain and the duplicated curve. the original is driven by hair
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
|
|
ikNodes = cmds.ikHandle(sol = "ikSplineSolver", ccv = False, pcv = False, snc = True, sj = jiggleStart, ee = jiggleEnd, c = crv)[0]
|
|
cmds.setAttr(ikNodes + ".v", 0)
|
|
ikNodes = cmds.rename(ikNodes, name + "_dynChain_ikHandle")
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create a duplicate joint chain for manual animation
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
|
|
dupeChain = cmds.duplicate(jiggleStart, rr = True, rc = True)
|
|
dupeStartJoint = dupeChain[0]
|
|
|
|
dupeJoints = cmds.listRelatives(dupeStartJoint, ad = True)
|
|
joints = cmds.listRelatives(jiggleStart, ad = True)
|
|
|
|
#rename duped joints and connect real joints to duped joints
|
|
for i in range(int(len(joints))):
|
|
if cmds.objectType(dupeJoints[i], isType = 'joint'):
|
|
cmds.rename(dupeJoints[i], "ANIM_" + joints[i])
|
|
cmds.connectAttr("ANIM_" + joints[i] + ".r", joints[i] + ".r", force = True)
|
|
|
|
else:
|
|
cmds.delete(dupeJoints[i])
|
|
|
|
#connect up start joint to ANIM start joint
|
|
cmds.connectAttr(dupeStartJoint + ".t", jiggleStart + ".t")
|
|
cmds.connectAttr(dupeStartJoint + ".r", jiggleStart + ".r")
|
|
cmds.connectAttr(dupeStartJoint + ".s", jiggleStart + ".s")
|
|
|
|
dupeStartJoint = cmds.rename(dupeStartJoint, "ANIM_" + jiggleStart)
|
|
#cmds.parent(dupeStartJoint, world = True)
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create skinCluster between duplicate curve and animation joint chain(dupe chain)
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
cmds.select(dupeStartJoint, hi = True)
|
|
dupeSkel = cmds.ls(sl = True, type = "joint")
|
|
cmds.select(curve)
|
|
cmds.select(dupeSkel, add = True)
|
|
skinCluster = cmds.skinCluster(tsb = True, mi = 3, dr = 4)
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create the control that has all of our dynamic attrs
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
control = self.createControl("square", 15, name + "_anim")
|
|
constraint = cmds.parentConstraint(jiggleStart, control)[0]
|
|
cmds.delete(constraint)
|
|
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
constraint = cmds.parentConstraint(jiggleStart, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.parentConstraint(control, dupeStartJoint)
|
|
|
|
#lock attrs
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#add attrs
|
|
cmds.select(control)
|
|
|
|
cmds.addAttr(ln = "___DYNAMICS___", at = "double", keyable = True)
|
|
cmds.setAttr(control + ".___DYNAMICS___", lock = True)
|
|
cmds.addAttr(ln = "chainAttach", at = "enum", en = "No Attach:Base:Tip:Both End:", dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainStartEnvelope", at = "double", min = 0, max = 1, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainStartFrame", at = "double", dv = 1, keyable = True)
|
|
|
|
cmds.addAttr(ln = "___BEHAVIOR___", at = "double", keyable = True)
|
|
cmds.setAttr(control + ".___BEHAVIOR___", lock = True)
|
|
cmds.addAttr(ln = "chainStiffness", at = "double", min = 0, dv = .1, keyable = True)
|
|
cmds.addAttr(ln = "chainDamping", at = "double", min = 0, dv = 0.2, keyable = True)
|
|
cmds.addAttr(ln = "chainGravity", at = "double", min = 0, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainIteration", at = "long", min = 0, dv = 1, keyable = True)
|
|
|
|
cmds.addAttr(ln = "___COLLISIONS___", at = "double", keyable = True)
|
|
cmds.setAttr(control + ".___COLLISIONS___", lock = True)
|
|
cmds.addAttr(ln = "chainCollide", at = "bool", dv = 0, keyable = True)
|
|
cmds.addAttr(ln = "chainWidthBase", at = "double", min = 0, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainWidthExtremity", at = "double", min = 0, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainCollideGround", at = "bool", dv = 0, keyable = True)
|
|
cmds.addAttr(ln = "chainCollideGroundHeight", at = "double", dv = 0, keyable = True)
|
|
|
|
|
|
#connect attrs
|
|
cmds.connectAttr(control + ".chainStartEnvelope", ikNodes + ".ikBlend")
|
|
cmds.connectAttr(control + ".chainAttach", hair + ".pointLock")
|
|
cmds.connectAttr(control + ".chainStartFrame", hairSys + ".startFrame")
|
|
cmds.connectAttr(control + ".chainStiffness", hairSys + ".stiffness")
|
|
cmds.connectAttr(control + ".chainDamping", hairSys + ".damp")
|
|
cmds.connectAttr(control + ".chainGravity", hairSys + ".gravity")
|
|
cmds.connectAttr(control + ".chainIteration", hairSys + ".iterations")
|
|
cmds.connectAttr(control + ".chainCollide", hairSys + ".collide")
|
|
cmds.connectAttr(control + ".chainWidthBase", hairSys + ".clumpWidth")
|
|
cmds.connectAttr(control + ".chainWidthExtremity", hairSys + ".clumpWidthScale[1].clumpWidthScale_FloatValue")
|
|
cmds.connectAttr(control + ".chainCollideGround", hairSys + ".collideGround")
|
|
cmds.connectAttr(control + ".chainCollideGroundHeight", hairSys + ".groundHeight")
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Create the expression for real time
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
track_RealTime = cmds.spaceLocator(name = name + "_track_rt_loc")[0]
|
|
cmds.pointConstraint(dupeSkel[len(dupeSkel) -1], track_RealTime)
|
|
connections = cmds.listConnections(hairSys + ".currentTime", p = True, c = True)
|
|
cmds.disconnectAttr(connections[1], connections[0])
|
|
|
|
expressionString = "if(frame!= " + hairSys + ".startFrame)\n\t" + hairSys + ".currentTime = " + hairSys + ".currentTime + 1 + " + track_RealTime + ".tx - " + track_RealTime + ".tx + " + track_RealTime + ".ty - " + track_RealTime + ".ty + " + track_RealTime + ".tz - " + track_RealTime + ".tz + " + control + ".chainWidthBase - "+ control + ".chainWidthBase + "+ control + ".chainWidthExtremity - "+ control + ".chainWidthExtremity + " + control + ".chainGravity - "+ control + ".chainGravity;\n" +"else\n\t" + hairSys + ".currentTime = " + hairSys + ".startFrame;"
|
|
cmds.expression(name = "EXP_" + hairSys + "_TRACK_RealTime", string = expressionString)
|
|
cmds.setAttr(track_RealTime + ".v", 0)
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Set Defaults
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
cmds.setAttr(hairSys + ".drawCollideWidth", 1)
|
|
cmds.setAttr(hairSys + ".widthDrawSkip", 0)
|
|
cmds.setAttr(hair + ".degree", 1)
|
|
|
|
cmds.parentConstraint("driver_" + parent, ctrlGrp, mo = True)
|
|
|
|
if cmds.objExists("dynHairChain") == False:
|
|
cmds.group(empty = True, name = "dynHairChain")
|
|
|
|
if cmds.objExists(jiggleStart + "_HairControls") == False:
|
|
group = cmds.group([ikNodes, hairSys, hair, track_RealTime, ctrlGrp, crvParent], name = jiggleStart + "_HairControls")
|
|
|
|
else:
|
|
cmds.parent([ikNodes, hairSys, hair, ctrlGrp,crvParent ], jiggleStart + "_HairControls")
|
|
|
|
cmds.parent(group, "dynHairChain")
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Cleanup
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
jointsGrp = cmds.group(empty = True, name = name + "_jiggle_jointsGrp")
|
|
createdControls.append(jointsGrp)
|
|
cmds.parent([jiggleStart, dupeStartJoint], jointsGrp)
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
#constrain driver joints
|
|
cmds.parentConstraint(jiggleStart, "driver_" + name, mo = True)
|
|
|
|
|
|
#return top level group
|
|
return createdControls
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def rigCustomJointChains(self):
|
|
|
|
|
|
#find attrs on the skeleton settings node
|
|
createdControls = []
|
|
rootControl = ""
|
|
attrs = cmds.listAttr("Skeleton_Settings")
|
|
for attr in attrs:
|
|
if attr.find("extraJoint") == 0:
|
|
attribute = cmds.getAttr("Skeleton_Settings." + attr, asString = True)
|
|
jointType = attribute.partition("/")[2].partition("/")[0]
|
|
name = attribute.rpartition("/")[2]
|
|
parent = attribute.partition("/")[0]
|
|
|
|
if jointType == "chain":
|
|
|
|
numJointsInChain = name.partition("(")[2].partition(")")[0]
|
|
name = name.partition(" (")[0]
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#FK RIG
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
fkJoints = []
|
|
frameCacheNodes = []
|
|
fkRootGrp = ""
|
|
|
|
for i in range(int(numJointsInChain)):
|
|
jointNum = i + 1
|
|
if jointNum == 1:
|
|
firstControl = "fk_" + name + "_0" + str(jointNum) + "_anim"
|
|
|
|
#create and position the joint
|
|
if cmds.objExists("rig_fk_" + name + "_0" + str(jointNum)):
|
|
cmds.delete("rig_fk_" + name + "_0" + str(jointNum))
|
|
|
|
cmds.select(clear = True)
|
|
joint = cmds.joint(name = "rig_fk_" + name + "_0" + str(jointNum))
|
|
cmds.select(clear = True)
|
|
fkJoints.append(joint)
|
|
|
|
constraint = cmds.parentConstraint("driver_" + name + "_0" + str(jointNum), joint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create the control and position
|
|
control = self.createControl("circle", 15, "fk_" + name + "_0" + str(jointNum) + "_anim")
|
|
cmds.setAttr(control + ".rx", 90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
constraint = cmds.parentConstraint(joint, control)[0]
|
|
cmds.delete(constraint)
|
|
cmds.makeIdentity(control, t = 0, r = 1, s = 0, apply = True)
|
|
|
|
#cmds.setAttr(control + ".rz", -90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#create the control grp and parent the control to the group
|
|
ctrlGrp = cmds.group(empty = True, name = "fk_" + name + "_0" + str(jointNum) + "_grp")
|
|
if i == 0:
|
|
fkRootGrp = ctrlGrp
|
|
|
|
constraint = cmds.parentConstraint(joint, ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#duplicate the ctrl grp for the lag mode
|
|
lagGrp = cmds.duplicate(ctrlGrp, po = True, name = "fk_" + name + "_0" + str(jointNum) + "_lag_grp")[0]
|
|
cmds.parent(lagGrp, ctrlGrp)
|
|
cmds.parent(control, lagGrp)
|
|
|
|
|
|
#color the control
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
if jointNum != 1:
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
|
|
else:
|
|
#aliasAttr one of the scale axis and connect the other two to that one
|
|
cmds.aliasAttr("global_scale", control + ".scaleZ")
|
|
cmds.connectAttr(control + ".scaleZ", control + ".scaleX")
|
|
cmds.connectAttr(control + ".scaleZ", control + ".scaleY")
|
|
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
|
|
|
|
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#parent the joint to the control
|
|
cmds.parent(joint, control)
|
|
|
|
|
|
|
|
#TEMP!
|
|
cmds.parentConstraint(joint, "driver_" + name + "_0" + str(jointNum))
|
|
|
|
|
|
#add attr to root joint of chain for turning on "lag" mode
|
|
|
|
if i == 0:
|
|
rootControl = ctrlGrp
|
|
cmds.select(control)
|
|
cmds.addAttr(longName='lagMode', defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
cmds.addAttr(longName='lagValue', defaultValue= 3, minValue= 0, maxValue=100, keyable = False)
|
|
|
|
#setup lag mode node chain
|
|
frameCacheX = cmds.createNode("frameCache")
|
|
frameCacheX = cmds.rename(frameCacheX, name + "_frameCacheX")
|
|
frameCacheY = cmds.createNode("frameCache")
|
|
frameCacheY = cmds.rename(frameCacheY, name + "_frameCacheY")
|
|
frameCacheZ = cmds.createNode("frameCache")
|
|
frameCacheZ = cmds.rename(frameCacheZ, name + "_frameCacheZ")
|
|
frameCacheNodes.append(frameCacheX)
|
|
frameCacheNodes.append(frameCacheY)
|
|
frameCacheNodes.append(frameCacheZ)
|
|
|
|
|
|
|
|
|
|
#create a switcher node
|
|
switchNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = name + "_switcherNode")
|
|
frameCacheNodes.append(switchNode)
|
|
cmds.connectAttr(control + ".rotateX", switchNode + ".input1X")
|
|
cmds.connectAttr(control + ".lagMode", switchNode + ".input2X")
|
|
|
|
cmds.connectAttr(control + ".rotateY", switchNode + ".input1Y")
|
|
cmds.connectAttr(control + ".lagMode", switchNode + ".input2Y")
|
|
|
|
cmds.connectAttr(control + ".rotateZ", switchNode + ".input1Z")
|
|
cmds.connectAttr(control + ".lagMode", switchNode + ".input2Z")
|
|
|
|
cmds.connectAttr(switchNode + ".outputX", frameCacheX + ".stream")
|
|
cmds.connectAttr(switchNode + ".outputY", frameCacheY + ".stream")
|
|
cmds.connectAttr(switchNode + ".outputZ", frameCacheZ + ".stream")
|
|
|
|
mainControl = control
|
|
|
|
|
|
|
|
|
|
#setup FK hierarchy
|
|
lagValue = cmds.getAttr(mainControl + ".lagValue")
|
|
if i != 0:
|
|
cmds.parent(ctrlGrp, lastControl)
|
|
|
|
#connect framecache results to lag Grps
|
|
|
|
mode = "past"
|
|
|
|
cmds.connectAttr(frameCacheX + "." + mode + "[" + str(int(abs(lagValue)) * (i + 1)) + "]", lagGrp + ".rotateX")
|
|
cmds.connectAttr(frameCacheY + "." + mode + "[" + str(int(abs(lagValue)) * (i + 1)) + "]", lagGrp + ".rotateY")
|
|
cmds.connectAttr(frameCacheZ + "." + mode + "[" + str(int(abs(lagValue)) * (i + 1)) + "]", lagGrp + ".rotateZ")
|
|
|
|
|
|
lastControl = control
|
|
|
|
|
|
|
|
#add nodes to container
|
|
lagContainer = cmds.container(name = (name + "_lag_container"))
|
|
for node in frameCacheNodes:
|
|
cmds.container(lagContainer, edit = True, addNode = node, includeNetwork = True, ihb = True)
|
|
|
|
#constrain root of fk chain to driver's parent joint
|
|
parent = cmds.listRelatives("driver_" + name + "_01", parent = True)[0]
|
|
cmds.parentConstraint(parent, rootControl, mo = True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#IK RIG
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
|
|
|
|
ikJoints = []
|
|
clusterControls = []
|
|
for i in range(int(numJointsInChain)):
|
|
jointNum = i + 1
|
|
|
|
#create and position the joint
|
|
if cmds.objExists("rig_ik_" + name + "_0" + str(jointNum)):
|
|
cmds.delete("rig_ik_" + name + "_0" + str(jointNum))
|
|
|
|
|
|
cmds.select(clear = True)
|
|
joint = cmds.joint(name = "rig_ik_" + name + "_0" + str(jointNum))
|
|
cmds.select(clear = True)
|
|
ikJoints.append(joint)
|
|
|
|
constraint = cmds.parentConstraint("driver_" + name + "_0" + str(jointNum), joint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#recreate the joint heirarchy
|
|
if i != 0:
|
|
cmds.parent(joint, lastJoint)
|
|
|
|
lastJoint = joint
|
|
|
|
|
|
|
|
startJoint = ikJoints[0]
|
|
endJoint = ikJoints[(len(ikJoints) - 1)]
|
|
cmds.makeIdentity(startJoint, r = 1, t = 0, s = 0, apply = True)
|
|
|
|
#create the spline IK
|
|
ikNodes = cmds.ikHandle(sj = startJoint, ee = endJoint, sol = "ikSplineSolver", createCurve = True, simplifyCurve = False, parentCurve = False, name = str(ikJoints[0]) + "_splineIK")
|
|
ikHandle = ikNodes[0]
|
|
ikCurve = ikNodes[2]
|
|
ikCurve = cmds.rename(ikCurve, name + "_splineIK_curve")
|
|
cmds.setAttr(ikCurve + ".inheritsTransform", 0)
|
|
cmds.setAttr(ikHandle + ".v", 0)
|
|
cmds.setAttr(ikCurve + ".v", 0)
|
|
|
|
#create the three joints to skin the curve to
|
|
|
|
if int(numJointsInChain) <= 6:
|
|
#3 joints for the curve
|
|
skinJoints = 3
|
|
|
|
if int(numJointsInChain) >= 7:
|
|
#add 1 joint to the curve every odd number
|
|
oddJoints = []
|
|
for i in range(7, int(numJointsInChain)):
|
|
if i % 2 != 0:
|
|
oddJoints.append(i)
|
|
|
|
#now we have a list of the total number of odd joints in our numJointsInChain. Take the length of the list + 3 to get the joints to create for our curve
|
|
skinJoints = 3 + len(oddJoints)
|
|
|
|
|
|
#create the joints to skin to the curve
|
|
curveJoints = []
|
|
if skinJoints == 3:
|
|
botJoint = cmds.duplicate(startJoint, name = name + "_splineIK_skin_joint_1", parentOnly = True)[0]
|
|
topJoint = cmds.duplicate(endJoint, name = name + "_splineIK_skin_joint_2", parentOnly = True)[0]
|
|
midJoint = cmds.duplicate(topJoint, name = name + "_splineIK_skin_joint_3", parentOnly = True)[0]
|
|
|
|
cmds.parent([botJoint, topJoint,midJoint], world = True)
|
|
|
|
constraint = cmds.pointConstraint([botJoint, topJoint], midJoint)[0]
|
|
cmds.delete(constraint)
|
|
curveJoints.append(botJoint)
|
|
curveJoints.append(topJoint)
|
|
curveJoints.append(midJoint)
|
|
|
|
else:
|
|
for i in range(skinJoints):
|
|
if i == 0:
|
|
joint = cmds.duplicate(ikJoints[i], name = name + "_splineIK_skin_joint_" + str(i), parentOnly = True)[0]
|
|
curveJoints.append(joint)
|
|
|
|
else:
|
|
joint = cmds.duplicate(ikJoints[i + i], name = name + "_splineIK_skin_joint_" + str(i), parentOnly = True)[0]
|
|
curveJoints.append(joint)
|
|
|
|
|
|
#parent all of the joints to the world
|
|
for joint in curveJoints:
|
|
try:
|
|
cmds.parent(joint, world = True)
|
|
except:
|
|
print joint
|
|
pass
|
|
|
|
|
|
|
|
|
|
#skin the joints to the curve
|
|
|
|
cmds.select(curveJoints)
|
|
cmds.skinCluster( curveJoints, ikCurve, toSelectedBones = True )
|
|
|
|
#find number of CVs on created curve
|
|
numSpans = cmds.getAttr(ikCurve + ".spans")
|
|
degree = cmds.getAttr(ikCurve + ".degree")
|
|
numCVs = numSpans + degree
|
|
|
|
#for each cv, create a cluster, then create the control
|
|
clusters = []
|
|
for cv in range(int(numCVs)):
|
|
cmds.select(ikCurve + ".cv[" + str(cv) + "]" )
|
|
cluster = cmds.cluster(name = name + "_cluster_" + str(cv))
|
|
clusters.append(cluster)
|
|
|
|
|
|
#cleanup clusters list
|
|
cmds.delete(clusters[1])
|
|
cmds.delete(clusters[(len(clusters) - 2)])
|
|
clusters.pop(1)
|
|
clusters.pop(len(clusters) - 2)
|
|
clusterNodes = []
|
|
ikAnimGrps = []
|
|
|
|
#create the controls for each cluster
|
|
for i in range(int(len(clusters))):
|
|
|
|
cluster = cmds.rename(clusters[i][1], name + "_cluster_" + str(i))
|
|
clusterNodes.append(cluster)
|
|
|
|
cmds.setAttr(cluster + ".v", 0)
|
|
|
|
control = cmds.spaceLocator(name = name + "_cv_" + str(i) + "_anim")[0]
|
|
constraint = cmds.parentConstraint(ikJoints[i], control)[0]
|
|
cmds.delete(constraint)
|
|
clusterControls.append(control)
|
|
|
|
|
|
#scale up the locator
|
|
scaleFactor = self.getScaleFactor()
|
|
shape = cmds.listRelatives(control, shapes = True)[0]
|
|
cmds.setAttr(shape + ".localScaleX", 15 * scaleFactor)
|
|
cmds.setAttr(shape + ".localScaleY", 15 * scaleFactor)
|
|
cmds.setAttr(shape + ".localScaleZ", 15 * scaleFactor)
|
|
|
|
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
ikAnimGrps.append(ctrlGrp)
|
|
|
|
constraint = cmds.pointConstraint(ikJoints[i], ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#point constrain the ctrlGrp to the corresponding joint
|
|
cmds.pointConstraint(ikJoints[i], ctrlGrp)
|
|
|
|
#connect the clusters translate to the control's so the cluster will move when the control does
|
|
cmds.connectAttr(control + ".translate", cluster + ".translate")
|
|
|
|
#color controls
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
|
|
#hookup stretch to joint scale
|
|
cmds.select(ikCurve)
|
|
curveInfoNode = cmds.arclen(cmds.ls(sl = True), ch = True )
|
|
originalLength = cmds.getAttr(curveInfoNode + ".arcLength")
|
|
|
|
#create the multiply/divide node that will get the scale factor
|
|
divideNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = name + "_divideNode")
|
|
cmds.setAttr(divideNode + ".operation", 2)
|
|
cmds.setAttr(divideNode + ".input2X", originalLength)
|
|
|
|
#create the blendcolors node
|
|
blenderNode = cmds.shadingNode("blendColors", asUtility = True, name = name + "_blenderNode")
|
|
cmds.setAttr(blenderNode + ".color2R", 1)
|
|
|
|
#connect attrs
|
|
cmds.connectAttr(curveInfoNode + ".arcLength", divideNode + ".input1X")
|
|
|
|
|
|
for joint in ikJoints:
|
|
cmds.connectAttr(divideNode + ".outputX", joint + ".scaleX")
|
|
cmds.connectAttr(divideNode + ".outputX", joint + ".scaleY")
|
|
cmds.connectAttr(divideNode + ".outputX", joint + ".scaleZ")
|
|
|
|
|
|
#create the control curves for the ik curve joints
|
|
i = 1
|
|
ikControls = []
|
|
for joint in curveJoints:
|
|
if joint != curveJoints[0]:
|
|
control = self.createControl("circle", 25, name + "_ik_" + str(i) + "_anim")
|
|
cmds.setAttr(control + ".rx", 90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
ikControls.append(control)
|
|
|
|
#position
|
|
constraint = cmds.parentConstraint(joint, control)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create grp
|
|
controlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
constraint = cmds.parentConstraint(joint, controlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#setup hierarchy
|
|
cmds.parent(control, controlGrp)
|
|
cmds.parent(joint, control)
|
|
|
|
#color controls
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
#lock attrs
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
else:
|
|
#find parent of base joint and constrain base joint to the parent
|
|
parent = cmds.listRelatives("driver_" + name + "_01", parent = True)[0]
|
|
|
|
|
|
#create a control for the base
|
|
control = self.createControl("circle", 30, name + "_ik_base_anim")
|
|
cmds.setAttr(control + ".rx", 90)
|
|
cmds.makeIdentity(control, t = 1, r = 1, s = 1, apply = True)
|
|
|
|
#position
|
|
constraint = cmds.parentConstraint(joint, control)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#create grp
|
|
controlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
constraint = cmds.parentConstraint(joint, controlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#setup hierarchy
|
|
cmds.parent(control, controlGrp)
|
|
cmds.parent(joint, control)
|
|
|
|
#color controls
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 17)
|
|
|
|
|
|
#lock attrs
|
|
cmds.aliasAttr("global_scale", control + ".scaleZ")
|
|
cmds.connectAttr(control + ".scaleZ", control + ".scaleX")
|
|
cmds.connectAttr(control + ".scaleZ", control + ".scaleY")
|
|
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
#hook the base control grp to the chain's parent
|
|
cmds.parentConstraint(parent, controlGrp, mo = True)
|
|
|
|
|
|
|
|
i = i + 1
|
|
|
|
#parent the other IK grp controls under the base
|
|
for control in ikControls:
|
|
grp = control + "_grp"
|
|
cmds.parent(grp, name + "_ik_base_anim")
|
|
|
|
|
|
#tip control only:
|
|
#add attr to show clusters on tip control
|
|
tipControl = ikControls[len(ikControls) - 1]
|
|
cmds.select(tipControl)
|
|
cmds.addAttr(longName=("clusterControlVis"), at = 'bool', dv = 0, keyable = True)
|
|
|
|
for control in clusterControls:
|
|
cmds.connectAttr(tipControl + ".clusterControlVis", control + ".v")
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".rx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".ry", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".rz", lock = True, keyable = False)
|
|
|
|
#set color for tip
|
|
cmds.setAttr(tipControl + ".overrideColor", 17)
|
|
|
|
#lock tip attrs
|
|
cmds.setAttr(tipControl + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(tipControl + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(tipControl + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(tipControl + ".v", lock = True, keyable = False)
|
|
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#Dynamics RIG
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
dynamicJoints = []
|
|
|
|
for i in range(int(numJointsInChain)):
|
|
jointNum = i + 1
|
|
|
|
#create and position the joint
|
|
if cmds.objExists("rig_dyn_" + name + "_0" + str(jointNum)):
|
|
cmds.delete("rig_dyn_" + name + "_0" + str(jointNum))
|
|
|
|
|
|
cmds.select(clear = True)
|
|
joint = cmds.joint(name = "rig_dyn_" + name + "_0" + str(jointNum))
|
|
if joint.find("|") == 0:
|
|
joint = joint.partition("|")[2]
|
|
|
|
cmds.select(clear = True)
|
|
dynamicJoints.append(joint)
|
|
|
|
constraint = cmds.parentConstraint("driver_" + name + "_0" + str(jointNum), joint)[0]
|
|
cmds.delete(constraint)
|
|
|
|
#recreate the joint heirarchy
|
|
if i != 0:
|
|
cmds.parent(joint, lastJoint)
|
|
|
|
|
|
lastJoint = joint
|
|
|
|
|
|
#freeze rotations on joints
|
|
cmds.makeIdentity(dynamicJoints[0], t = False, r = True, scale = False, apply = True)
|
|
|
|
|
|
#Create curve on joint chain
|
|
positions = []
|
|
|
|
#get the world space positions of each joint, and create a curve using those positions
|
|
for i in range(int(len(dynamicJoints))):
|
|
pos = cmds.xform(dynamicJoints[i], q = True, ws = True, t = True)
|
|
positions.append(pos)
|
|
|
|
createCurveCommand = "curve -d 1"
|
|
for pos in positions:
|
|
xPos = pos[0]
|
|
yPos = pos[1]
|
|
zPos = pos[2]
|
|
createCurveCommand += " -p " + str(xPos) + " " + str(yPos) + " " + str(zPos)
|
|
|
|
for i in range(int(len(positions))):
|
|
createCurveCommand += " -k " + str(i)
|
|
|
|
curve = mel.eval(createCurveCommand)
|
|
curve = cmds.rename(curve, name + "_dynCurve")
|
|
cmds.setAttr(curve + ".v", 0)
|
|
|
|
|
|
|
|
#Create hair system
|
|
cmds.select(curve)
|
|
|
|
#find all hair systems in scene
|
|
hairSystems = cmds.ls(type = "hairSystem")
|
|
hairSys = ""
|
|
|
|
|
|
#create the hair system and make the stiffness uniform
|
|
madeHairCurve = True
|
|
if hairSys == "":
|
|
hairSys = cmds.createNode("hairSystem")
|
|
cmds.removeMultiInstance(hairSys + ".stiffnessScale[1]", b = True)
|
|
cmds.setAttr(hairSys + ".clumpWidth", 0.0)
|
|
cmds.connectAttr("time1.outTime", hairSys + ".currentTime")
|
|
|
|
hairSysParent = cmds.listRelatives(hairSys, parent = True)
|
|
hairSysParent = cmds.rename(hairSysParent, name + "_hairSystem")
|
|
cmds.setAttr(hairSysParent + ".v", 0)
|
|
hairSys = name + "_hairSystemShape"
|
|
|
|
|
|
#create the hair follicle
|
|
hair = cmds.createNode("follicle")
|
|
cmds.setAttr(hair + ".parameterU", 0)
|
|
cmds.setAttr(hair + ".parameterV", 0)
|
|
hairTransforms = cmds.listRelatives(hair, p = True)
|
|
hairDag = hairTransforms[0]
|
|
hairDag = cmds.rename(hairDag, name + "_follicle")
|
|
hair = name + "_follicleShape"
|
|
|
|
cmds.setAttr(hairDag + ".v", 0)
|
|
cmds.setAttr(hair + ".startDirection", 1)
|
|
|
|
#get the curve CVs and set follicle degree to 1 if CVs are less than 3
|
|
curveCVs = cmds.getAttr(curve + ".cp", size = True)
|
|
if curveCVs < 3:
|
|
cmds.setAttr(hair + ".degree", 1)
|
|
|
|
#parent the curve to the follicle and connect the curve's worldspace[0] to the follicle startPos
|
|
cmds.parent(curve, hairDag, relative = True)
|
|
cmds.connectAttr(curve + ".worldSpace[0]", hair + ".startPosition")
|
|
|
|
#connect the hair follicle to the hair system
|
|
cmds.connectAttr(hair + ".outHair", hairSys + ".inputHair[0]")
|
|
|
|
#create a new curve and connect the follicle's outCurve attr to the new curve
|
|
cmds.connectAttr(hairSys + ".outputHair[0]", hair + ".currentPosition")
|
|
crv = cmds.createNode("nurbsCurve")
|
|
crvParent = cmds.listRelatives(crv, parent = True)[0]
|
|
crvParent = cmds.rename(crvParent, name + "_track_rt_curve")
|
|
crv = name + "_track_rt_curveShape"
|
|
cmds.setAttr(crvParent + ".v", 0)
|
|
|
|
cmds.connectAttr(hair + ".outCurve", crv + ".create")
|
|
|
|
#set the hair follicle attrs
|
|
if len(hairDag) > 0:
|
|
cmds.setAttr(hairDag + ".pointLock", 3)
|
|
cmds.setAttr(hairDag + ".restPose", 1)
|
|
|
|
cmds.select(hairSys)
|
|
|
|
|
|
|
|
#Create Spline Handle for the selected chain and the duplicated curve. the original is driven by hair
|
|
ikNodes = cmds.ikHandle(sol = "ikSplineSolver", ccv = False, pcv = False, snc = True, rootTwistMode = False, sj = dynamicJoints[0], ee = dynamicJoints[len(dynamicJoints) - 1], c = crv)[0]
|
|
cmds.setAttr(ikNodes + ".v", 0)
|
|
ikNodes = cmds.rename(ikNodes, name + "_dynChain_ikHandle")
|
|
|
|
|
|
#Create a duplicate joint chain for manual animation
|
|
dupeChain = cmds.duplicate(dynamicJoints[0], rr = True, rc = True)
|
|
dupeStartJoint = dupeChain[0]
|
|
|
|
dupeJoints = cmds.listRelatives(dupeStartJoint, ad = True)
|
|
joints = cmds.listRelatives(dynamicJoints[0], ad = True)
|
|
|
|
#rename duped joints and connect real joints to duped joints
|
|
for i in range(int(len(joints))):
|
|
if cmds.objectType(dupeJoints[i], isType = 'joint'):
|
|
cmds.rename(dupeJoints[i], "ANIM_" + joints[i])
|
|
cmds.connectAttr("ANIM_" + joints[i] + ".r", joints[i] + ".r", force = True)
|
|
|
|
else:
|
|
cmds.delete(dupeJoints[i])
|
|
|
|
#connect up start joint to ANIM start joint
|
|
cmds.connectAttr(dupeStartJoint + ".t", dynamicJoints[0] + ".t")
|
|
cmds.connectAttr(dupeStartJoint + ".r", dynamicJoints[0] + ".r")
|
|
cmds.connectAttr(dupeStartJoint + ".s", dynamicJoints[0] + ".s")
|
|
|
|
dupeStartJoint = cmds.rename(dupeStartJoint, "ANIM_" + dynamicJoints[0])
|
|
#cmds.parent(dupeStartJoint, world = True)
|
|
|
|
#Create skinCluster between duplicate curve and animation joint chain(dupe chain)
|
|
cmds.select(dupeStartJoint, hi = True)
|
|
dupeSkel = cmds.ls(sl = True, type = "joint")
|
|
cmds.select(curve)
|
|
cmds.select(dupeSkel, add = True)
|
|
skinCluster = cmds.skinCluster(tsb = True, mi = 3, dr = 4)
|
|
|
|
|
|
#Create the control that has all of our dynamic attrs
|
|
control = self.createControl("square", 30, name + "_dyn_anim")
|
|
constraint = cmds.parentConstraint(dynamicJoints[0], control)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.makeIdentity(control, r = 1, t = 0, s = 0, apply = True)
|
|
cmds.setAttr(control + ".rx", 90)
|
|
|
|
ctrlGrp = cmds.group(empty = True, name = control + "_grp")
|
|
constraint = cmds.parentConstraint(dynamicJoints[0], ctrlGrp)[0]
|
|
cmds.delete(constraint)
|
|
|
|
cmds.parent(control, ctrlGrp)
|
|
cmds.makeIdentity(control, r = 1, t = 1, s = 1, apply = True)
|
|
cmds.parentConstraint(control, dupeStartJoint)
|
|
|
|
#lock attrs
|
|
cmds.setAttr(control + ".sx", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sy", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".sz", lock = True, keyable = False)
|
|
cmds.setAttr(control + ".v", lock = True, keyable = False)
|
|
|
|
|
|
|
|
|
|
#add attrs
|
|
cmds.select(control)
|
|
|
|
cmds.addAttr(ln = "___DYNAMICS___", at = "double", keyable = True)
|
|
cmds.setAttr(control + ".___DYNAMICS___", lock = True)
|
|
cmds.addAttr(ln = "chainAttach", at = "enum", en = "No Attach:Base:Tip:Both End:", dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainStartEnvelope", at = "double", min = 0, max = 1, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainStartFrame", at = "double", dv = 1, keyable = True)
|
|
|
|
cmds.addAttr(ln = "___BEHAVIOR___", at = "double", keyable = True)
|
|
cmds.setAttr(control + ".___BEHAVIOR___", lock = True)
|
|
cmds.addAttr(ln = "chainStiffness", at = "double", min = 0, dv = .1, keyable = True)
|
|
cmds.addAttr(ln = "chainDamping", at = "double", min = 0, dv = 0.2, keyable = True)
|
|
cmds.addAttr(ln = "chainGravity", at = "double", min = 0, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainIteration", at = "long", min = 0, dv = 1, keyable = True)
|
|
|
|
cmds.addAttr(ln = "___COLLISIONS___", at = "double", keyable = True)
|
|
cmds.setAttr(control + ".___COLLISIONS___", lock = True)
|
|
cmds.addAttr(ln = "chainCollide", at = "bool", dv = 0, keyable = True)
|
|
cmds.addAttr(ln = "chainWidthBase", at = "double", min = 0, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainWidthExtremity", at = "double", min = 0, dv = 1, keyable = True)
|
|
cmds.addAttr(ln = "chainCollideGround", at = "bool", dv = 0, keyable = True)
|
|
cmds.addAttr(ln = "chainCollideGroundHeight", at = "double", dv = 0, keyable = True)
|
|
|
|
|
|
|
|
|
|
#connect attrs
|
|
cmds.connectAttr(control + ".chainStartEnvelope", ikNodes + ".ikBlend")
|
|
cmds.connectAttr(control + ".chainAttach", hair + ".pointLock")
|
|
cmds.connectAttr(control + ".chainStartFrame", hairSys + ".startFrame")
|
|
cmds.connectAttr(control + ".chainStiffness", hairSys + ".stiffness")
|
|
cmds.connectAttr(control + ".chainDamping", hairSys + ".damp")
|
|
cmds.connectAttr(control + ".chainGravity", hairSys + ".gravity")
|
|
cmds.connectAttr(control + ".chainIteration", hairSys + ".iterations")
|
|
cmds.connectAttr(control + ".chainCollide", hairSys + ".collide")
|
|
cmds.connectAttr(control + ".chainWidthBase", hairSys + ".clumpWidth")
|
|
cmds.connectAttr(control + ".chainWidthExtremity", hairSys + ".clumpWidthScale[1].clumpWidthScale_FloatValue")
|
|
cmds.connectAttr(control + ".chainCollideGround", hairSys + ".collideGround")
|
|
cmds.connectAttr(control + ".chainCollideGroundHeight", hairSys + ".groundHeight")
|
|
|
|
|
|
#Create the expression for real time
|
|
track_RealTime = cmds.spaceLocator(name = name + "_track_rt_loc")[0]
|
|
cmds.pointConstraint(dupeSkel[len(dupeSkel) -1], track_RealTime)
|
|
connections = cmds.listConnections(hairSys + ".currentTime", p = True, c = True)
|
|
cmds.disconnectAttr(connections[1], connections[0])
|
|
|
|
expressionString = "if(frame!= " + hairSys + ".startFrame)\n\t" + hairSys + ".currentTime = " + hairSys + ".currentTime + 1 + " + track_RealTime + ".tx - " + track_RealTime + ".tx + " + track_RealTime + ".ty - " + track_RealTime + ".ty + " + track_RealTime + ".tz - " + track_RealTime + ".tz + " + control + ".chainWidthBase - "+ control + ".chainWidthBase + "+ control + ".chainWidthExtremity - "+ control + ".chainWidthExtremity + " + control + ".chainGravity - "+ control + ".chainGravity;\n" +"else\n\t" + hairSys + ".currentTime = " + hairSys + ".startFrame;"
|
|
cmds.expression(name = "EXP_" + hairSys + "_TRACK_RealTime", string = expressionString)
|
|
cmds.setAttr(track_RealTime + ".v", 0)
|
|
|
|
#Set Defaults
|
|
cmds.setAttr(hairSys + ".drawCollideWidth", 1)
|
|
cmds.setAttr(hairSys + ".widthDrawSkip", 0)
|
|
cmds.setAttr(hair + ".degree", 1)
|
|
|
|
cmds.parentConstraint(parent, ctrlGrp, mo = True)
|
|
|
|
if cmds.objExists("dynHairChain") == False:
|
|
cmds.group(empty = True, name = "dynHairChain")
|
|
|
|
if cmds.objExists(dynamicJoints[0] + "_HairControls") == False:
|
|
group = cmds.group([ikNodes, hairSys, hair, track_RealTime, ctrlGrp, crvParent], name = dynamicJoints[0] + "_HairControls")
|
|
|
|
else:
|
|
cmds.parent([ikNodes, hairSys, hair, ctrlGrp,crvParent ], dynamicJoints[0] + "_HairControls")
|
|
|
|
cmds.parent(group, "dynHairChain")
|
|
|
|
#Cleanup
|
|
jointsGrp = cmds.group(empty = True, name = name + "_jointGrp")
|
|
cmds.parent([dynamicJoints[0], dupeStartJoint], jointsGrp)
|
|
|
|
cmds.setAttr(control + ".overrideEnabled", 1)
|
|
cmds.setAttr(control + ".overrideColor", 18)
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#CLEAN UP SCENE
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
ikGrp = cmds.group(empty = True, name = name + "_ik_ctrl_grp")
|
|
clustersGrp = cmds.group(empty = True, name = name + "_ik_clusters_grp")
|
|
dynGrp = cmds.group(empty = True, name = name + "_dyn_ctrl_grp")
|
|
masterGrp = cmds.group(empty = True, name = name + "_master_ctrl_grp")
|
|
createdControls.append(masterGrp)
|
|
|
|
#need to parent control groups in here
|
|
cmds.parent([ikHandle, ikJoints[0], ikCurve, name + "_ik_base_anim_grp"], ikGrp)
|
|
|
|
for cluster in clusterNodes:
|
|
cmds.parent(cluster, clustersGrp)
|
|
|
|
for grp in ikAnimGrps:
|
|
cmds.parent(grp, ikGrp)
|
|
|
|
cmds.parent(clustersGrp, "master_anim")
|
|
cmds.setAttr(clustersGrp + ".inheritsTransform", 0)
|
|
|
|
cmds.parent(name + "_jointGrp", dynGrp)
|
|
cmds.parent([ikGrp, dynGrp, fkRootGrp], masterGrp)
|
|
|
|
|
|
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
#HOOKUP RIGS TO RIG SETTINGS
|
|
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
|
|
cmds.select("Rig_Settings")
|
|
cmds.addAttr(longName= (name + "_fk"), defaultValue=1, minValue=0, maxValue=1, keyable = True)
|
|
cmds.addAttr(longName= (name + "_ik"), defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
cmds.addAttr(longName= (name + "_dynamic"), defaultValue=0, minValue=0, maxValue=1, keyable = True)
|
|
|
|
for i in range(int(len(dynamicJoints))):
|
|
driverJoint = dynamicJoints[i].replace("rig_dyn_", "driver_")
|
|
|
|
constraint = cmds.parentConstraint([fkJoints[i], ikJoints[i], dynamicJoints[i]], driverJoint)[0]
|
|
|
|
|
|
cmds.connectAttr("Rig_Settings." + name + "_fk", constraint + "." + fkJoints[i] + "W0")
|
|
cmds.connectAttr("Rig_Settings." + name + "_ik", constraint + "." + ikJoints[i] + "W1")
|
|
cmds.connectAttr("Rig_Settings." + name + "_dynamic", constraint + "." + dynamicJoints[i] + "W2")
|
|
|
|
#create blend Color nodes for scale
|
|
scaleBlendColors = cmds.shadingNode("blendColors", asUtility = True, name = name + "_scale_blend")
|
|
cmds.connectAttr(firstControl + ".scale", scaleBlendColors + ".color1")
|
|
cmds.connectAttr(name + "_ik_base_anim" + ".scale", scaleBlendColors + ".color2")
|
|
cmds.connectAttr(scaleBlendColors + ".output", driverJoint + ".scale")
|
|
|
|
cmds.connectAttr("Rig_Settings." + name + "_fk", scaleBlendColors + ".blender")
|
|
|
|
|
|
|
|
|
|
#setup visibility connections
|
|
cmds.connectAttr("Rig_Settings." + name + "_fk", fkRootGrp + ".v")
|
|
cmds.connectAttr("Rig_Settings." + name + "_ik", ikGrp + ".v")
|
|
cmds.connectAttr("Rig_Settings." + name + "_dynamic", name + "_dyn_anim_grp.v")
|
|
|
|
|
|
|
|
return createdControls
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def createDriverSkeleton(self):
|
|
|
|
dupe = cmds.duplicate("root", rc = True)[0]
|
|
cmds.select("root", hi = True)
|
|
joints = cmds.ls(sl = True)
|
|
|
|
cmds.select(dupe, hi = True)
|
|
dupeJoints = cmds.ls(sl = True)
|
|
|
|
driverJoints = []
|
|
for i in range(int(len(dupeJoints))):
|
|
|
|
if cmds.objExists(dupeJoints[i]):
|
|
driverJoint = cmds.rename(dupeJoints[i], "driver_" + joints[i])
|
|
driverJoints.append(driverJoint)
|
|
|
|
|
|
#create a direct connection between the driver and the export joints
|
|
exceptionJoints = ["upperarm_l", "upperarm_r"]
|
|
|
|
for joint in driverJoints:
|
|
exportJoint = joint.partition("_")[2]
|
|
|
|
if exportJoint not in exceptionJoints:
|
|
cmds.connectAttr(joint + ".translate", exportJoint + ".translate")
|
|
cmds.connectAttr(joint + ".rotate", exportJoint + ".rotate")
|
|
cmds.connectAttr(joint + ".scale", exportJoint + ".scale")
|
|
else:
|
|
cmds.connectAttr(joint + ".translate", exportJoint + ".translate")
|
|
cmds.connectAttr(joint + ".scale", exportJoint + ".scale")
|
|
cmds.orientConstraint(joint, exportJoint)
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def getSpineJoints(self):
|
|
|
|
numSpineBones = int(cmds.getAttr("Skeleton_Settings.numSpineBones"))
|
|
spineJoints = []
|
|
|
|
for i in range(int(numSpineBones)):
|
|
|
|
if i < 10:
|
|
spineJoint = "spine_0" + str(i + 1)
|
|
|
|
else:
|
|
spineJoint = "spine_" + (i + 1)
|
|
|
|
spineJoints.append(spineJoint)
|
|
|
|
return spineJoints
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def createControl(self, controlType, size, name):
|
|
|
|
scale = self.getScaleFactor()
|
|
|
|
if controlType == "circle":
|
|
control = cmds.circle(c = (0,0,0), sw = 360, r = size * scale, d = 3, name = name)[0]
|
|
|
|
if controlType == "circleSpecial":
|
|
control = cmds.circle(c = (0,0,0), sw = 360, r = 1, d = 3, name = name)[0]
|
|
|
|
side = name.rpartition("_")[2]
|
|
|
|
if side == "l":
|
|
cmds.xform(control, piv = (0, -1, 0))
|
|
|
|
else:
|
|
cmds.xform(control, piv = (0, 1, 0))
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
if controlType == "square":
|
|
control = cmds.circle(c = (0,0,0), s = 4, sw = 360, r = size * scale, d = 1, name = name)[0]
|
|
cmds.setAttr(control + ".rz", 45)
|
|
|
|
if controlType == "foot":
|
|
control = cmds.curve(name = name, d = 3, p = [(0, 40, 0), (-3.42, 39, 0), (-10.2, 37, 0), (-13, 22, 0), (-15.7, 13.2, 0), (-20, -14, 0), (-18.1, -25.6, 0), (-15, -44.8, 0), (1.1, -41.2, 0), (4.8, -41.7, 0), (15.5, -31.9, 0), (16.9, -22.7, 0), (18.6, -15.2, 0), (16.5, -.5, 0), (11.2, 29.2, 0), (10.7, 39.7, 0), (3.6, 39.9, 0), (0, 40, 0)])
|
|
|
|
footLoc = cmds.spaceLocator(name = (name + "_end_loc"))[0]
|
|
cmds.parent(footLoc, control)
|
|
cmds.setAttr(footLoc + ".ty", -40)
|
|
cmds.setAttr(footLoc + ".v", 0)
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
|
|
if controlType == "arrow":
|
|
control = cmds.curve(name = name, d = 1, p = [(0, -45, 0), (5, -45, 0), (5, -62, 0), (10, -62, 0), (0, -72, 0), (-10, -62, 0), (-5, -62, 0), (-5, -45, 0), (0, -45, 0)])
|
|
cmds.xform(control, cp = True)
|
|
cmds.setAttr(control + ".ty", 58.5)
|
|
cmds.makeIdentity(control, t = 1, apply = True)
|
|
cmds.xform(control, piv = (0, 13.5, 0))
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
if controlType == "arrowOnBall":
|
|
|
|
control = cmds.curve(name = name, d = 1, p = [(0.80718, 0.830576, 8.022739), (0.80718, 4.219206, 7.146586 ), (0.80718, 6.317059, 5.70073), (2.830981, 6.317059, 5.70073), (0, 8.422749, 2.94335), (-2.830981, 6.317059, 5.70073), (-0.80718, 6.317059, 5.70073), (-0.80718, 4.219352, 7.146486), (-0.80718, 0.830576, 8.022739), (-4.187851, 0.830576, 7.158003), (-6.310271, 0.830576, 5.705409), (-6.317059, 2.830981, 5.7007), (-8.422749, 0, 2.94335), (-6.317059, -2.830981, 5.70073), (-6.317059, -0.830576, 5.70073), (-4.225134, -0.830576, 7.142501), (-0.827872, -0.830576, 8.017446), (-0.80718, -4.176512, 7.160965), (-0.80718, -6.317059, 5.70073), (-2.830981, -6.317059, 5.70073), (0, -8.422749, 2.94335), (2.830981, -6.317059, 5.70073), (0.80718, -6.317059, 5.70073), (0.80718, -4.21137, 7.151987), (0.80718, -0.830576, 8.022739), (4.183345, -0.830576, 7.159155), (6.317059, -0.830576, 5.70073), (6.317059, -2.830981, 5.70073), (8.422749, 0, 2.94335), (6.317059, 2.830981, 5.70073), (6.317059, 0.830576, 5.70073), (4.263245, 0.830576, 7.116234), (0.80718, 0.830576, 8.022739)])
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
|
|
if controlType == "semiCircle":
|
|
|
|
control = cmds.curve(name = name, d = 3, p = [(0,0,0), (7, 0, 0), (8, 0, 0), (5, 4, 0), (0, 5, 0), (-5, 4, 0), (-8, 0, 0), (-7, 0, 0), (0,0,0)])
|
|
cmds.xform(control, ws = True, t = (0, 5, 0))
|
|
cmds.xform(control, ws = True, piv = (0,0,0))
|
|
cmds.makeIdentity(control, t = 1, apply = True)
|
|
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
|
|
if controlType == "pin":
|
|
control = cmds.curve(name = name, d = 1, p = [(12,0,0), (0, 0, 0), (-12, -12, 0), (-12, 12, 0), (0, 0, 0)])
|
|
cmds.xform(control, ws = True, piv = [12,0,0])
|
|
cmds.setAttr(control + ".scaleY", .5)
|
|
cmds.makeIdentity(control, t = 1, apply = True)
|
|
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
|
|
if controlType == "sphere":
|
|
|
|
points = [(0, 0, 1), (0, 0.5, 0.866), (0, 0.866025, 0.5), (0, 1, 0), (0, 0.866025, -0.5), (0, 0.5, -0.866025), (0, 0, -1), (0, -0.5, -0.866025), (0, -0.866025, -0.5), (0, -1, 0), (0, -0.866025, 0.5), (0, -0.5, 0.866025), (0, 0, 1), (0.707107, 0, 0.707107), (1, 0, 0), (0.707107, 0, -0.707107), (0, 0, -1), (-0.707107, 0, -0.707107), (-1, 0, 0), (-0.866025, 0.5, 0), (-0.5, 0.866025, 0), (0, 1, 0), (0.5, 0.866025, 0), (0.866025, 0.5, 0), (1, 0, 0), (0.866025, -0.5, 0), (0.5, -0.866025, 0), (0, -1, 0), (-0.5, -0.866025, 0), (-0.866025, -0.5, 0), (-1, 0, 0), (-0.707107, 0, 0.707107), (0, 0, 1)]
|
|
control = cmds.curve(name = name, d = 1, p = points)
|
|
|
|
cmds.setAttr(control + ".scaleX", size * scale)
|
|
cmds.setAttr(control + ".scaleY", size * scale)
|
|
cmds.setAttr(control + ".scaleZ", size * scale)
|
|
|
|
|
|
return control
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def getScaleFactor(self):
|
|
|
|
headLoc = cmds.spaceLocator(name = "headLoc")[0]
|
|
cmds.parentConstraint("head", headLoc)
|
|
|
|
height = cmds.getAttr(headLoc + ".tz")
|
|
|
|
defaultHeight = 400
|
|
scaleFactor = height/defaultHeight
|
|
cmds.delete(headLoc)
|
|
|
|
return scaleFactor
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def getUpAxis(self, obj):
|
|
|
|
cmds.xform(obj, ws = True, relative = True, t = [0, 0, 10])
|
|
translate = cmds.getAttr(obj + ".translate")[0]
|
|
newTuple = (abs(translate[0]), abs(translate[1]), abs(translate[2]))
|
|
cmds.xform(obj, ws = True, relative = True, t = [0, 0, -10])
|
|
|
|
highestVal = max(newTuple)
|
|
axis = newTuple.index(highestVal)
|
|
upAxis = None
|
|
|
|
if axis == 0:
|
|
upAxis = "X"
|
|
|
|
if axis == 1:
|
|
upAxis = "Y"
|
|
|
|
if axis == 2:
|
|
upAxis = "Z"
|
|
|
|
return upAxis
|
|
|
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
def normalizeSubVector(self, vector1, vector2):
|
|
import math
|
|
returnVec = []
|
|
for i in range(len(vector1)):
|
|
returnVec.append(vector1[i] - vector2[i])
|
|
|
|
#get length of vector
|
|
length = math.sqrt( (returnVec[0] * returnVec[0]) + (returnVec[1] * returnVec[1]) + (returnVec[2] * returnVec[2]) )
|
|
|
|
#normalize the vector
|
|
normalizedVector = []
|
|
for i in range(len(returnVec)):
|
|
normalizedVector.append(returnVec[i]/length)
|
|
|
|
absVector = []
|
|
for i in range(len(normalizedVector)):
|
|
absVector.append(abs(normalizedVector[i]))
|
|
|
|
aimAxis = max(absVector)
|
|
aimAxisIndex = absVector.index(aimAxis)
|
|
|
|
if aimAxisIndex == 0:
|
|
if normalizedVector[0] < 0:
|
|
axis = "X"
|
|
if normalizedVector[0] > 0:
|
|
axis = "-X"
|
|
|
|
if aimAxisIndex == 1:
|
|
if normalizedVector[1] < 0:
|
|
axis = "Y"
|
|
if normalizedVector[1] > 0:
|
|
axis = "-Y"
|
|
|
|
if aimAxisIndex == 2:
|
|
if normalizedVector[2] < 0:
|
|
axis = "Z"
|
|
if normalizedVector[2] > 0:
|
|
axis = "-Z"
|
|
|
|
return axis
|
|
|
|
|
|
|