Wednesday, December 4, 2013

Maya API Learning Resources

I am on a journey to learn about the Maya API using Python and C++. Below are some helpful blogs, and Autodesk documentation that I have found useful in my development. Feel free to leave a comment below to add to the list.

Autodesk Maya Developers:

Maya 2014 API Docs:

Maya 2013 API Docs:

Maya Station:

User groups:
Google Group, Python Programming for Autodesk Maya:

Casual Learner:

Chad Vernon:

Chris Devito:

Chris Evans:

Cyrille Fauvel:

Daisuke Maki:


Dimitry Kachkovski:

Dorian Fevrier:

Dunham Lee:

Ethan Shilling:

Jordan Hueckstaedt:

Koichi Tamura:

Mattias Bergbom:

Marco Giordano

Meng Xie:

Michael Tsai:

Parzival Roethlein:

Richard Kazuo Maegaki:

Sam Hodge:

Serge Scherbakov:



Video Training:

Wednesday, October 30, 2013

Cluster Edgeloops [Maya Python]

A Maya Python script that adds a cluster to each edge loop based off a single edge ring selection.

Saturday, October 5, 2013

V-Ray Dirt Multi Tile Baker [Maya Python]

This is a tool I wrote that will bake out V-Ray Dirt based off a min and max UV Region set by the user. I have used this in production on assets with a hundred tiles and baking out at 4 K resolution.

I will be releasing this in the near future on Creative Crash.

V-Ray Dirt Param Documentation
V-Ray Dirt Examples

Video Demo:

Input Mesh:


Wednesday, October 2, 2013

Joint Labeling Function [Maya Python]

This is a Python function that I have created to help me do joint labeling in Maya.

Oct 6th, 2013 - Add help docs. To access this type, 'acJntLabel.__doc__' or 'help(acJntLabel)'
Oct 8th, 2013 - Add functionality for user to pass joints through a selection or a list.

Video Demo:

Source Code:

 Author: Andrew Kin Fun Chan  
 Date: Sept 2013  
 Version: 1.0  
 Compatibility: Maya 2011+ (It will probably work in older versions as well. Contact me if you have issues.)  
 import maya.cmds as mc  
 def toList(objects):  
   This function takes in data and returns it as a list.  
   if isinstance(objects, str):  
     return [objects]  
   elif isinstance(objects, tuple):  
     return list(objects)  
   return objects  
 #acceptable side keys to use.  
 sideDict = {  
 #acceptable type keys to use.  
 typeDict = {  
       'Index Finger':19,  
       'Middle Finger':20,  
       'Ring Finger':21,  
       'Pinky Finger':22,  
       'Extra Finger':23,  
       'Big Toe':24,  
       'Index Toe':25,  
       'Middle Toe':26,  
       'Ring Toe':27,  
       'Pinky Toe':28,  
       'Extra Toe':29  
 acJntLabel ('Left', 'Other',None, 'oi')  
 def acJntLabel (side, type, joints = None, *args):  
   [Description:] This is a function that joint labels using the user input or selected joints.  
     If the selected joint names were...  
       lf_joint1_bnd, lf_joint2_bnd, lf_joint3_bnd  
     I would want to assign the side to Left, type to Other,   
     and remove 'lf_' & '_bnd' from the joint label name.   
     acJntLabel ('Left', 'Other', None, 'lf_','_bnd')  
   @param side: Name of joint label side.  
   @type side: *str*  
     Acceptable side parameters:  
       'Center', 'Left', 'Right', 'None'  
   @param type: Name of joint label type.  
   @type side: *str*  
     Acceptable type parameters:  
       'None', 'Root', 'Hip', 'Knee', 'Foot', 'Toe', 'Spine', 'Neck', 'Head', 'Collar', 'Shoulder',   
       'Elbow', 'Hand', 'Finger', 'Thumb', 'PropA', 'PropB', 'PropC', 'Other', 'Index Finger', 'Middle Finger',  
       'Ring Finger', 'Pinky Finger', 'Extra Finger', 'Big Toe', 'Index Toe', 'Middle Toe', 'Ring Toe',  
       'Pinky Toe', 'Extra Toe'  
   @param joints: List of joint names to label. If param is set to None, then get joints based off user selection.  
   @type side: *str*, *tuple*, *list*   
   @param *args: Name of strings you would like to remove from the joint name.  
   @type *args: *str*  
   joints = toList(joints)  
   if not joints:  
      joints = (sl = True)  
      if not joints:  
        raise RuntimeError('Must select or pass in joints.')  
   if side not in sideDict.keys():  
     raise RuntimeError('Side name,%s, must be one of the following: %s' % (side, sideDict.keys()))    
   if type not in typeDict.keys():  
     raise RuntimeError('Type name, %s, must be one of the following: %s' % (type, typeDict.keys()))  
   for jnt in joints:  
     print jnt  
     if not mc.objExists(jnt):  
       print '%s joint does not exist... Continuing to next joint.' % (jnt)  
     #assigning the side and type to all selected joints.  
     mc.setAttr ((jnt + '.side'), sideDict[side])  
     mc.setAttr ((jnt + '.type'), typeDict[type])  
     jntNewName = jnt  
     #looping through the args to remove them from the name.  
     for i, arg in enumerate(args):  
       jntNewName = jntNewName.replace(arg, '')  
     #assign the name of the joint label with the new name.  
     mc.setAttr ((jnt+'.otherType'), jntNewName, type ='string' )  

Sunday, September 29, 2013

Save and Reload Selection [Maya Python]

This is a Python script for Maya that can save your selection and reload it at a later point in your session.
 ## --------------------------------------------------------------------  
 Author: Andrew Kin Fun Chan  
 Date: Sept 2013  
 Version: 1.0  
 Compatibility: Maya 2011+ (It will probably work in older versions as well. Contact me if you have issues.)  
 Function:        Commands:  
 Load Selection:     reloadSel = AC_RememberSelection(1)  
 Reload Selection:    AC_RememberSelection(0)  
 ## --------------------------------------------------------------------  
 import maya.cmds as mc  
 def AC_RememberSelection(x):  
   if x == 1:  
     print 'Storing Selection'  
     loadSel =  
     print 'Reloading Selection.' (reloadSel)  
   return (loadSel)  

Saturday, September 28, 2013

Zero Transforms with Groups. [Maya Python]

When it comes to rigging, it's important to keep controllers clean while keeping it's orientation. Since freeze transformations destroys the orientation data, this is a little script I wrote to zero out object transforms using groups.

Video Demo:

Source Code:

 ## --------------------------------------------------------------------  
 Author: Andrew Kin Fun Chan  
 Date: Sept 2013  
 Version: 1.0  
 Compatibility: Maya 2011+ (It will probably work in older versions as well. Contact me if you have issues.)  
 Install Instructions:  
      1. Copy the mel script ( to your local user/scripts folder:  
        Example path to icons folder:   
        C:\Documents and Settings\*USERNAME*\My Documents\maya\#.#\scripts        
      2. Copy the icon file (ZeroTransformsWithGroup.png) to your user/prefs/icons folder:  
           Example path to icons folder:   
           C:\Documents and Settings\*USERNAME*\My Documents\maya\#.#\prefs\icons        
        3. Then type the below code into a Maya Python tab:                                 
           import AC_ZeroTransformsWithGroup as zero  
      4. Create the command on the shelf and so you have a button.   
       You should now have a new shelf button.   
       When you click the button it will create a group above   
       your selection to zero out the transforms.  
     A script that will take your selection and zero out the   
     transforms by putting an empty group above it with matching  
     transforms. This script only works on single selection.   
 ## --------------------------------------------------------------------  
 import maya.cmds as mc  
 def AC_ZeroTransformsWithGroup():  
   #Getting the Long and Short names of my selection.  
   zeroSelection = (sl = True, long = True)  
   zeroSelectionShort = (sl = True, shortNames = True)  
   #Check if anything is referenced.  
   if zeroSelection == None:  
     print 'Please select something with transforms to zero out.'  
   #Check if list is empty.  
     if not zeroSelection:  
       print 'Please select something with transforms to zero out.'  
       print 'cool'  
       for obj in enumerate(zeroSelection):  
         i = obj[0]  
         zeroParent = mc.listRelatives (obj[1], parent = True)  
   #Create the empty group respecting the hierarchy. Checks to see if there is a parent or not.  
         if zeroParent == None:  
  ( obj[1], n = (zeroSelectionShort[i] + '_ZERO'), em = True, r = True, p = obj[1])  
           mc.parent ((zeroSelectionShort[i] + '_ZERO'), w = True)  
           mc.parent ( obj[1], (zeroSelectionShort[i] + '_ZERO'))  
           print 'Created empty zero group in world space.'  
  ( obj[1], n = (zeroSelectionShort[i] + '_ZERO'), em = True, r = True, p = obj[1])  
           mc.parent ( (obj[1] + '|' + zeroSelectionShort[i] + '_ZERO'), zeroParent[i] )  
           mc.parent ( obj[1], (zeroSelectionShort[i] + '_ZERO'))  
           print 'Created empty zero group hierarchy.'  

Monday, December 10, 2012

Geometry Paint Tool Maya 2011 and earlier.

Geometry Paint is a tool part of Maya 2012 as part of the bonus tools, but this has been in Maya for quite some time now. I will show how to use an artisian brush to paint geometry to another geometry's surface using Maya 2011. I haven't tried this on any version earlier than 2008 but I think it's been implemented as early as that.

Make sure the geometry you want to put on the surface has the pivot on the bottom with Y axis oriented up, and have the transforms frozen at 0,0,0 world space. For the geometry you wish to paint on. It must have UVs and must be at 1001 UV space. If you can't modify the UVs because of existing texture maps, than you could use UV sets to create a second set of UVs.

On the toolbar go to Modify>Paint Scripts Tool Option Box.

If this is your first time you'll need to navigate to the Setup tab.

Type 'geometryPaint' into Tool setup cmd and hit enter.

After hitting enter, it will auto complete the rest and pop up another menu.

In Geometry fill in the name of the geometry you wish to paint. In my case, I've named it instance1, instance2, instance3, and instance4. These are the settings I chose to use in this example. I will go over some of the settings below. If you wish the geometry to be instanced have duplicate unchecked.

After you are happy with the placement of the geometries you are free to modify their translation, rotation, and scale. You'll need to set the brush to modify, and name the geometry according to modify the correct ones. For example if instance1 what I input, it will only modify those pieces. You'll need to use the brush settings by using replace/add, and using changing values. It may be easier to just manually rotate each piece after you have all the pieces oriented to get the desired rotation but I thought it would be good to cover the ability to modify through the brush.

Geometry Paint Settings:

One of the important things to take note is the U and V Grid size. In the example below I have it set to 5, and 8. In the below example the surface division level is 10, but the U and V grid size is set to 5. The brush will paint the attach the geometry to the grid point of the U and V grid you specify. In the two examples below I have Jitter Grid disabled so it is placing it uniformly.

With Jitter Grid turned on it will randomize the position of the painted objects. If you play around with Jitter Value it will also have different results.

Align option on and off. It seems to take positive Y as the vector it wants to orient to so make your your instance geometry is oriented correctly.

Below is a link to the documentation for each setting if you wish to learn more about it.
Maya Documentation on each setting