Delanimation

Delano Athias - Animator

Segmenting Joints with Python in Maya [Update]

In this mini course, we'll learn how to create a simple Python tool to segment selected joint chains. We'll also learn how to use an object's DAG path to avoid name-clash errors.

from maya import cmds

'''
Joint Segment Tool
Instructions: select root(s) of joint chain(s) and run script...
'''
#Store selected root joints in variable "sel_jt"
sel_jt = cmds.ls(sl=True, type='joint')
#Var for segment length
count = 9
#Var for joint radius offset value
rad_offset = 0.5
#Iterate through each root joint in selection and do the following...
for each_jt in sel_jt:
    #Print each selected joint
    print(each_jt)
    #Find the end joint of the selected root(s)
    end_jt = cmds.listRelatives(each_jt, c=True)[0]
    #Find path to end joint
    end_jt_path = each_jt + '|' + end_jt
    #Store length of chain
    end_offset = cmds.getAttr(end_jt_path + '.tx')
    print(end_offset)
    #Var used for the new radius val of each new joint
    rad = cmds.getAttr(each_jt + '.radius') - rad_offset
    #Force selection of each root joint to create the root of segmented chain
    cmds.select(each_jt, r=True)
    #Create root of segmented chain
    seg_root = cmds.joint(radius=rad)
    #Force selection of segment root to append segmented chain
    cmds.select(seg_root, r=True)
    #Add joints to segment tool based on value stored in "count" var
    for i in range(count):
        #Create a hierarchy of new segment joints
        seg_jt = cmds.joint(radius=rad)
        #Offset segment joints evenly along chain length
        cmds.move((end_offset/count), 0, 0, ls=True)

Creating an OBJ Exporter with Python in Maya

In this mini-course, we’ll use Python to create a tool for quickly exporting objects as OBJs. We will also learn how to create a progress bar that can be cancelled with the Escape key.

from maya import cmds, mel
'''
OBJ Exporter
Instructions: select object(s) to export and click EXPORT OBJ
[Contact Info]
'''

#UI

#This forces a single instance of window
if cmds.window('w_obj_exp', ex=True):
    cmds.deleteUI('w_obj_exp', window=True)
#This creates a new window
cmds.window('w_obj_exp', t='OBJ Exporter', s=False)
#Add a layout for window
cmds.columnLayout(rs=10, adj=True)
#Add a separator to help organize the window (optional)
cmds.separator()
#Add instructions with Text command
cmds.text('Instructions: select object(s) to export and click EXPORT OBJ')
cmds.separator()
#Create a Text Field with a Button that will be used to browse to the desired export path
cmds.textFieldButtonGrp('tfbg_obj_browse', l='Export Path:', pht='Load Directory', bl='Load Path', bc='go_obj_path()')
cmds.separator()
#Create a button that will export our selected objects as .OBJs
cmds.button(l='EXPORT OBJ', h=40, bgc=[0.2, 0.5, 0.3], c='go_obj_export()')
#Show the window
cmds.showWindow('w_obj_exp')
#Edit the window's Width and Height
cmds.window('w_obj_exp', e=True, wh=[500, 140])

#Functions

#Define a custom function
def go_obj_path():
    #Create a variable to store the desired directory
    path = cmds.fileDialog2(fm=2, cc='Cancel', okc='GO')
    if path:
        #"path[0]" stores the directory alone
        path = path[0]
        #Edit the Text Field to include the path
        cmds.textFieldButtonGrp('tfbg_obj_browse', e=True, tx=path)
    #If a path is not chosen, print "Cancelled"
    else:
        print('Cancelled')
        
def endProcess():
    #Check if preogress of export is cancelled
    interrupt = cmds.progressWindow(q=True, isCancelled=True)
    #If cancelled, make sure "endProgress()" will return the command to interrupt the exporting progress
    if interrupt:
        cmds.progressWindow(endProgress=True)
    return interrupt
    
def go_obj_export():
    #Grab export directory from the Text Field
    path = cmds.textFieldButtonGrp('tfbg_obj_browse', q=True, tx=True)
    #Store objects in selection
    sel = cmds.ls(sl=True, type='transform')
    #Tell the user the export process has started
    print('Export started!')
    #Create the Progress Bar that can be cancelled
    cmds.progressWindow(step=1, status='Exporting...', isInterruptable=True)
    #Store amount of objects in selection
    size = len(sel)
    #Create a variable that will be used to increment the Progress Bar
    iter = 100/size
    #Iterate through each object in selection with For Loop
    for each in sel:
        #This ends the export process using the Escape key
        if endProcess():
            return
        #Increment the Progress Bar using the amount of objects in selection
        cmds.progressWindow(e=True, step=iter, status='Exporting...')
        #Select the objects to export
        cmds.select(each, r=True)
        #Export selected objects as OBJ files
        mel.eval('file -force -options "groups=1;ptgroups=1;materials=1;smoothing=1;normals=1" -typ "OBJexport" -pr -es "' + path + '/' + each + '.obj";')
    #Close the Progress Window
    cmds.progressWindow(endProgress=True)
    #Tell the user the export process has ended
    print('Export completed!')
    #Added a Heads Up Message to remind the user the export process as ended
    cmds.headsUpMessage('Export completed!')

Auto-rigging Basics w/ Python in Maya: IK/FK Limbs

Hello! I'd like to share with you a few auto-rigging techniques inside of Maya that I've used quite a bit to quickly generate control rigs for animation. We're about to learn production-proven techniques that will create clean and blendable IK/FK systems while keeping our scenes organized. We'll start by creating Python definitions that we'll use to speed up repetitive tasks. Then finish the course by setting up our tool to generate a scalable control rig while learning good practices to keep our code efficient and simple to modify. By the end of this course, you'll gain rigging knowledge that can help you save hours of time in your own process. Level: Beginner to Advanced Software: Maya 2016 - up Project files: https://app.box.com/s/380zi4881iranu191cvaop1ug63mkkfi Bonus: https://vimeo.com/520870461 This lesson will show you how we can approach building joint chains from locators.

Hello! I'd like to share with you a few auto-rigging techniques inside of Maya that I've used quite a bit to quickly generate control rigs for animation. We're about to learn production-proven techniques that will create clean and blendable IK/FK systems while keeping our scenes organized. We'll start by creating Python definitions that we'll use to speed up repetitive tasks. Then finish the course by setting up our tool to generate a scalable control rig while learning good practices to keep our code efficient and simple to modify. By the end of this course, you'll gain rigging knowledge that can help you save hours of time in your own process.

Level: Beginner to Advanced

Software: Maya 2016 - up

Project files:

https://app.box.com/s/380zi4881iranu191cvaop1ug63mkkfi

Bonus:

https://vimeo.com/520870461

This lesson will show you how we can approach building joint chains from locators.

Selecting Nodes with Identical Names with Python in Houdini

In this lesson, we will learn how Python can be used to select nodes with similar patterns in Houdini. Level: Beginner to Intermediate

#Import Houdini's Command Module
import hou
#Store path to Subnet in variable "rig"
rig = hou.node("/obj/Rig")
#For Loop - iterate through network, in search of nodes that match pattern "*_anim"
for ctrl in rig.glob("*_anim"):
    #Select all nodes that match pattern "*_anim" | NOTE: ctrl.setSelected(1, 0) also works :)
    ctrl.setSelected(True, clear_all_selected=False)

Restoring Default Values on Selected Items with Python in Maya

In this lesson, we will build a simple Python tool in Maya to reset any select control and custom channel back to its default value. Level: Beginner to Intermediate

#Import Maya's Command Module
import maya.cmds as mc
#Store selected transforms in variable "sel"
sel = mc.ls(sl=True, type='transform')
#Return selection
print sel
#For Loop - iterative through variable "sel" with "each", and do the following...
for each in sel:
    #Store keyable, unlocked channels in variable "keyable"
    keyable = mc.listAttr(each, k=True, u=True)
    print keyable
    #For Loop - iterative through all keyable/unlocked channels
    for key in keyable:
        #Get default values of each keyable/unlocked channel
        defaults = mc.attributeQuery(key, n=each, ld=True)
        #For Loop - set each item back to its default value
        for dv in defaults:
            print dv
            mc.setAttr(each + '.' + key, dv)

Creating Skeletons w/ Python in Houdini

In this tutorial, we will learn how to generate a skeleton in Houdini using Python.

In this tutorial, we'll get our feet wet with auto-rigging by learning how to generate a skeleton in Houdini using Python.

#Import Houdini's Command Module
import hou

'''
This Python script will create a Subnetwork, along with with 2 Bone objects parented to a Null...
Instructions: simply run the script in the Python Source Editor :)
'''

#Create Subnet
subnet = hou.node("/obj").createNode("subnet", "%s_Skeleton" % "Cool")
#Prevent Overlapping Nodes
subnet.moveToGoodPosition()
#Create Root Null and Use Name of Subnet as Prefix
root = subnet.createNode("null", "%s_Root" % subnet)
#Offset Root Null in the Translate Y axis
root.parm("ty").set(2)
#Clean Transforms of Null
root.moveParmTransformIntoPreTransform()
#Create First Bone
bone_0 = subnet.createNode("bone", "%s_Bone_0" % root)
#Parent First Bone to Root Null
bone_0.setNextInput(root)
bone_0.moveToGoodPosition()
bone_0.parm("rx").set(-120)
bone_0.moveParmTransformIntoPreTransform()
#Enable Xray on Bone
bone_0.useXray(True)
#Create Second Bone
bone_1 = subnet.createNode("bone", "%s_Bone_1" % root)
bone_1.setNextInput(bone_0)
bone_1.moveToGoodPosition()
bone_1.parm("rx").set(60)
bone_1.moveParmTransformIntoPreTransform()
bone_1.useXray(True)

IKFK Blending w/ Python in Maya

In this lesson, we will learn how Python can be used to quickly create blendable IK/FK rigs in Maya, saving hours of setup time :) Annnd, here's a link to the Python tutorial for segmenting joint chains: https://vimeo.com/430055602 Level: Beginner to Intermediate

import maya.cmds as mc
import maya.mel as mel
#Instructions: Select Root Joint(s) and run script...
#[NOTE: joint chain should have "_skin" suffix]
jnts = mc.ls(sl=True, type='joint')
for jnt in jnts:
    mc.select(jnt, r=True)
    rootJnt = mc.ls(sl=True, type='joint')[0]
    if mc.objExists('CONTROL') != True:
        mc.spaceLocator(n='CONTROL')
    else:
        print 'Proceed'
    loc = 'CONTROL'
    #FK Chain
    mc.select(rootJnt, r=True)
    mc.duplicate(rr=True)
    rootJnt_fk_node = mc.ls(sl=True, type='joint')[0]
    print rootJnt_fk_node
    rootJnt_fk = mc.rename(rootJnt_fk_node.replace('skin1', 'fk'))
    mc.select(rootJnt_fk, hi=True)
    jnts_fk = mc.ls(sl=True, type='joint')
    for each_fk in jnts_fk:
        rad = mc.getAttr(each_fk + '.radius')
        mc.setAttr(each_fk + '.radius', rad + 0.5)
    mel.eval('searchReplaceNames "skin" "fk" "hierarchy"')
    fk_chain = mc.ls(sl=True, type='joint')
    #IK Chain
    mc.select(rootJnt, r=True)
    mc.duplicate(rr=True)
    rootJnt_ik_node = mc.ls(sl=True, type='joint')[0]
    print rootJnt_ik_node
    rootJnt_ik = mc.rename(rootJnt_ik_node.replace('skin1', 'ik'))
    mc.select(rootJnt_ik, hi=True)
    jnts_ik = mc.ls(sl=True, type='joint')
    for each_ik in jnts_ik:
        rad = mc.getAttr(each_ik + '.radius')
        mc.setAttr(each_ik + '.radius', rad + 1)
    mel.eval('searchReplaceNames "skin" "ik" "hierarchy"')
    ik_chain = mc.ls(sl=True, type='joint')
    #FK/IK Blending
    mc.addAttr(loc, ln=(rootJnt + '_fkIk'), at='double', min=0, max=1)
    fkIk = loc + '.' + rootJnt + '_fkIk'
    print fkIk
    mc.setAttr(fkIk, e=True, k=True)
    mc.select(rootJnt, hi=True)
    main_jnts = mc.ls(sl=True, type='joint')
    for main_jnt in main_jnts:
        blender = mc.createNode('blendColors', n=(main_jnt + '_fk_ik_blend'))
        fk = main_jnt.replace('skin', 'fk')
        ik = main_jnt.replace('skin', 'ik')
        mc.connectAttr((ik + '.rotate'), (blender + '.color1'), f=True)
        mc.connectAttr((fk + '.rotate'), (blender + '.color2'), f=True)
        mc.connectAttr((blender + '.output'), (main_jnt + '.rotate'), f=True)
        mc.connectAttr(fkIk, (blender + '.blender'), f=True)

Segmenting Joints with Python in Maya

In this tutorial, we'll learn how to create a Python tool to segment joint chains in Maya. Level: Beginner-Intermediate

import maya.cmds as mc
#Segment Joints - select root joint and run script
val = 5
selRoot = mc.ls(sl=True, type='joint')[0]
mc.select(selRoot, hi=True)
chain = mc.ls(sl=True)
print chain
if len(chain) > 1: 
    selChild = mc.listRelatives(selRoot, c=True)[0]
    print selChild
    tx = mc.getAttr(selChild + '.tx')
    rad = mc.getAttr(selChild + '.radius')
    mc.select(selRoot, r=True)
    for i in range(1, val):
        jnt = mc.joint(rad=rad)
        mc.move(tx/val, 0, 0, ls=True)
    lastJnt = mc.ls(sl=True, type='joint')[0]
    print lastJnt
    mc.parent(selChild, lastJnt)
else:
    mc.warning('Please select bone object')

Generating Curves from Motion Trails in Maya

In this tutorial, we will learn a technique for creating curves from Editable Motion Trails with the help of Python in Maya. Here's the script: https://www.dropbox.com/s/9wz0dfnrcpvdtu8/motionTrail_to_curve_python.pdf?dl=0

import maya.cmds as mc

'''
Motion Trail to Curve
Instructions: select animated object(s), and run script…
'''
#Find selected transform nodes
sel = mc.ls(sl=True, type='transform')
#Get playback start time
start = mc.playbackOptions(q=True, min=True)
#Get playback end time
end = mc.playbackOptions(q=True, max=True)
#For Loop - iterate on each selected object
for each in sel:
    #Create geometry - used later for a snapshot trail
    geo = mc.polyCube()[0]
    #Point Constrain the geometry to the selected object
    mc.pointConstraint(each, geo)
    #Select the geo we created and create an animated snapshot
    mc.select(geo, r=True)
    #Create variable "snap_node" that stores the snapshot group
    snap_node = mc.snapshot(n=each + '_snap', i=1, st=start, et=end, u='animCurve')
    #Find parented objects stored in snapshot group
    trail_geo = mc.listRelatives(snap_node[0], c=True)
    #Get the amount of objects parented to snapshot group
    size = len(trail_geo)
    #Create Curve
    cv_node = mc.curve(d=1, p=[(0, 0, 0), (0, 0, 1)])
    #Rebuild the curve to create the new curve we will align to our motion trail
    cv = mc.rebuildCurve(cv_node, ch=False, rpo=True, rt=0, end=0, s=size-1, d=1)
    #Select all points on the rebuilt curve
    mc.select((cv[0] + '.cv[0:*]'), r=True)
    #Store component selection in variable "pts"
    pts = mc.ls(sl=True, fl=True)
    #For Loop - iterate using the amount of snapshat geo stored in snapshot group  
    for i in range(size):
        #Select each snapshot geo
        mc.select(trail_geo[i], r=True)
        #Connect a cluster to each snapshot mesh
        cl = mc.cluster()
        #Rename the snapshot clusters
        mc.rename(cl[1], (each + '_' + str(i) + '_cl'))
    #Clear selection
    mc.select(cl=True)
    #For Loop - iterate using the amount of snapshat geo stored in snapshot group
    for i in range(size):
        #Create variable for snapshot clusters
        cl_geo = each + '_' + str(i) + '_cl'
        #Select each curve point and create a cluster
        mc.select(pts[i], r=True)
        cl_pt_node = mc.cluster()
        #Rename curve point clusters
        cl_pt = mc.rename(cl_pt_node[1], (each + '_' + str(i) + '_pt_cl'))
        #Now, align curve clusters to snapshot clusters!
        mc.delete(mc.pointConstraint(cl_geo, cl_pt))
    #Remove initial geometry used for snapshot, and remove snapshot group
    mc.delete(geo, snap_node[0]) 
    #Remove history on curve to bake the cluster deformations
    mc.delete(cv, ch=True)  
    #Finally, make the curve smooth
    mc.rebuildCurve(cv, ch=False, rpo=True, rt=0, end=0, kcp=True, kep=True, d=3)