Let's learn how to leverage Python to write and load JSON files. In this mini course, we'll use the awesome technique to load control sizes, in case our rig is ever rebuilt.
And, to learn more about auto-rigging in Maya, have a look at this course:
from maya import cmds
import json
'''
Save Control Sizes - Python/JSON
email example:me@me.com
'''
#Get Data Path
data_path = cmds.workspace(q=True, rd=True) + 'data/'
print(data_path)
#Get all controls to eventually store their radius values
cmds.select('*_anim', r=True)
ctrls = cmds.ls(sl=True, type='transform')
#Create an empty list to append the data we'll store in our JSON file
ctrl_rad_json = []
for ctrl in ctrls:
#Create a variable to store each control's radius channel + the keys we'll use to call upon the radius values in our JSON file
ctrl_rad = ctrl + '.radius'
#Get the radius of each control
ctrl_rad_val = cmds.getAttr(ctrl_rad)
#Store both the radius channels and their values in variable "ctrl_rad_data"
ctrl_rad_data = [ctrl_rad, ctrl_rad_val]
#Append the data in our empty list "ctrl_rad_json" to extract it from the for loop
ctrl_rad_json.append(ctrl_rad_data)
#Convert List to Dictionary
ctrl_rad_json = dict(ctrl_rad_json)
#Write our JSON file
with open(data_path + 'set_ctrl_radius.json', 'w', encoding='utf-8') as ctrl_rad_file:
json.dump(ctrl_rad_json, ctrl_rad_file)
from maya import cmds
import json
'''
Load Control Sizes - Python/JSON
'''
#Get Data Path
data_path = cmds.workspace(q=True, rd=True) + 'data/'
#Store JSON Data in variable "jsctrlrad"
with open(data_path + 'set_ctrl_radius.json', 'r') as ctrl_rad:
jsctrlrad = json.load(ctrl_rad)
'''
Store all control objects + the path to their radius channels
'''
cmds.select('*_anim', r=True)
ctrls = cmds.ls(sl=True, type='transform')
#Find amount of controls stored in variable "ctrls"
size = len(ctrls)
for i in range(size):
#Create a variable to store each control's radius channel + the keys in our JSON file
ctrl_rad = ctrls[i] + '.radius'
#Iteratively set the value of each radius channel using the keys stored in our JSON file
cmds.setAttr(ctrl_rad, jsctrlrad[ctrl_rad])
In this lesson, we will learn how to create a Python class to append a directional string to selected objects. We will also learn how to work with arguments and keyword arguments in a class.
In this lesson, we will learn how PySide2 can be used to create a window with a text field and button. We will also learn how to create a signal that runs a function when the button is clicked.
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)
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!')
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.
In this tutorial, we will learn how to build joint chains from locators with Python in Maya.
Level: Beginner to Intermediate...
Software: Maya 2016 - up
In this tutorial, we will learn how to build joint chains from locators with Python in Maya.
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 Moduleimporthou#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"forctrlinrig.glob("*_anim"):
#Select all nodes that match pattern "*_anim" | NOTE: ctrl.setSelected(1, 0) also works :)ctrl.setSelected(True, clear_all_selected=False)
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 Moduleimportmaya.cmdsasmc#Store selected transforms in variable "sel"sel=mc.ls(sl=True, type='transform')
#Return selectionprintsel#For Loop - iterative through variable "sel" with "each", and do the following...foreachinsel:
#Store keyable, unlocked channels in variable "keyable"keyable=mc.listAttr(each, k=True, u=True)
printkeyable#For Loop - iterative through all keyable/unlocked channelsforkeyinkeyable:
#Get default values of each keyable/unlocked channeldefaults=mc.attributeQuery(key, n=each, ld=True)
#For Loop - set each item back to its default valuefordvindefaults:
printdvmc.setAttr(each+'.'+key, dv)
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 Moduleimporthou'''ThisPythonscriptwillcreateaSubnetwork, alongwithwith2BoneobjectsparentedtoaNull...Instructions: simplyrunthescriptinthePythonSourceEditor :)
'''#Create Subnetsubnet=hou.node("/obj").createNode("subnet", "%s_Skeleton"%"Cool")
#Prevent Overlapping Nodessubnet.moveToGoodPosition()
#Create Root Null and Use Name of Subnet as Prefixroot=subnet.createNode("null", "%s_Root"%subnet)
#Offset Root Null in the Translate Y axisroot.parm("ty").set(2)
#Clean Transforms of Nullroot.moveParmTransformIntoPreTransform()
#Create First Bonebone_0=subnet.createNode("bone", "%s_Bone_0"%root)
#Parent First Bone to Root Nullbone_0.setNextInput(root)
bone_0.moveToGoodPosition()
bone_0.parm("rx").set(-120)
bone_0.moveParmTransformIntoPreTransform()
#Enable Xray on Bonebone_0.useXray(True)
#Create Second Bonebone_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)
Here's a lesson on pinning a soft body curve in Blender. This can be useful for ropes, cables, etc...
Couldn't find a tutorial on this, so sometimes you've just gotta do it yourself :)
Software: Blender 2.8 or higher
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
This tutorial is a followup to the course I posted prior, where we learn how to generate curves from motion trails. In this tutorial, we’ll learn how to attach rigs to a path in Maya with the help of Python.
Hope you enjoy!
This is a quick walk-through of the Python tool we will learn how to build in the Python Driven Curve Animation course:
https://maxdepth.tv/product/python-driven-curve-animation/
Also here's a tutorial on generating curves from motion trails in Maya:
https://www.delanimation.com/tutorials-1/2020/1/2/generating-curves-from-motion-trails-in-maya
Take care!
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)