Constraints can be confusing, and damn are they annoying and unintuitive!
So here is an effort to clean things up and hopefully make constraining a little more logical and easy.
This script attempts to consolidate the constraint weights and blend parents into a single switcher.
How do I use it?!
To use it, copy the below and paste it into a new shelf button as a PYTHON script. Then set up your constraints, and select the object with constraints on it. Press your new shelf button and watch the magic happen!
# simplify constraint setup
import maya.cmds as cmds
import re
# create condition node
class condition ( object ):
#create node
def __init__ ( self ):
self . node = cmds . shadingNode ( "condition" , au = True )
cmds . setAttr ( "%s.ctr" % self . node , 1 ) #set TRUE to be 1
cmds . setAttr ( "%s.cfr" % self . node , 0 ) #set FALSE to be 0
#set condition value
def set_value ( self , value ):
cmds . setAttr ( "%s.secondTerm" % self . node , value )
return self
#connect input
def connect_in ( self , into ):
cmds . connectAttr ( into , "%s.ft" % self . node , f = True )
return self
#connect output
def connect_out ( self , out ):
cmds . connectAttr ( "%s.ocr" % self . node , out , f = True )
return self
# create clamp node
class clamp ( object ):
#create node
def __init__ ( self ):
self . node = cmds . shadingNode ( "clamp" , au = True )
cmds . setAttr ( "%s.mxr" % self . node , 1 ) #set MAX to be 1
#connect input
def connect_in ( self , into ):
cmds . connectAttr ( into , "%s.ipr" % self . node , f = True )
return self
#connect output
def connect_out ( self , out ):
cmds . connectAttr ( "%s.opr" % self . node , out , f = True )
return self
# warning message
def message ( mess ):
cmds . confirmDialog ( t = 'Yeah, nah bro.' , m = mess )
# get working!
sel = cmds . ls ( sl = True )
if len ( sel ) == 1 :
sel = sel [ 0 ]
for at in [ "translate" , "rotate" ]: #add keyframe if none to force a pairBlend
if not cmds . keyframe ( sel , at = at , q = True ):
cmds . setKeyframe ( sel , at = at )
blend_reg = re . compile ( "pairBlend[0-9]+" ) #regex for getting the blendparent node
const_reg = re . compile ( "_[a-z]+Constraint[0-9]+" ) # check contraint is there
opt = {} #menu options - different constraints
children = cmds . listRelatives ( sel , typ = "transform" )
if children :
for child in children : #find constraint
if const_reg . search ( child ):
attr = cmds . listConnections ( child , p = True , c = True ) #find pairBlend
for at in attr :
if blend_reg . search ( at ):
opt . setdefault ( "nothing" , set ()). add ( cmds . listConnections ( "%s.w" % at . split ( "." )[ 0 ], p = True , d = False )[ 0 ])
for node in cmds . listAttr ( child , sn = True , st = "w*" , k = True ): #grab the constraint attributes
attr = "%s.%s" % ( child , node )
opt . setdefault ( cmds . attributeName ( attr , l = True )[ 0 : - 2 ], set ()). add ( attr )
if opt : #we now have our connection information
dropdown_opt = sorted ( list ( set ( opt . keys ()))) # create list of possible connections
dropdown_opt . insert ( 0 , dropdown_opt . pop ( dropdown_opt . index ( "nothing" ))) #make sure animation is first
if cmds . objExists ( "%s.atch" % sel ): #create or update the drop down button
old_keys = cmds . keyframe ( sel , at = "atch" , q = True ) #update keyframes
old_opt = cmds . addAttr ( "%s.atch" % sel , q = True , en = True ). split ( ":" )
if old_keys :
print "Updating keyframes..."
old_new = {}
for old in old_opt :
try :
old_new [ old_opt . index ( old )] = dropdown_opt . index ( old )
except ValueError :
old_new [ old_opt . index ( old )] = "remove" #constraint was removed, mark for removal
for key in old_keys :
old_val = cmds . keyframe ( sel , at = "atch" , t = ( key , key ), q = True , vc = True )[ 0 ]
new_val = old_new [ int ( old_val )]
if new_val == "remove" :
cmds . cutKey ( sel , at = "atch" , cl = True , t = ( key , key ))
else :
cmds . keyframe ( sel , at = "atch" , e = True , t = ( key , key ), vc = new_val )
cmds . addAttr ( "%s.atch" % sel , e = True , en = ":" . join ( dropdown_opt ) )
else :
cmds . addAttr ( ln = "attach_to" , sn = "atch" , k = True , at = "enum" , en = ":" . join ( dropdown_opt ) )
for i in range ( len ( dropdown_opt )): #connect up our items
if i : #set up constraints
for link in opt [ dropdown_opt [ i ]]:
condition (). set_value ( i ). connect_in ( "%s.atch" % sel ). connect_out ( link )
else : #set up blend node
for link in opt [ dropdown_opt [ i ]]:
clamp (). connect_in ( "%s.atch" % sel ). connect_out ( link )
cmds . select ( sel )
else :
message ( "Cannot find the constraint. \n Ensure the constraint is under the object in the outliner." )
else :
message ( "Cannot find the constraint. \n Ensure the constraint is under the object in the outliner." )
else :
message ( "You can only select one object at a time." )