Project

Dynamic Hair Creation

It is a tedious work to rig every single strain of hair for the character so i written this script to speed up my working progress.

Summary about my script

As title this script will create dynamic hair by curve. The script will create consistent ranged of joints, make the selected curve dynamic and finally connect the joints to dynamic curve by using ik Spline system. The next part of the script is to change attributes of a group of dynamic hair with the window.

The naming convention was being set and could be changed easily and might consider to add the function to the window. The nucleus created will be bind when run the script. It will track the nucleus even after it being rename but the failure of this script is the name had to be change back to necleus1 for each run. I am looking for another way to track the node or object without going through the name.

Ram Warrior Rig With Hair Simulation

Brief Introduction

Ram warrior was created by student graduated from Full Sail who is Herman Omar Gonzalez. He created this awesome warrior and i had a chance to rig it and able to make it alive with rig whihc is super awesome.

For this project I had been working on the body and also the simulation of dynamic hair which also include for controls.

This is the footage with controls and without staging& Texturing.

 

Tool Built for Stretch&Squash IK system

Stretch & Squash Automated Rig

from __future__ import division
import maya.cmds as my
import pymel.core as pm
def padding( *args ):
list = pm.ls( sl=True )
num_name_delete = pm.intField(intFieldEntry_num_name_delete, editable = True, query = True, value = True )
for n in list :
pm.group( em=True, name= 'empty' )
pm.parent( 'empty' , n )
pm.setAttr( 'empty.translateX' , 0)
pm.setAttr( 'empty.translateY' , 0)
pm.setAttr( 'empty.translateZ' , 0)
pm.setAttr( 'empty.rotateX' , 0)
pm.setAttr( 'empty.rotateY' , 0)
pm.setAttr( 'empty.rotateZ' , 0)
pm.parent( 'empty', world=True )
pm.parent( n, 'empty' )
newname= n.split( '_' )
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name – num_name_delete-1 or i == number_name – num_name_delete-1 :
new_name = new_name_first
print 'naming error'
break
else :
if i < number_name – num_name_delete-1 :
new_name_second= newname[i+1]+'_'
new_name = new_name_first+new_name_second
new_name_first= new_name
else:
break
pm.rename ( 'empty' , new_name + '00_pad' )
def rename_lt ( *args ):
global ori
ori = 'lt'
def rename_ct ( *args ):
global ori
ori = 'ct'
def rename_rt ( *args ):
global ori
ori = 'rt'
def renamer ( *args ):
textFieldData_name = pm.textField(textFieldEntry_name, editable = True, query = True, text=True)
textFieldData_suffix = pm.textField(textFieldEntry_suffix, editable = True, query = True, text=True)
list = pm.ls( sl=True )
name= textFieldData_name
count=0
suffix= textFieldData_suffix
for n in list:
x = len(list)
if x>1 :
count = count+1
if count < x :
newname = '{0}_{1}_{2:02d}_{3}'.format(ori, name, count, suffix)
elif count > x-1 :
newname = '{0}_{1}_{2:02d}_waste'.format(ori, name, count)
else:
print 'error_on_selected'
pm.rename( n, newname )
else :
count = count+1
newname = '{0}_{1}_{2:02d}_{3}'.format(ori, name, count, suffix)
pm.rename( n, newname )
def renamer_mirror ( *args ):
item_renaming = pm.ls(sl=True, head=1)
list = pm.ls(sl=True, tail=1)
for n in list:
newname = n.split( '_' )
x = len(newname)
if x == 6 :
list_mirrored = pm.rename( item_renaming , 'rt' + '_' + newname[1] + '_' + newname[2] + '_' + newname[3] + '_' + newname[4] + '_' + newname[5] )
elif x == 5 :
list_mirrored = pm.rename( item_renaming , 'rt' + '_' + newname[1] + '_' + newname[2] + '_' + newname[3] + '_' + newname[4] )
elif x == 4 :
list_mirrored = pm.rename( item_renaming , 'rt' + '_' + newname[1] + '_' + newname[2] + '_' + newname[3] )
else:
list_mirrored = pm.rename( item_renaming , 'rt' + '_' + newname[1] + '_' + newname[2])
def snapping ( *args ):
list= pm.ls(sl=True, head=1)
groupinto= pm.ls(sl=True, tail=1)
textFieldData_ik_suffix = pm.textField(textFieldEntry_ik_suffix, editable = True, query = True, text=True)
ik_suffix = textFieldData_ik_suffix
num_name_delete = pm.intField(intFieldEntry_num_name_delete, editable = True, query = True, value = True )
for n in groupinto:
pm.duplicate(list,name=('snapping'))
pm.group( 'snapping' , n='readytosnap')
pm.parent('readytosnap', n)
pm.setAttr( 'readytosnap.translateX' , 0)
pm.setAttr( 'readytosnap.translateY' , 0)
pm.setAttr( 'readytosnap.translateZ' , 0)
pm.setAttr( 'readytosnap.rotateX' , 0)
pm.setAttr( 'readytosnap.rotateY' , 0)
pm.setAttr( 'readytosnap.rotateZ' , 90)
pm.parent( 'readytosnap', world=True )
newname= n.split( '_' )
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name – num_name_delete-1 or i == number_name – num_name_delete-1 :
new_name = new_name_first
print 'naming error'
break
else :
if i < number_name – num_name_delete-1 :
new_name_second= newname[i+1]+'_'
new_name = new_name_first+new_name_second
new_name_first= new_name
else:
break
pm.rename ( 'readytosnap' , new_name + '{0}_pad'.format(ik_suffix) )
pm.rename ( 'snapping' , new_name + '{0}'.format(ik_suffix) )
def dist_dimension_name ( *args ) :
for i in range (0 , 100) :
global dist_dimension_created
if pm.objExists ( 'distanceDimension{0}'.format(i+1) ) :
dist_dimension_created = 'distanceDimension{0}'.format(i+2)
else :
dist_dimension_created = 'distanceDimension{0}'.format(i+1)
break
def IK_Stretch (*args) :
joint_selected = pm.ls (sl= True)
joint_start = joint_selected[0]
joint_end = joint_selected[1]
textFieldData_ik_suffix = pm.textField(textFieldEntry_ik_suffix, editable = True, query = True, text=True)
ik_suffix = textFieldData_ik_suffix
num_name_delete = pm.intField(intFieldEntry_num_name_delete, editable = True, query = True, value = True )
newname= joint_start.split( '_' )
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name – num_name_delete-1 or i == number_name – num_name_delete-1 :
new_name_ik = new_name_first
print 'naming error'
break
else :
if i < number_name – num_name_delete-1 :
new_name_second= newname[i+1]+'_'
new_name_ik = new_name_first+new_name_second
new_name_first= new_name_ik
else:
break
pm.ikHandle ( sj = joint_start , ee = joint_end , n= '{0}ik_handle'.format(new_name_ik) )
if pm.objExists('dist_loc_01') :
print 'dist_loc_01 exists'
else :
dist_loc_01 = pm.spaceLocator ( n = 'dist_loc_01' )
for i in range ( 0,20 ) :
if i == 0 :
pm.select (joint_start)
joint_parent = pm.listRelatives(p=True, type= 'joint')
elif i > 0 :
pm.select (joint_parent)
joint_first = pm.ls(sl=True)
joint_parent = pm.listRelatives(p=True, type= 'joint')
if joint_parent == []:
pm.select(joint_first)
joint_first_select = pm.ls(sl=True)
break
else :
continue
pm.select ( joint_first_select , hi = True )
all_hierachy = pm.ls ( sl = True )
pm.select( joint_start )
joint_mid = pm.listRelatives(c=True)
pm.select ( dist_loc_01 , joint_start )
snapping()
pm.select ( dist_loc_01 , joint_mid )
snapping()
pm.select ( dist_loc_01 , joint_end )
snapping()
pm.select ( joint_start , joint_mid , joint_end)
ik_joint_loc = pm.ls ( sl = True )
pm.select ( d = True )
for n in ik_joint_loc :
newname= n.split( '_' )
print newname
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name – num_name_delete-1 or i == number_name – num_name_delete-1 :
new_name = new_name_first
print 'naming error'
break
else :
if i < number_name – num_name_delete-1 :
new_name_second= newname[i+1]+'_'
new_name = new_name_first+new_name_second
new_name_first= new_name
else:
break
print new_name
pm.select ( '{0}{1}'.format(new_name,ik_suffix) , add = True )
dist_loc_all = pm.ls ( sl = True)
dist_loc_start = dist_loc_all[0]
dist_loc_mid = dist_loc_all[1]
dist_loc_end = dist_loc_all[2]
pm.pointConstraint( '{0}'.format(dist_loc_start) , joint_start , mo=True , w = 1 )
pm.pointConstraint( joint_mid , '{0}_pad'.format(dist_loc_mid) , mo =True , w = 1 )
pm.pointConstraint( '{0}'.format(dist_loc_end) , '{0}ik_handle'.format(new_name_ik) , mo =True , w = 1 )
dist_loc_start_tx = pm.getAttr ('{0}_pad.tx'.format(dist_loc_start) )
dist_loc_start_ty = pm.getAttr ('{0}_pad.ty'.format(dist_loc_start) )
dist_loc_start_tz = pm.getAttr ('{0}_pad.tz'.format(dist_loc_start) )
dist_loc_mid_tx = pm.getAttr ('{0}_pad.tx'.format(dist_loc_mid) )
dist_loc_mid_ty = pm.getAttr ('{0}_pad.ty'.format(dist_loc_mid) )
dist_loc_mid_tz = pm.getAttr ('{0}_pad.tz'.format(dist_loc_mid) )
dist_loc_end_tx = pm.getAttr ('{0}_pad.tx'.format(dist_loc_end) )
dist_loc_end_ty = pm.getAttr ('{0}_pad.ty'.format(dist_loc_end) )
dist_loc_end_tz = pm.getAttr ('{0}_pad.tz'.format(dist_loc_end) )
dist_dimension_name()
pm.distanceDimension( sp = ( dist_loc_start_tx , dist_loc_start_ty , dist_loc_start_tz ) , ep = ( dist_loc_mid_tx , dist_loc_mid_ty , dist_loc_mid_tz ) )
newname= dist_loc_start.split( '_' )
print newname
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name – num_name_delete-2 or i == number_name – num_name_delete-2 :
new_name = new_name_first
print 'naming error'
break
else :
if i < number_name – num_name_delete-2 :
new_name_second= newname[i+1]+'_'
new_name = new_name_first+new_name_second
new_name_first= new_name
else:
break
dist_measure_01 = pm.rename ( dist_dimension_created , '{0}01_dist'.format(new_name))
dist_dimension_name()
pm.distanceDimension( sp = ( dist_loc_mid_tx , dist_loc_mid_ty , dist_loc_mid_tz ) , ep = ( dist_loc_end_tx , dist_loc_end_ty , dist_loc_end_tz ) )
dist_measure_02 = pm.rename ( dist_dimension_created , '{0}02_dist'.format(new_name))
dist_dimension_name()
pm.distanceDimension( sp = ( dist_loc_start_tx , dist_loc_start_ty , dist_loc_start_tz ) , ep = ( dist_loc_end_tx , dist_loc_end_ty , dist_loc_end_tz ) )
actual_length_ik = pm.rename ( dist_dimension_created , '{0}dist'.format(new_name))
first_length_ik = pm.getAttr ( '{0}.distance'.format ( dist_measure_01 ) )
second_length_ik = pm.getAttr ( '{0}.distance'.format ( dist_measure_02 ) )
max_length_ik = first_length_ik + second_length_ik
ratio_ik_stretch = pm.createNode ( 'multiplyDivide' , n = '{0}ratio_ik_stretch'.format ( new_name ) )
pm.setAttr ( '{0}.operation'.format ( ratio_ik_stretch ) , 2 )
pm.connectAttr ( '{0}.distance'.format ( actual_length_ik ) , '{0}.input1X'.format ( ratio_ik_stretch ) )
pm.setAttr ( '{0}.input2X'.format ( ratio_ik_stretch ) , max_length_ik )
ratio_ik_stretch_cond = pm.createNode ( 'condition' , n = '{0}ratio_ik_stretch_cond'.format ( new_name ) )
pm.connectAttr ( '{0}.outputX'.format ( ratio_ik_stretch ) , '{0}.firstTerm'.format ( ratio_ik_stretch_cond ) )
pm.connectAttr ( '{0}.outputX'.format ( ratio_ik_stretch ) , '{0}.colorIfTrueR'.format ( ratio_ik_stretch_cond ) )
pm.setAttr ( '{0}.operation'.format ( ratio_ik_stretch_cond ) , 3 )
pm.setAttr ( '{0}.secondTerm'.format ( ratio_ik_stretch_cond ) , 1 )
pm.setAttr ( '{0}.colorIfFalseR'.format ( ratio_ik_stretch_cond ) , 1 )
pm.connectAttr ( '{0}.outColorR'.format ( ratio_ik_stretch_cond ) , '{0}.scaleX'.format( joint_start ) )
pm.connectAttr ( '{0}.outColorR'.format ( ratio_ik_stretch_cond ) , '{0}.scaleX'.format( joint_mid[0] ) )
pm.connectAttr ( '{0}.outColorR'.format ( ratio_ik_stretch_cond ) , '{0}.scaleX'.format( joint_end ) )
pm.delete ( dist_loc_01 )
def squash_stretch_IK ( *args ) :
list_loc = pm.ls(sl=True)
list_loc_number = len (list_loc)
if pm.objExists('IK_spline_stretch_squash_bind_grp'):
print 'group already exist'
else :
pm.group(em = True, n='IK_spline_stretch_squash_bind_grp' , w = True)
if pm.objExists('IK_spline_stretch_squash_IK_handle_grp'):
print 'group already exist'
else :
pm.group(em = True, n='IK_spline_stretch_squash_IK_handle_grp' , w = True)
if pm.objExists('IK_spline_stretch_squash_curve_grp') :
print 'group already exist'
else :
pm.group(em = True, n='IK_spline_stretch_squash_curve_grp' , w = True)
if pm.objExists('IK_spline_stretch_squash_loc_grp'):
print 'group already exist'
else :
pm.group(em = True, n='IK_spline_stretch_squash_loc_grp' , w = True)
if pm.objExists('IK_spline_stretch_squash_joint_ctrl_grp'):
print 'group already exist'
else :
pm.group(em = True, n='IK_spline_stretch_squash_joint_ctrl_grp' , w = True)
'''
Retreiving data entry
'''
intFieldData_num_joint = pm.intField( intFieldEntry_num_joint, editable = True, query = True, value = True)
textFieldData_ik_spline_name = pm.textField(textFieldEntry_ik_spline_name, editable = True, query = True, text=True)
for loc_seq in range ( 1 , list_loc_number + 1 ) :
if loc_seq == list_loc_number :
print ( list_loc[list_loc_number-1]) , 'is the final locator'
pm.delete ( list_loc[list_loc_number-1] )
break
elif (intFieldData_num_joint % 2) > 0 :
print 'Input joint number is odd number'
break
else :
if pm.objExists( '{0}_{1}_IK_spline_loc_grp'.format( textFieldData_ik_spline_name , loc_seq) ) :
print 'Naming error – system with same name exist'
break
else :
pm.group ( em = True, n= '{0}_{1}_IK_spline_loc_grp'.format( textFieldData_ik_spline_name , loc_seq) , w = True)
pm.parent ( '{0}_{1}_IK_spline_loc_grp'.format( textFieldData_ik_spline_name , loc_seq) , 'IK_spline_stretch_squash_loc_grp' )
loc_first = list_loc[loc_seq-1]
loc_second = list_loc[loc_seq]
loc_first_X = pm.getAttr(loc_first.translateX)
loc_first_Y = pm.getAttr(loc_first.translateY)
loc_first_Z = pm.getAttr(loc_first.translateZ)
loc_second_X = pm.getAttr(loc_second.translateX)
loc_second_Y = pm.getAttr(loc_second.translateY)
loc_second_Z = pm.getAttr(loc_second.translateZ)
loc_mid_tranX = loc_first_X + ((loc_second_X – loc_first_X)/2)
loc_mid_tranY = loc_first_Y + ((loc_second_Y – loc_first_Y)/2)
loc_mid_tranZ = loc_first_Z + ((loc_second_Z – loc_first_Z)/2)
loc_mid = pm.spaceLocator ( n= '{0}_{1}_02_trans_loc'.format( textFieldData_ik_spline_name , loc_seq))
pm.setAttr( '{0}.tx'.format(loc_mid) , (loc_mid_tranX))
pm.setAttr( '{0}.ty'.format(loc_mid) , (loc_mid_tranY))
pm.setAttr( '{0}.tz'.format(loc_mid) , (loc_mid_tranZ))
if loc_seq == 1 :
pm.rename (loc_first, '{0}_{1}_01_trans_loc'.format( textFieldData_ik_spline_name , loc_seq))
pm.rename (loc_second, '{0}_{1}_01_trans_loc'.format( textFieldData_ik_spline_name , loc_seq+1))
else :
pm.rename (loc_second, '{0}_{1}_01_trans_loc'.format( textFieldData_ik_spline_name , loc_seq+1))
curve_path = pm.curve (d=1 , p = [( loc_first_X , loc_first_Y ,loc_first_Z ),( loc_mid_tranX , loc_mid_tranY , loc_mid_tranZ ),( loc_second_X , loc_second_Y , loc_second_Z )])
'''
Method on reconstruct curve and rename
'''
pm.rebuildCurve( curve_path , ch=1, rpo=1 , rt=0 , end=1 , kr=0 , kcp=0 , kep=1 , kt=0 , s=intFieldData_num_joint, d=3 , tol=0.0001 )
name_curve = pm.rename( curve_path , '{0}_{1}_ik_spline_curve'.format( textFieldData_ik_spline_name , loc_seq ) )
pre_joint = ''
root_joint = ''
for i in range( 0 , intFieldData_num_joint ) :
user_default_unit = pm.currentUnit( query=True, linear=True )
pm.currentUnit( linear = 'cm' )
pm.select( cl = True )
new_joint = pm.joint()
mot_path = pm.pathAnimation( new_joint , c = curve_path , fm = True )
pm.cutKey( mot_path + '.u' )
pm.setAttr( mot_path + '.u', i * ( 1.0 / ( intFieldData_num_joint – 1 )) )
pm.delete( '{0}.{1}'.format( new_joint , 'tx' ) , icn = True )
pm.delete( '{0}.{1}'.format( new_joint , 'ty' ) , icn = True )
pm.delete( '{0}.{1}'.format( new_joint , 'tz' ) , icn = True )
pm.currentUnit( linear = '{0}'.format(user_default_unit) )
renaming_item = pm.ls( sl = True )
if i == 0 :
pre_joint = new_joint
root_joint = new_joint
pm.rename( renaming_item , '{0}_{1}_{2:02d}_IK_spline_bind'.format( textFieldData_ik_spline_name , loc_seq , i+1 ) )
continue
elif i == intFieldData_num_joint -1 :
pm.rename( renaming_item , '{0}_{1}_{2:02d}_IK_spline_waste'.format( textFieldData_ik_spline_name , loc_seq , i+1 ) )
else :
pm.rename( renaming_item , '{0}_{1}_{2:02d}_IK_spline_bind'.format( textFieldData_ik_spline_name , loc_seq ,i+1 ) )
pm.parent( new_joint , pre_joint )
pre_joint = new_joint
pm.joint( root_joint, e = True , zso = True, oj = 'xyz' , ch = True , sao = 'yup' )
stretch_squash_ik_handle = pm.ikHandle (sol = 'ikSplineSolver' , pcv = False , ccv = False , c = curve_path , roc = True , ns=2 , sj = ('{0}_{1}_01_IK_spline_bind'.format( textFieldData_ik_spline_name , loc_seq )) , ee = ('{0}_{1}_{2:02d}_IK_spline_bind'.format( textFieldData_ik_spline_name , loc_seq , intFieldData_num_joint-1 )), n = '{0}_{1}_IK_spline'.format( textFieldData_ik_spline_name , loc_seq ))
pre_joint = ''
root_joint = ''
for i in range( 0 , 3 ) :
user_default_unit = pm.currentUnit( query=True, linear=True )
pm.currentUnit( linear = 'cm' )
pm.select( cl = True )
new_joint = pm.joint()
mot_path = pm.pathAnimation( new_joint , c = curve_path , fm = True )
pm.cutKey( mot_path + '.u' )
pm.setAttr( mot_path + '.u', i * ( 1.0 / 2 ) )
pm.delete( '{0}.{1}'.format( new_joint , 'tx' ) , icn = True )
pm.delete( '{0}.{1}'.format( new_joint , 'ty' ) , icn = True )
pm.delete( '{0}.{1}'.format( new_joint , 'tz' ) , icn = True )
pm.currentUnit( linear = '{0}'.format(user_default_unit) )
renaming_item = pm.ls( sl = True )
if i == 0 :
pre_joint = new_joint
root_joint = new_joint
pm.rename( renaming_item , '{0}_{1}_{2:02d}_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq , i+1 ) )
else :
pm.rename( renaming_item , '{0}_{1}_{2:02d}_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ,i+1 ) )
for n in renaming_item :
pm.group( em=True, name= 'empty' )
pm.parent( 'empty' , n )
pm.setAttr( 'empty.translateX' , 0)
pm.setAttr( 'empty.translateY' , 0)
pm.setAttr( 'empty.translateZ' , 0)
pm.setAttr( 'empty.rotateX' , 0)
pm.setAttr( 'empty.rotateY' , 0)
pm.setAttr( 'empty.rotateZ' , 0)
pm.parent( 'empty', world=True )
pm.parent( n, 'empty' )
for n in renaming_item:
newname= n.split( '_' )
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name-3 or i == number_name-3 :
new_name = new_name_first
print 'naming error'
break
else :
if i<number_name-3 :
new_name_second= newname[i+1]+'_'
new_name = new_name_first+new_name_second
new_name_first= new_name
else:
break
pm.rename ( 'empty' , new_name + 'joint_ctrl_pad' )
stretch_squash_joint_ctrl_grp = pm.group( '{0}_{1}_01_IK_spline_joint_ctrl_pad'.format( textFieldData_ik_spline_name , loc_seq ) , '{0}_{1}_02_IK_spline_joint_ctrl_pad'.format( textFieldData_ik_spline_name , loc_seq ) , '{0}_{1}_03_IK_spline_joint_ctrl_pad'.format( textFieldData_ik_spline_name , loc_seq ) , n = '{0}_{1}_IK_spline_joint_ctrl_grp'.format( textFieldData_ik_spline_name , loc_seq ) )
loc_first_rot = pm.duplicate ( loc_first, n = '{0}_{1}_01_rot_loc'.format( textFieldData_ik_spline_name , loc_seq ))
loc_mid_rot = pm.duplicate ( loc_mid, n = '{0}_{1}_02_rot_loc'.format( textFieldData_ik_spline_name , loc_seq ))
loc_second_trans = pm.duplicate ( loc_second, n = '{0}_{1}_03_trans_loc'.format( textFieldData_ik_spline_name , loc_seq ))
loc_second_rot = pm.duplicate ( loc_second, n = '{0}_{1}_03_rot_loc'.format( textFieldData_ik_spline_name , loc_seq ))
pm.parent (loc_first_rot , loc_first )
pm.parent (loc_mid_rot , loc_mid )
pm.parent (loc_second_rot , loc_second_trans[0] )
pm.select ( loc_first , loc_mid , loc_second_trans[0] )
list_loc_trans = pm.ls(sl= True)
number_loc_trans = len(list_loc_trans)
for n in list_loc_trans:
pm.group( em=True, name= 'empty' )
pm.parent( 'empty' , n )
pm.setAttr( 'empty.translateX' , 0)
pm.setAttr( 'empty.translateY' , 0)
pm.setAttr( 'empty.translateZ' , 0)
pm.setAttr( 'empty.rotateX' , 0)
pm.setAttr( 'empty.rotateY' , 0)
pm.setAttr( 'empty.rotateZ' , 0)
pm.parent( 'empty', world=True )
pm.parent( n, 'empty' )
newname= n.split( '_' )
number_name = len(newname)
new_name_first= newname[0]+'_'
for i in range ( 0, number_name ) :
if i > number_name-1 or i == number_name-1 :
new_name = new_name_first
print 'naming error'
break
else :
if i<number_name-1 :
new_name_second= newname[i+1]+'_'
new_name = new_name_first+new_name_second
new_name_first= new_name
else:
break
pm.rename ( 'empty' , new_name + 'pad' )
pm.parent ( '{0}_{1}_01_trans_loc_pad'.format( textFieldData_ik_spline_name , loc_seq ) , '{0}_{1}_02_trans_loc_pad'.format( textFieldData_ik_spline_name , loc_seq ) , '{0}_{1}_03_trans_loc_pad'.format( textFieldData_ik_spline_name , loc_seq ) , '{0}_{1}_IK_spline_loc_grp'.format( textFieldData_ik_spline_name , loc_seq ) )
pm.aimConstraint ( loc_first , loc_mid_rot )
pm.aimConstraint ( loc_mid , loc_first_rot )
pm.aimConstraint ( loc_mid , loc_second_rot )
pm.pointConstraint (loc_first , loc_second_trans[0] , (loc_mid+'_pad') )
pm.pointConstraint ( loc_first , '{0}_{1}_01_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ) , mo=True)
pm.pointConstraint ( loc_mid , '{0}_{1}_02_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ) , mo=True)
pm.pointConstraint ( loc_second_trans[0] , '{0}_{1}_03_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ) , mo=True)
pm.orientConstraint ( loc_first_rot , '{0}_{1}_01_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ) , mo=True)
pm.orientConstraint ( loc_mid_rot , '{0}_{1}_02_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ) , mo=True)
pm.orientConstraint ( loc_second_rot , '{0}_{1}_03_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ) , mo=True)
curve_length_node = pm.createNode ( 'curveInfo' , n = '{0}curve_length_{1}'.format ( new_name , loc_seq ) )
pm.connectAttr ( '{0}.worldSpace[0]'.format ( curve_path ) , '{0}.inputCurve'.format( curve_length_node ) )
curve_arc_length = pm.getAttr ( '{0}.arcLength'.format ( curve_length_node ) )
ratio_curve_stretch = pm.createNode ( 'multiplyDivide' , n = '{0}ratio_curve_stretch_{1}'.format ( new_name , loc_seq ) )
pm.setAttr ( '{0}.operation'.format ( ratio_curve_stretch ) , 2 )
pm.connectAttr ( '{0}.arcLength'.format ( curve_length_node ) , '{0}.input1X'.format ( ratio_curve_stretch ) )
pm.setAttr ( '{0}.input2X'.format ( ratio_curve_stretch ) , curve_arc_length)
ratio_curve_squash = pm.createNode ( 'multiplyDivide' , n = '{0}ratio_curve_squash_{1}'.format ( new_name , loc_seq ) )
pm.setAttr ( '{0}.operation'.format ( ratio_curve_squash ) , 2 )
pm.connectAttr ( '{0}.arcLength'.format( curve_length_node ) , '{0}.input2X'.format ( ratio_curve_squash ) )
pm.setAttr ( '{0}.input1X'.format ( ratio_curve_squash ) , curve_arc_length )
exp_squash = pm.createNode ( 'multiplyDivide' , n = '{0}exp_squash_{1}'.format ( new_name , loc_seq ) )
pm.setAttr ( '{0}.operation'.format ( exp_squash ) , 2 )
pm.setAttr ( '{0}.input2X'.format ( exp_squash ) , intFieldData_num_joint-1 )
for number_joint in range ( 0 , intFieldData_num_joint-1 ) :
pm.connectAttr ( '{0}.outputX'.format ( ratio_curve_stretch ) , '{0}_{1}_{2:02d}_IK_spline_bind.scaleX'.format( textFieldData_ik_spline_name , loc_seq , number_joint+1 ) )
exp_squash_plus = pm.createNode ( 'plusMinusAverage' , n = '{0}exp_squash_plus_0{1}_{2}'.format( new_name , number_joint+1 , loc_seq ) )
pm.setAttr ( '{0}.input1D[0]'.format( exp_squash_plus ) , 1 )
if number_joint < (intFieldData_num_joint / 2 ) :
pm.setAttr ( '{0}.operation'.format ( exp_squash_plus ) , 1 )
else :
pm.setAttr ( '{0}.operation'.format ( exp_squash_plus ) , 2 )
if number_joint == 0 :
print 'do nothing'
elif number_joint > 0 :
pm.connectAttr ( '{0}.outputX'.format( exp_squash ) , '{0}.input1D[1]'.format( exp_squash_plus ) )
pm.connectAttr ( '{0}exp_squash_plus_0{1}_{2}.output1D'.format( new_name , number_joint , loc_seq ) , '{0}.input1D[0]'.format( exp_squash_plus ) )
power_curve_squash = pm.createNode ( 'multiplyDivide' , n = '{0}power_curve_squash_0{1}_{2}'.format( new_name , number_joint+1 , loc_seq ) )
pm.setAttr ( '{0}.operation'.format ( power_curve_squash ) , 3)
pm.connectAttr ( '{0}.outputX'.format ( ratio_curve_squash ) , '{0}.input1X'.format ( power_curve_squash ) )
pm.connectAttr ( '{0}.output1D'.format ( exp_squash_plus ) , '{0}.input2X'.format ( power_curve_squash ) )
pm.connectAttr ( '{0}.outputX'.format ( power_curve_squash ) , '{0}_{1}_{2:02d}_IK_spline_bind.scaleY'.format( textFieldData_ik_spline_name , loc_seq , number_joint+1 ) )
pm.connectAttr ( '{0}.outputX'.format ( power_curve_squash ) , '{0}_{1}_{2:02d}_IK_spline_bind.scaleZ'.format( textFieldData_ik_spline_name , loc_seq , number_joint+1 ) )
pm.skinCluster('{0}_{1}_01_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ),'{0}_{1}_02_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ),'{0}_{1}_03_IK_spline_joint_ctrl'.format( textFieldData_ik_spline_name , loc_seq ), '{0}_{1}_ik_spline_curve'.format( textFieldData_ik_spline_name , loc_seq ))
pm.parent ( curve_path , 'IK_spline_stretch_squash_curve_grp' )
pm.parent ( '{0}_{1}_01_IK_spline_bind'.format( textFieldData_ik_spline_name , loc_seq ) , 'IK_spline_stretch_squash_bind_grp' )
pm.parent ( '{0}_{1}_IK_spline'.format( textFieldData_ik_spline_name , loc_seq ) , 'IK_spline_stretch_squash_IK_handle_grp' )
pm.parent ( stretch_squash_joint_ctrl_grp , 'IK_spline_stretch_squash_joint_ctrl_grp' )
class window_creation_speedrig :
def __init__(self) :
self.create_window()
def create_window(self):
if pm.window('RiggingSpeedUp',exists=True):
pm.deleteUI('RiggingSpeedUp')
pm.scriptJob( killAll=True )
window = pm.window( title="RiggingSpeedUp", iconName="Speed", widthHeight=( 400,400 ) )
pm.columnLayout( )
pm.text('Rename', align='center',width=400, height=20, font='boldLabelFont')
pm.rowColumnLayout( nc=7, cw = [(1,30),(2,30),(3,30),(4,50),(5,100),(6,50),(7,100)] )
pm.radioCollection()
pm.radioButton(label = 'lt', editable = True, onCommand = rename_lt)
pm.radioButton(label = 'rt', editable = True, onCommand = rename_rt)
pm.radioButton(label = 'ct', editable = True, onCommand = rename_ct)
global textFieldName_name
global textFieldEntry_name
textFieldName_name= pm.text( label= 'Name:')
textFieldEntry_name = pm.textField(textFieldName_name, editable = True)
global textFieldName_suffix
global textFieldEntry_suffix
textFieldName_suffix= pm.text( label= 'Suffix:')
textFieldEntry_suffix = pm.textField(textFieldName_suffix, editable = True)
pm.setParent('..')
pm.button( label="Apply",width=400, command=renamer )
pm.button( label="MirrorIntoRt",width=400, command=renamer_mirror )
pm.separator( h=5, style='none')
pm.text('Padding&Snapping', align='center',width=400, height=20, font='boldLabelFont')
global intFieldName_num_name_delete
global intFieldEntry_num_name_delete
pm.rowColumnLayout (nc=2, cw = [(1,200) , (2,200)])
pm.rowColumnLayout (nr= 2 , rh = [(1 , 25) , (2 , 25)] )
intFieldName_num_name_delete = pm.text( label= 'No_Name_Delete :')
intFieldEntry_num_name_delete = pm.intField(intFieldName_num_name_delete, editable = True, value=0)
global textFieldName_ik_suffix
global textFieldEntry_ik_suffix
textFieldName_ik_suffix= pm.text( label= 'Suffix:')
textFieldEntry_ik_suffix = pm.textField(textFieldName_ik_suffix, editable = True)
pm.setParent( '..' )
pm.rowColumnLayout (nc=1 , cw = (1,200) )
pm.button( label="Padding", width=200, command=padding )
pm.separator( h=5, style='none')
pm.button( label='Snapping', width = 200, command=snapping )
pm.separator( h=5, style='none')
pm.setParent( '..' )
pm.setParent( '..' )
pm.text('IK_Stretch', align='center',width=400, height=20, font='boldLabelFont')
pm.button( label="Stretch IK", width=400, command= IK_Stretch )
pm.separator( h=5, style='none')
pm.text('IK_Spline_Stretch&Squash', align='center',width=400, height=20, font='boldLabelFont')
pm.separator( h=5, style='none')
pm.rowColumnLayout (nc=4, cw = [ (1,50) , (2,50) , (3,50) , (4,250) ] )
global intFieldName_num_joint
global intFieldEntry_num_joint
intFieldName_num_joint = pm.text( label= 'No_Joint :')
intFieldEntry_num_joint = pm.intField(intFieldName_num_joint, editable = True, value=0)
global textFieldName_ik_spline_name
global textFieldEntry_ik_spline_name
textFieldName_ik_spline_name= pm.text( label= 'Name:')
textFieldEntry_ik_spline_name = pm.textField(textFieldName_name, editable = True)
pm.setParent( '..' )
pm.button( label="Stretch&Squash IK", width=400, command= squash_stretch_IK )
window.show()
window_creation_speedrig()
view raw gistfile1.txt hosted with ❤ by GitHub
Stretch&Squash Automated Rig GitHub Link
https://gist.github.com/williamyap912/7687ebf0d2f4035cfead1e3a92412a2c

Demo Reel for Graduation

import pymel.core as pm
import maya.mel as mel
import re
'''
Radio button for point lock activation
'''
def button_base( *args ) :
intFieldData_seq = pm.intField( intFieldEntry_seq, editable = True, query = True, value = True)
global radioButton_follicle
radioButton_follicle=0
def button_tip( *args ) :
intFieldData_seq = pm.intField( intFieldEntry_seq, editable = True, query = True, value = True)
global radioButton_follicle
radioButton_follicle=1
def button_both_end( *args ) :
intFieldData_seq = pm.intField( intFieldEntry_seq, editable = True, query = True, value = True)
global radioButton_follicle
radioButton_follicle=2
'''
Radio button for Self Collision activation
'''
def self_col_on( *args ) :
global checkBox_self_col
checkBox_self_col = 1
def self_col_off( *args ) :
global checkBox_self_col
checkBox_self_col = 0
'''
Radio button for Self Collision activation
'''
def col_on( *args ) :
global checkBox_col
checkBox_col = 1
def col_off( *args ) :
global checkBox_col
checkBox_col = 0
'''
Create dynamic hair with multi curve
'''
def hair_joint_multi( *args ) :
'''
Collect Data
'''
intFieldData_num_joint = pm.intField( intFieldEntry_num_joint, editable = True, query = True, value = True)
intFieldData_seq = pm.intField( intFieldEntry_seq, editable = True, query = True, value = True)
if intFieldData_seq == 0 :
seq_curve = intFieldData_seq
elif intFieldData_seq > 0 :
seq_curve = intFieldData_seq 1
if pm.objExists( 'hair_{0}_01_bind'.format( seq_curve + 1 ) ) :
print 'Error on naming sequence'
else :
list_curve = pm.ls( sl= True )
for item in list_curve :
seq_curve = seq_curve + 1
'''
Collect Data
'''
intFieldData_num_joint = pm.intField( intFieldEntry_num_joint, editable = True, query = True, value = True)
'''
Method on reconstruct curve and rename
'''
pm.rebuildCurve( item , ch=1, rpo=1 , rt=0 , end=1 , kr=0 , kcp=0 , kep=1 , kt=0 , s=intFieldData_num_joint, d=3 , tol=0.0001 )
name_curve = pm.rename( item , 'hair_{0}_curve'.format( seq_curve ) )
'''
Method on create joint along curve
'''
pre_joint = ''
root_joint = ''
for i in range( 0 , intFieldData_num_joint ) :
user_default_unit = pm.currentUnit( query=True, linear=True )
pm.currentUnit( linear = 'cm' )
pm.select( cl = True )
new_joint = pm.joint()
mot_path = pm.pathAnimation( new_joint , c = item , fm = True )
pm.cutKey( mot_path + '.u' )
pm.setAttr( mot_path + '.u', i * ( 1.0 / ( intFieldData_num_joint 1 )) )
pm.delete( '{0}.{1}'.format( new_joint , 'tx' ) , icn = True )
pm.delete( '{0}.{1}'.format( new_joint , 'ty' ) , icn = True )
pm.delete( '{0}.{1}'.format( new_joint , 'tz' ) , icn = True )
pm.currentUnit( linear = '{0}'.format(user_default_unit) )
renaming_item = pm.ls( sl = True )
if i == 0 :
pre_joint = new_joint
root_joint = new_joint
pm.rename( renaming_item , 'hair_{0}_{1:02d}_bind'.format( seq_curve ,i+1 ) )
continue
elif i < intFieldData_num_joint 1 :
pm.rename( renaming_item , 'hair_{0}_{1:02d}_bind'.format( seq_curve ,i+1 ) )
else :
pm.rename( renaming_item , 'hair_{0}_{1:02d}_waste'.format( seq_curve ,i+1 ) )
pm.parent( new_joint , pre_joint )
pre_joint = new_joint
pm.joint( root_joint, e = True , zso = True, oj = 'xyz' , ch = True , sao = 'yup' )
'''
Method on create dynamic curve
'''
pm.select( name_curve )
mel.eval('makeCurvesDynamic 2 { "0", "0", "1", "1", "0"}')
pm.hide(item)
pm.parent( 'hairSystem{0}Follicles'.format(seq_curve) , 'hair_{0}_01_bind'.format(seq_curve) )
output_curve_selected = pm.listRelatives( 'hairSystem{0}OutputCurves'.format(seq_curve) , c=1 )
output_curve = pm.rename( output_curve_selected , 'hair_{0}_output_curve'.format( seq_curve ) )
'''
Method on IK Spline
'''
pm.ikHandle(sj='hair_{0}_02_bind'.format(seq_curve), ee='hair_{0}_{1:02d}_waste'.format(seq_curve , intFieldData_num_joint ),c=output_curve, n = 'hair_{0}_ik'.format( seq_curve ), sol= 'ikSplineSolver' , createCurve = False, simplifyCurve = False, rootOnCurve = False , twistType = 'linear' , createRootAxis = False , parentCurve= False, snapCurve = False , rootTwistMode = False)
'''
Method on changing pointLock of dynamic curve
'''
if radioButton_follicle == 0 :
curve_follicle = 'follicleShape{0}'.format(seq_curve)
pm.setAttr(curve_follicle + ".pointLock", 1)
elif radioButton_follicle == 1 :
curve_follicle = 'follicleShape{0}'.format(seq_curve)
pm.setAttr(curve_follicle + ".pointLock", 2)
else :
curve_follicle = 'follicleShape{0}'.format(seq_curve)
pm.setAttr(curve_follicle + ".pointLock", 3)
print '-'*100
print 'dynamic hair created, proceed to attritube'
print '-'*100
'''
Create group if not exist
'''
if pm.objExists('hair_system_group'):
print 'group already exist'
else :
pm.group(em = True, n='hair_system_group' , w = True)
if pm.objExists('hair_ik_group'):
print 'group already exist'
else :
pm.group(em = True, n='hair_ik_group' , w = True)
if pm.objExists('hair_output_group'):
print 'group already exist'
else :
pm.group(em = True, n='hair_output_group' , w = True)
if pm.objExists('hair_joint_group'):
print 'group already exist'
else :
pm.group(em = True, n='hair_joint_group' , w = True)
'''
Parent object to existing group
'''
if pm.objExists('hair_system_group') :
pm.parent( 'hairSystem{0}'.format(seq_curve) , 'hair_system_group')
else :
print 'group not exist'
if pm.objExists('hair_ik_group'):
pm.parent( 'hair_{0}_ik'.format(seq_curve) , 'hair_ik_group' )
else :
print 'group not exist'
if pm.objExists('hair_output_group'):
pm.parent( 'hairSystem{0}OutputCurves'.format(seq_curve) , 'hair_output_group' )
else :
print 'group not exist'
if pm.objExists('hair_joint_group'):
pm.parent( 'hair_{0}_01_bind'.format( seq_curve ) , 'hair_joint_group' )
else :
print 'group not exist'
def dyn_curve_attr ( *args ) :
list_hair_curve = pm.ls(sl=True)
for item_hair_curve in list_hair_curve :
'''
Collect Data
'''
str_item_hair_curve = str(item_hair_curve)
allNum_curve = re.findall(r'\d+',str_item_hair_curve)
num_seq_curve = allNum_curve[0]
hair_joint_rel = pm.select( 'hair_{0}_01_bind'.format(num_seq_curve) )
last_jnt = pm.listRelatives( allDescendents=True , type = 'joint' )[0]
str_last_jnt = str(last_jnt)
allNum_joint = re.findall(r'\d+',str_last_jnt)
int_allNum_joint = int(allNum_joint[1])
floatFieldData_joint_size = pm.floatSliderGrp ( floatFieldEntry_joint_size , query = True, value = True)
floatFieldData_stretch_res = pm.floatSliderGrp ( floatFieldEntry_stretch_res , query = True, value = True)
floatFieldData_compress_res = pm.floatSliderGrp ( floatFieldEntry_compress_res , query = True, value = True)
floatFieldData_bend_res = pm.floatSliderGrp ( floatFieldEntry_bend_res , query = True, value = True)
floatFieldData_twist_res = pm.floatSliderGrp ( floatFieldEntry_twist_res , query = True, value = True)
floatFieldData_curve_att = pm.floatSliderGrp ( floatFieldEntry_curve_att , query = True, value = True)
floatFieldData_curve_att_damp = pm.floatSliderGrp ( floatFieldEntry_curve_att_damp , query = True, value = True)
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
'''
Method on changing SelfCollision of dynamic curve
'''
if checkBox_self_col == 0 :
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".selfCollide", 0 )
elif checkBox_self_col == 1 :
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".selfCollide", 1 )
'''
Method on changing Collision of dynamic curve
'''
if checkBox_col == 0 :
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".collide", 0 )
elif checkBox_col == 1 :
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".collide", 1 )
'''
Method on changing size of joint
'''
for i in range( 1 , int_allNum_joint + 1 ) :
if i < int_allNum_joint :
hair_joint_edit = 'hair_{0}_{1:02d}_bind'.format( num_seq_curve ,i )
elif i == int_allNum_joint :
hair_joint_edit = 'hair_{0}_{1:02d}_waste'.format( num_seq_curve ,i )
pm.setAttr( hair_joint_edit + '.radius' , floatFieldData_joint_size )
'''
Method on changing attribute of dynamic curve
'''
pm.setAttr( curve_hair_sys + '.stretchResistance' , floatFieldData_stretch_res )
pm.setAttr( curve_hair_sys + '.compressionResistance' , floatFieldData_compress_res )
pm.setAttr( curve_hair_sys + '.bendResistance' , floatFieldData_bend_res )
pm.setAttr( curve_hair_sys + '.twistResistance' , floatFieldData_twist_res )
pm.setAttr( curve_hair_sys + '.startCurveAttract' , floatFieldData_curve_att )
pm.setAttr( curve_hair_sys + '.attractionDamp' , floatFieldData_curve_att_damp )
def nucleus_name_changed ( *args ) :
print 'Nucleus name had changed to ' + nucleus_located
'''
locate nucleus
'''
global nucleus_located
nucleus_located = 'nucleus1'
if pm.objExists(nucleus_located) :
nucleus_located = pm.rename ( nucleus_located , 'nucleus1' )
else :
print 'nucleus1 not in the scene'
print 'Create nucleus1 or rename nucleus name back to nucleus1 and run again'
pm.scriptJob( killAll = True )
pm.scriptJob( e = [ 'NameChanged' , nucleus_name_changed ] , cu = True )
def dyn_nucleus_attr ( *args ) :
'''
Collect Data
'''
floatFieldData_gravity = pm.floatSliderGrp ( floatFieldEntry_gravity , query = True, value = True )
floatFieldData_gravityDirectionX = pm.floatSliderGrp ( floatFieldEntry_gravityDirectionX , query = True, value = True )
floatFieldData_gravityDirectionY = pm.floatSliderGrp ( floatFieldEntry_gravityDirectionY , query = True, value = True )
floatFieldData_gravityDirectionZ = pm.floatSliderGrp ( floatFieldEntry_gravityDirectionZ , query = True, value = True )
floatFieldData_airDensity = pm.floatSliderGrp ( floatFieldEntry_airDensity , query = True, value = True )
floatFieldData_windSpeed = pm.floatSliderGrp ( floatFieldEntry_windSpeed , query = True, value = True )
floatFieldData_windDirectionX = pm.floatSliderGrp ( floatFieldEntry_windDirectionX , query = True, value = True )
floatFieldData_windDirectionY = pm.floatSliderGrp ( floatFieldEntry_windDirectionY , query = True, value = True )
floatFieldData_windDirectionZ = pm.floatSliderGrp ( floatFieldEntry_windDirectionZ , query = True, value = True )
floatFieldData_windNoise = pm.floatSliderGrp ( floatFieldEntry_windNoise , query = True, value = True )
floatFieldData_maxCollisionIterations = pm.floatSliderGrp ( floatFieldEntry_maxCollisionIterations , query = True, value = True )
'''
Method on changing attribute of nucleus
'''
pm.setAttr( '{0}.gravity'.format(nucleus_located) , floatFieldData_gravity )
pm.setAttr( '{0}.gravityDirectionX'.format(nucleus_located) , floatFieldData_gravityDirectionX )
pm.setAttr( '{0}.gravityDirectionY'.format(nucleus_located) , floatFieldData_gravityDirectionY )
pm.setAttr( '{0}.gravityDirectionZ'.format(nucleus_located) , floatFieldData_gravityDirectionZ )
pm.setAttr( '{0}.airDensity'.format(nucleus_located) , floatFieldData_airDensity )
pm.setAttr( '{0}.windSpeed'.format(nucleus_located) , floatFieldData_windSpeed )
pm.setAttr( '{0}.windDirectionX'.format(nucleus_located) , floatFieldData_windDirectionX )
pm.setAttr( '{0}.windDirectionY'.format(nucleus_located) , floatFieldData_windDirectionY )
pm.setAttr( '{0}.windDirectionZ'.format(nucleus_located) , floatFieldData_windDirectionZ )
pm.setAttr( '{0}.windNoise'.format(nucleus_located) , floatFieldData_windNoise )
pm.setAttr( '{0}.maxCollisionIterations'.format(nucleus_located) , floatFieldData_maxCollisionIterations )
def dyn_nucleus_attr_default ( *args ) :
'''
Method on changing attribute of nucleus back to default
'''
pm.setAttr( '{0}.gravity'.format(nucleus_located) , 9.8 )
pm.setAttr( '{0}.gravityDirectionX'.format(nucleus_located) , 0 )
pm.setAttr( '{0}.gravityDirectionY'.format(nucleus_located) , 1 )
pm.setAttr( '{0}.gravityDirectionZ'.format(nucleus_located) , 0 )
pm.setAttr( '{0}.airDensity'.format(nucleus_located) , 1 )
pm.setAttr( '{0}.windSpeed'.format(nucleus_located) , 0 )
pm.setAttr( '{0}.windDirectionX'.format(nucleus_located) , 1 )
pm.setAttr( '{0}.windDirectionY'.format(nucleus_located) , 0 )
pm.setAttr( '{0}.windDirectionZ'.format(nucleus_located) , 0 )
pm.setAttr( '{0}.windNoise'.format(nucleus_located) , 0 )
pm.setAttr( '{0}.maxCollisionIterations'.format(nucleus_located) , 4 )
floatFieldEntry_gravity.setValue( 9.8 )
floatFieldEntry_gravityDirectionX.setValue( 0 )
floatFieldEntry_gravityDirectionY.setValue( 1 )
floatFieldEntry_gravityDirectionZ.setValue( 0 )
floatFieldEntry_airDensity.setValue( 1 )
floatFieldEntry_windSpeed.setValue( 0 )
floatFieldEntry_windDirectionX.setValue( 1 )
floatFieldEntry_windDirectionY.setValue( 0 )
floatFieldEntry_windDirectionZ.setValue( 0 )
floatFieldEntry_windNoise.setValue( 0 )
floatFieldEntry_maxCollisionIterations.setValue( 4 )
def dyn_curve_attr_rough_low (*args) :
list_hair_curve = pm.ls(sl=True)
for item_hair_curve in list_hair_curve :
'''
Collect Data
'''
str_item_hair_curve = str(item_hair_curve)
allNum_curve = re.findall(r'\d+',str_item_hair_curve)
num_seq_curve = allNum_curve[0]
hair_joint_rel = pm.select( 'hair_{0}_01_bind'.format(num_seq_curve) )
last_jnt = pm.listRelatives( allDescendents=True , type = 'joint' )[0]
str_last_jnt = str(last_jnt)
allNum_joint = re.findall(r'\d+',str_last_jnt)
int_allNum_joint = int(allNum_joint[1])
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".selfCollide", 1 )
pm.setAttr( curve_hair_sys + ".collide", 1 )
pm.setAttr( curve_hair_sys + '.stretchResistance' , 100 )
pm.setAttr( curve_hair_sys + '.compressionResistance' , 70 )
pm.setAttr( curve_hair_sys + '.bendResistance' , 50 )
pm.setAttr( curve_hair_sys + '.twistResistance' , 80 )
pm.setAttr( curve_hair_sys + '.startCurveAttract' , 0.1 )
pm.setAttr( curve_hair_sys + '.attractionDamp' , 0.05 )
floatFieldEntry_stretch_res.setValue( 100 )
floatFieldEntry_compress_res.setValue( 70 )
floatFieldEntry_bend_res.setValue( 50 )
floatFieldEntry_twist_res.setValue( 80 )
floatFieldEntry_curve_att.setValue( 0.1 )
floatFieldEntry_curve_att_damp.setValue( 0.05 )
collision_dyn.setValue( 1 )
selfCollision_dyn.setValue( 1 )
def dyn_curve_attr_rough_medium (*args) :
list_hair_curve = pm.ls(sl=True)
for item_hair_curve in list_hair_curve :
'''
Collect Data
'''
str_item_hair_curve = str(item_hair_curve)
allNum_curve = re.findall(r'\d+',str_item_hair_curve)
num_seq_curve = allNum_curve[0]
hair_joint_rel = pm.select( 'hair_{0}_01_bind'.format(num_seq_curve) )
last_jnt = pm.listRelatives( allDescendents=True , type = 'joint' )[0]
str_last_jnt = str(last_jnt)
allNum_joint = re.findall(r'\d+',str_last_jnt)
int_allNum_joint = int(allNum_joint[1])
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".selfCollide", 1 )
pm.setAttr( curve_hair_sys + ".collide", 1 )
pm.setAttr( curve_hair_sys + '.stretchResistance' , 120 )
pm.setAttr( curve_hair_sys + '.compressionResistance' , 100 )
pm.setAttr( curve_hair_sys + '.bendResistance' , 70 )
pm.setAttr( curve_hair_sys + '.twistResistance' , 120 )
pm.setAttr( curve_hair_sys + '.startCurveAttract' , 0.3 )
pm.setAttr( curve_hair_sys + '.attractionDamp' , 0.1 )
floatFieldEntry_stretch_res.setValue( 120 )
floatFieldEntry_compress_res.setValue( 100 )
floatFieldEntry_bend_res.setValue( 70 )
floatFieldEntry_twist_res.setValue( 120 )
floatFieldEntry_curve_att.setValue( 0.3 )
floatFieldEntry_curve_att_damp.setValue( 0.1 )
collision_dyn.setValue( 1 )
selfCollision_dyn.setValue( 1 )
def dyn_curve_attr_rough_high (*args) :
list_hair_curve = pm.ls(sl=True)
print list_hair_curve
for item_hair_curve in list_hair_curve :
'''
Collect Data
'''
str_item_hair_curve = str(item_hair_curve)
allNum_curve = re.findall(r'\d+',str_item_hair_curve)
num_seq_curve = allNum_curve[0]
hair_joint_rel = pm.select( 'hair_{0}_01_bind'.format(num_seq_curve) )
last_jnt = pm.listRelatives( allDescendents=True , type = 'joint' )[0]
str_last_jnt = str(last_jnt)
allNum_joint = re.findall(r'\d+',str_last_jnt)
int_allNum_joint = int(allNum_joint[1])
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
pm.setAttr( curve_hair_sys + ".selfCollide", 1 )
pm.setAttr( curve_hair_sys + ".collide", 1 )
dyn_curve_prop_stretch_res = pm.setAttr( curve_hair_sys + '.stretchResistance' , 145 )
dyn_curve_prop_compress_res = pm.setAttr( curve_hair_sys + '.compressionResistance' , 125 )
dyn_curve_prop_bend_res = pm.setAttr( curve_hair_sys + '.bendResistance' , 100 )
dyn_curve_prop_twist_res = pm.setAttr( curve_hair_sys + '.twistResistance' , 150 )
dyn_curve_prop_curve_att = pm.setAttr( curve_hair_sys + '.startCurveAttract' , 0.5 )
dyn_curve_prop_curve_att_damp = pm.setAttr( curve_hair_sys + '.attractionDamp' , 0.15 )
floatFieldEntry_stretch_res.setValue( 145 )
floatFieldEntry_compress_res.setValue( 125 )
floatFieldEntry_bend_res.setValue( 100 )
floatFieldEntry_twist_res.setValue( 150 )
floatFieldEntry_curve_att.setValue( 0.5 )
floatFieldEntry_curve_att_damp.setValue( 0.15 )
collision_dyn.setValue( 1 )
selfCollision_dyn.setValue( 1 )
'''
Window creation
'''
class window_creation :
def changing_properties( self , *args ) :
dyn_nucleus_prop_gravity = pm.getAttr('{0}.gravity'.format(nucleus_located))
dyn_nucleus_prop_gravityDirectionX = pm.getAttr('{0}.gravityDirectionX'.format(nucleus_located))
dyn_nucleus_prop_gravityDirectionY = pm.getAttr('{0}.gravityDirectionY'.format(nucleus_located))
dyn_nucleus_prop_gravityDirectionZ = pm.getAttr('{0}.gravityDirectionZ'.format(nucleus_located))
dyn_nucleus_prop_airDensity = pm.getAttr('{0}.airDensity'.format(nucleus_located))
dyn_nucleus_prop_windSpeed = pm.getAttr('{0}.windSpeed'.format(nucleus_located))
dyn_nucleus_prop_windDirectionX = pm.getAttr('{0}.windDirectionX'.format(nucleus_located))
dyn_nucleus_prop_windDirectionY = pm.getAttr('{0}.windDirectionY'.format(nucleus_located))
dyn_nucleus_prop_windDirectionZ = pm.getAttr('{0}.windDirectionZ'.format(nucleus_located))
dyn_nucleus_prop_windNoise = pm.getAttr('{0}.windNoise'.format(nucleus_located))
dyn_nucleus_prop_maxCollisionIterations = pm.getAttr('{0}.maxCollisionIterations'.format(nucleus_located))
self.floatFieldEntry_gravity.setValue( dyn_nucleus_prop_gravity )
self.floatFieldEntry_gravityDirectionX.setValue( dyn_nucleus_prop_gravityDirectionX )
self.floatFieldEntry_gravityDirectionY.setValue( dyn_nucleus_prop_gravityDirectionY )
self.floatFieldEntry_gravityDirectionZ.setValue( dyn_nucleus_prop_gravityDirectionZ )
self.floatFieldEntry_airDensity.setValue( dyn_nucleus_prop_airDensity )
self.floatFieldEntry_windSpeed.setValue( dyn_nucleus_prop_windSpeed )
self.floatFieldEntry_windDirectionX.setValue( dyn_nucleus_prop_windDirectionX )
self.floatFieldEntry_windDirectionY.setValue( dyn_nucleus_prop_windDirectionY )
self.floatFieldEntry_windDirectionZ.setValue( dyn_nucleus_prop_windDirectionZ )
self.floatFieldEntry_windNoise.setValue( dyn_nucleus_prop_windNoise )
self.floatFieldEntry_maxCollisionIterations.setValue( dyn_nucleus_prop_maxCollisionIterations )
'''
Collect data
'''
list_hair_curve = pm.ls(sl=True)
for item_hair_curve in list_hair_curve :
if len(list_hair_curve) > 0 :
first_item_hair_curve = list_hair_curve[0]
str_item_hair_curve = str(first_item_hair_curve)
allNum_curve = re.findall(r'\d+',str_item_hair_curve)
num_seq_curve = allNum_curve[0]
curve_hair_sys = 'hairSystemShape{0}'.format(num_seq_curve)
'''
set value for ui based on selection
'''
if item_hair_curve == 'hair_{0}_output_curve'.format(num_seq_curve) :
print ' '
print '-'*100
print first_item_hair_curve + ' is the first hair curve to show properties'
dyn_curve_prop_collision = pm.getAttr (curve_hair_sys + '.collide')
dyn_curve_prop_self_collision = pm.getAttr (curve_hair_sys + '.selfCollide')
dyn_curve_prop_stretch_res = pm.getAttr( curve_hair_sys + '.stretchResistance' )
dyn_curve_prop_compress_res = pm.getAttr( curve_hair_sys + '.compressionResistance' )
dyn_curve_prop_bend_res = pm.getAttr( curve_hair_sys + '.bendResistance' )
dyn_curve_prop_twist_res = pm.getAttr( curve_hair_sys + '.twistResistance' )
dyn_curve_prop_curve_att = pm.getAttr( curve_hair_sys + '.startCurveAttract' )
dyn_curve_prop_curve_att_damp = pm.getAttr( curve_hair_sys + '.attractionDamp' )
if dyn_curve_prop_collision == True :
collision_on_off = 1
else :
collision_on_off = 0
if dyn_curve_prop_self_collision == True :
selfCollision_on_off = 1
else :
selfCollision_on_off = 0
'''
show the value of properties
'''
print' '
print'-'*100
if collision_on_off == 1 :
print 'Collision is On'
else :
print 'Collision is Off'
if selfCollision_on_off == 1 :
print 'Self Collision is On'
else :
print 'Self Collision is Off'
print 'stretch resistance = {0} '.format(dyn_curve_prop_stretch_res)
print 'compress resistance = {0} '.format(dyn_curve_prop_compress_res)
print 'bend resistance = {0} '.format(dyn_curve_prop_bend_res)
print 'twist resistance = {0} '.format(dyn_curve_prop_twist_res)
print 'curve attraction = {0} '.format(dyn_curve_prop_curve_att)
print 'curve attraction damp = {0} '.format(dyn_curve_prop_curve_att_damp)
print'-'*100
print' '
self.floatFieldEntry_stretch_res.setValue( dyn_curve_prop_stretch_res )
self.floatFieldEntry_compress_res.setValue( dyn_curve_prop_compress_res )
self.floatFieldEntry_bend_res.setValue( dyn_curve_prop_bend_res )
self.floatFieldEntry_twist_res.setValue( dyn_curve_prop_twist_res )
self.floatFieldEntry_curve_att.setValue( dyn_curve_prop_curve_att )
self.floatFieldEntry_curve_att_damp.setValue( dyn_curve_prop_curve_att_damp )
self.collision_dyn.setValue( collision_on_off )
self.selfCollision_dyn.setValue( selfCollision_on_off )
else :
dyn_curve_prop_stretch_res = 0
dyn_curve_prop_compress_res = 0
dyn_curve_prop_bend_res = 0
dyn_curve_prop_twist_res = 0
dyn_curve_prop_curve_att = 0
dyn_curve_prop_curve_att_damp = 0
else :
print 'nothing selected or not output curve'
def __init__(self) :
self.ui_creation()
def ui_creation(self) :
if pm.window('hair_window' , exists = True ) :
pm.deleteUI('hair_window')
window = pm.window( 'hair_window' , title="HairRigging", iconName="SpeedHairRig", widthHeight=( 450,900 ) )
pm.columnLayout( )
pm.text(' ')
pm.text( 'Create Dynamic Hair Based on Curve' )
pm.text(' ')
pm.rowColumnLayout( nc=7, cw = [ (1,50),(2,40),(3,80),(4,70),(5,50),(6,60),(7,50) ] )
pm.radioCollection()
pm.radioButton(label = 'Base', editable = True, onCommand = button_base)
pm.radioButton(label = 'Tip', editable = True, onCommand = button_tip)
pm.radioButton(label = 'Both_End', editable = True, onCommand = button_both_end)
global intFieldName_num_joint
global intFieldEntry_num_joint
global intFieldName_seq
global intFieldEntry_seq
intFieldName_num_joint = pm.text( label= 'No_Joint :')
intFieldEntry_num_joint = pm.intField(intFieldName_num_joint, editable = True, value=0)
intFieldName_seq = pm.text( label= 'Sequence :')
intFieldEntry_seq = pm.intField(intFieldName_seq, editable = True, value=0)
pm.setParent('..')
pm.button( label="Create Hair Joint", width=400, command= hair_joint_multi )
pm.text(' ')
pm.setParent('..')
pm.columnLayout( )
pm.text('-'*100)
pm.text( 'Dynamic Curve Properties' )
pm.text(' ')
pm.rowColumnLayout( nc=3, cw = [ (1,50),(2,150),(3,150) ] )
pm.text(' ')
self.collision_dyn = pm.checkBox( label = 'Collision' , ofc = col_off , onc = col_on )
self.selfCollision_dyn = pm.checkBox( label = 'selfCollision' , ofc = self_col_off , onc = self_col_on )
global collision_dyn
global selfCollision_dyn
collision_dyn = self.collision_dyn
selfCollision_dyn = self.selfCollision_dyn
pm.setParent('..')
self.floatFieldEntry_joint_size = pm.floatSliderGrp ( label= 'Joint Size' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_stretch_res = pm.floatSliderGrp ( label= 'Stretch Resistance' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_compress_res = pm.floatSliderGrp ( label= 'Compression Resistance' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_bend_res = pm.floatSliderGrp ( label= 'Bend Resistance' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_twist_res = pm.floatSliderGrp ( label= 'Twist Resistance' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_curve_att = pm.floatSliderGrp ( label= 'Start Curve Attraction' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_curve_att_damp = pm.floatSliderGrp ( label= 'Atrraction Damp' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =0 , fieldMaxValue = 200.0 , value= 0 , precision = 3 , step = 0.01 )
global floatFieldEntry_joint_size
global floatFieldEntry_stretch_res
global floatFieldEntry_compress_res
global floatFieldEntry_bend_res
global floatFieldEntry_twist_res
global floatFieldEntry_curve_att
global floatFieldEntry_curve_att_damp
floatFieldEntry_joint_size = self.floatFieldEntry_joint_size
floatFieldEntry_stretch_res = self.floatFieldEntry_stretch_res
floatFieldEntry_compress_res = self.floatFieldEntry_compress_res
floatFieldEntry_bend_res = self.floatFieldEntry_bend_res
floatFieldEntry_twist_res = self.floatFieldEntry_twist_res
floatFieldEntry_curve_att = self.floatFieldEntry_curve_att
floatFieldEntry_curve_att_damp = self.floatFieldEntry_curve_att_damp
pm.button( label="Change Attritbute", width=400, command = dyn_curve_attr )
pm.separator( h=5, style='none')
pm.button( label="Low Resistance", width=400, command = dyn_curve_attr_rough_low )
pm.button( label="Medium Resistance", width=400, command = dyn_curve_attr_rough_medium )
pm.button( label="High Resistance", width=400, command = dyn_curve_attr_rough_high )
pm.separator( h=10, style='none')
pm.text('-'*100)
pm.text( 'Nucleus Properties' )
pm.text(' ')
self.floatFieldEntry_gravity = pm.floatSliderGrp ( label= 'Gravity' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 9.8 )
self.floatFieldEntry_gravityDirectionX = pm.floatSliderGrp ( label= 'Gravity DirectionX' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_gravityDirectionY = pm.floatSliderGrp ( label= 'Gravity DirectionY' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 1 )
self.floatFieldEntry_gravityDirectionZ = pm.floatSliderGrp ( label= 'Gravity DirectionZ' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_airDensity = pm.floatSliderGrp ( label= 'Air Density' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 1 )
self.floatFieldEntry_windSpeed = pm.floatSliderGrp ( label= 'Wind Speed' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_windDirectionX = pm.floatSliderGrp ( label= 'Wind Direction X' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 1 )
self.floatFieldEntry_windDirectionY = pm.floatSliderGrp ( label= 'Wind Direction Y' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_windDirectionZ = pm.floatSliderGrp ( label= 'Wind Direction Z' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_windNoise = pm.floatSliderGrp ( label= 'Wind Noise' , field= True , minValue = 200 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 0 )
self.floatFieldEntry_maxCollisionIterations = pm.floatSliderGrp ( label= 'Max Collision Iterations' , field= True , minValue = 0 , maxValue =200.0 , fieldMinValue =200 , fieldMaxValue = 200.0 , value= 4 )
global floatFieldEntry_gravity
global floatFieldEntry_gravityDirectionX
global floatFieldEntry_gravityDirectionY
global floatFieldEntry_gravityDirectionZ
global floatFieldEntry_airDensity
global floatFieldEntry_windSpeed
global floatFieldEntry_windDirectionX
global floatFieldEntry_windDirectionY
global floatFieldEntry_windDirectionZ
global floatFieldEntry_windNoise
global floatFieldEntry_maxCollisionIterations
floatFieldEntry_gravity = self.floatFieldEntry_gravity
floatFieldEntry_gravityDirectionX = self.floatFieldEntry_gravityDirectionX
floatFieldEntry_gravityDirectionY = self.floatFieldEntry_gravityDirectionY
floatFieldEntry_gravityDirectionZ = self.floatFieldEntry_gravityDirectionZ
floatFieldEntry_airDensity = self.floatFieldEntry_airDensity
floatFieldEntry_windSpeed = self.floatFieldEntry_windSpeed
floatFieldEntry_windDirectionX = self.floatFieldEntry_windDirectionX
floatFieldEntry_windDirectionY = self.floatFieldEntry_windDirectionY
floatFieldEntry_windDirectionZ = self.floatFieldEntry_windDirectionZ
floatFieldEntry_windNoise = self.floatFieldEntry_windNoise
floatFieldEntry_maxCollisionIterations = self.floatFieldEntry_maxCollisionIterations
pm.button( label="Change Attritbute", width=400, command= dyn_nucleus_attr )
pm.button( label="Default", width=400, command= dyn_nucleus_attr_default )
pm.scriptJob(e = [ 'SelectionChanged' , self.changing_properties ], cu = True, parent= 'hair_window')
window.show()
window_creation()
Github web address for hair rig script
https://gist.github.com/williamyap912/9b770550c2eca58a4b877ba8abe0191f