Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #FK-IK auto rig & matching script
- #select your shoulder joint, the next one in the hierarchy will be the elbow and so on.
- from maya import cmds
- #this function makes a list from a parent object, and places items in the right order. The updated list is returned.
- def getRelatives(parent, lenght):
- newList = cmds.listRelatives(parent, allDescendents=1)
- newList.append(parent)
- newList.reverse()
- print newList
- if len(newList)<lenght:
- print "too little joints"
- else:
- del newList[lenght:]
- return newList
- #this function adds suffixes to a given list of objects
- def renameList(array, suffix):
- for element in array:
- oldName = str(element)
- cmds.rename([element], oldName+"_"+suffix)
- #this function duplicates a list, makes sure they have the same lenght and gives the duplicated objects a new suffix.
- #The duplicated list is returned.
- def duplicateList(array, suffix, bHide):
- oldName = str(array[0])
- newList = cmds.duplicate(array[0], n=oldName+"_"+suffix, renameChildren=1)
- if len(newList)>len(array):
- cmds.delete(newList[len(array):len(newList)])
- del newList[len(array):len(newList)]
- for id in range(0, len(array)):
- if bHide == 1:
- cmds.setAttr(str(newList[id])+".visibility", 0)
- cmds.rename(newList[id], str(array[id])+"_"+suffix)
- newList = getRelatives(newList[0], 3)
- return newList
- #this function hides and optionally locks translate, rotate, and scale attributes
- def lockHideAttr(array, bTranslate, bRotate, bScale, bLock):
- for object in array:
- if isinstance(object, list):
- object=object[0]
- if bTranslate == 1:
- cmds.setAttr(str(object)+".tx", keyable=0, channelBox=0, lock=bLock)
- cmds.setAttr(str(object)+".ty", keyable=0, channelBox=0, lock=bLock)
- cmds.setAttr(str(object)+".tz", keyable=0, channelBox=0, lock=bLock)
- if bRotate == 1:
- cmds.setAttr(str(object)+".rx", keyable=0, channelBox=0, lock=bLock)
- cmds.setAttr(str(object)+".ry", keyable=0, channelBox=0, lock=bLock)
- cmds.setAttr(str(object)+".rz", keyable=0, channelBox=0, lock=bLock)
- if bScale == 1:
- cmds.setAttr(str(object)+".sx", keyable=0, channelBox=0, lock=bLock)
- cmds.setAttr(str(object)+".sy", keyable=0, channelBox=0, lock=bLock)
- cmds.setAttr(str(object)+".sz", keyable=0, channelBox=0, lock=bLock)
- #this function creates and returns FK controllers for a given list of joints.
- #Null objects act as buffer for rotational values, so the controllers keep the right angle at 0,0,0
- def makeFKCtrls(array):
- nullList = []
- controllerList = []
- for element in array:
- fkController = cmds.circle(n=str(element)+"_ctrl", sweep=360, normalX=90, radius=1.5)
- cmds.delete(cmds.parentConstraint(element, fkController, maintainOffset=0))
- fkNull = cmds.group(n=str(element)+"_null", empty=1)
- cmds.delete(cmds.parentConstraint(element, fkNull, maintainOffset=0))
- cmds.parent(fkController, fkNull)
- cmds.makeIdentity(fkController, apply=1)
- cmds.orientConstraint(fkController, element, maintainOffset=0)
- nullList.append(fkNull)
- controllerList.append(fkController)
- parentGroup = cmds.group(n="fkControllers_grp", empty=1)
- cmds.parent(nullList[0], parentGroup)
- cmds.parent(nullList[1], controllerList[0])
- cmds.parent(nullList[2], controllerList[1])
- lockHideAttr([parentGroup], 1, 1, 1, 1)
- lockHideAttr(nullList, 1, 1, 1, 1)
- lockHideAttr(controllerList, 1, 0, 1, 1)
- return controllerList
- #this function calculates and returns the appropriate position of the pole vector from a list of joints.
- #Credits to https://bindpose.com/seamless-ik-fk-switch-maya-python/ for this one
- def poleVectorLocation(array):
- vector1=[cmds.xform(array[1], translation=1, worldSpace=1, query=1)[id] - cmds.xform(array[0], translation=1, worldSpace=1, query=1)[id] for id in range(3)]
- vector2=[cmds.xform(array[1], translation=1, worldSpace=1, query=1)[id] - cmds.xform(array[2], translation=1, worldSpace=1, query=1)[id] for id in range(3)]
- middlePos=[cmds.xform(array[1], translation=1, worldSpace=1, query=1)[id] for id in range(3)]
- return [middlePos[id]+(vector1[id]*.75)+(vector2[id]*.75) for id in range(3)]
- #this function creates IK controllers from a list of joints. The controller is returned.
- def makeIKCtrl(array, poleVector):
- ikController = cmds.curve (n=str(array[2])+"_ctrl", d=1, p=[(.75, .75, .75), (.75, .75, -.75), (-.75, .75, -.75), (-.75, -.75, -.75), (.75, -.75, -.75), (.75, .75, -.75), (-.75, .75, -.75), (-.75, .75, .75), (.75, .75, .75), (.75, -.75, .75), (.75, -.75, -.75), (-.75, -.75, -.75), (-.75, -.75, .75), (.75, -.75, .75), (-.75, -.75, .75), (-.75, .75, .75)])
- #this is the fastest way to make a cube of curves
- cmds.delete(cmds.parentConstraint(array[2], ikController, maintainOffset=0))
- ikNull = cmds.group(n=str(array[2])+"_null", empty=1)
- cmds.delete(cmds.parentConstraint(array[2], ikNull, maintainOffset=0))
- cmds.parent(ikController, ikNull)
- cmds.makeIdentity(ikController, apply=1)
- ikEffector = cmds.ikHandle(n=str(array[2])+"_handle", startJoint=array[0], endEffector=array[2])
- ikHandle = str(array[2])+"_handle"
- cmds.pointConstraint(ikController, ikHandle)
- cmds.orientConstraint(ikController, array[2])
- cmds.poleVectorConstraint(poleVector, ikHandle)
- cmds.setAttr(str(ikHandle)+".visibility", 0)
- lockHideAttr([ikNull], 1, 1, 1, 1)
- lockHideAttr([ikController], 0, 0, 1, 1)
- return ikController
- #this function creates and returns a controller for switching between IK and FK controllers
- #a "reverse" shader node is used to set FK and IK influence, as well as their visibility, as opposite to eachother
- def makeSwitchCtrl(skinJoints, fkJoints, ikJoints, fkCtrls, ikCtrl, poleVector):
- cmds.shadingNode("reverse", asUtility=1, name="invertValue")
- switchCtrl = cmds.circle(n="switch_ctrl", sweep=360, normalX=90, radius=0.7)
- cmds.delete(cmds.pointConstraint(str(skinJoints[2])+"_bind", switchCtrl, maintainOffset=0))
- cmds.setAttr(str(switchCtrl[0])+".translateY", 2)
- cmds.makeIdentity(switchCtrl, apply=1)
- cmds.pointConstraint(str(skinJoints[2])+"_bind", switchCtrl, maintainOffset=1)
- lockHideAttr([switchCtrl], 1, 1, 1, 1)
- cmds.addAttr(switchCtrl, longName="fkIkSwitch", niceName="FK/IK", attributeType="bool", keyable=1, exists=1)
- cmds.connectAttr(str(switchCtrl[0])+".fkIkSwitch", "invertValue.inputX")
- for id in range(3):
- cmds.orientConstraint(fkJoints[id], ikJoints[id], str(skinJoints[id])+"_bind")
- cmds.connectAttr(str(switchCtrl[0])+".fkIkSwitch", str(skinJoints[id])+"_bind_orientConstraint1."+str(skinJoints[id])+"_FKW0")
- cmds.connectAttr("invertValue.outputX", str(skinJoints[id])+"_bind_orientConstraint1."+str(skinJoints[id])+"_IKW1")
- for ctrl in fkCtrls:
- cmds.connectAttr(str(switchCtrl[0])+".fkIkSwitch", str(ctrl[0])+".visibility" )
- cmds.connectAttr("invertValue.outputX", str(ikCtrl)+".visibility")
- cmds.connectAttr("invertValue.outputX", "poleVector_ctrl.visibility")
- return switchCtrl
- #this function matches the IK and FK controllers to current pose, depending on the value of the switch controller
- #this function is called in real time from the viewport using a scriptjob
- def matchCtrls():
- #this orients to FK controllers to the IK joints
- if cmds.getAttr(str(switchCtrl[0])+".fkIkSwitch") == 1:
- for id in range(len(fkControllers)):
- if id != 2:
- cmds.delete(cmds.aimConstraint(ikJointList[id+1], fkControllers[id]))
- cmds.delete(cmds.orientConstraint(ikController, fkControllers[2]))
- #this places the IK controller at the wrist, and places the pole vector at the appropriate position from the FK joints
- else:
- cmds.delete(cmds.pointConstraint(fkJointList[2], ikController))
- cmds.delete(cmds.orientConstraint(fkControllers[2], ikController))
- newPositionLocator = cmds.spaceLocator(name="newPositionLocator", position = poleVectorLocation(fkJointList))
- cmds.xform(newPositionLocator, centerPivots=1)
- cmds.delete(cmds.pointConstraint(newPositionLocator, poleVectorCtrl))
- cmds.delete(newPositionLocator)
- #this calls the functions in the right order, using the selected object as the elbow joint.
- #A scriptjob is created to call the matchCtrls function when the switchCtrl changes values
- sl = cmds.ls(sl=1)
- if len(sl) ==1:
- jointList = getRelatives(sl[0], 3)
- fkJointList = duplicateList(jointList, "FK", 1)
- ikJointList = duplicateList(jointList, "IK", 1)
- renameList (jointList, "bind")
- poleVectorCtrl = cmds.spaceLocator(name="poleVector_ctrl", position= poleVectorLocation(ikJointList))
- cmds.xform(poleVectorCtrl, centerPivots=1)
- lockHideAttr(poleVectorCtrl, 0, 1, 1, 1)
- fkControllers = makeFKCtrls(fkJointList)
- ikController = makeIKCtrl(ikJointList, poleVectorCtrl)
- switchCtrl = makeSwitchCtrl(jointList, fkJointList, ikJointList, fkControllers, ikController, poleVectorCtrl)
- cmds.scriptJob(attributeChange=[str(switchCtrl[0])+".fkIkSwitch", matchCtrls])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement