Args, Kwargs, and Mirroring Transforms w/ Python in Maya
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 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.
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)
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!')
Added a new course, published on CG Circuit!
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.
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
#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)
#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)
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)
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)
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')
(Click the image to learn more…)
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!
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)