Wednesday, February 27, 2013

Top 10 Autodesk Maya Python API Gotchas When Getting Started


I found an awesome article today from last year's GDC session by Kristion Middlemiss. I want to share it with you. It is really useful for Maya Python beginners.

10)   Not Understanding the Difference between Python Script and Python API
Maya has four programming interfaces, two of which are using the Python language. It’s important to know the distinction between the terminology of Python Script and the Python API, because they each access different functionality within Maya (with very little overlap). The other two interfaces are Maya Embedded Language (MEL) and the C++ API.

9) Python Plug-in Disclosure
You cannot hide your Python API code from users! If you’re a games developer looking to create Python plug-ins in-house and not worried about protecting your code, then feel free to code away. But it you want to protect, or commercialize and sell your hard work, you should consider using C++ to create your plug-ins.

8) Must use Autodesk Specific Version of Qt for Building PyQt
Building PyQt to work with Maya is a three step process. First you need to compile Qt using the Autodesk's Modified Qt Source Code (new for 2012) that is located on the Autodesk.com site. Then you need to compile SIP (generates Python bindings for C++) against your built Qt libraries. Last, you need to compile PyQt against your built SIP libraries. Check the website for the correct versions or you could have some difficulties down the road in your tools.

7) Awareness of Potential Python API Performance Penalties
In certain situations when computation involves complex or many API calls, the Python API may take a performance penalty compared to the C++ API. This is because the Python API sits on top of the C++ API. This results in an extra level of conversion through C++ and as well as Python is an interpreted language which is slower by nature. For example if you are thinking of doing a Python API shader, C++ will be the better choice, but for most other tasks Python is perfect!

6) Working with Multiple Versions of Maya Equals Multiple Versions of Python
If you are working on multiple versions of Maya, then you need to keep in mind that you will need to have multiple version of Python. Also if you are using PyQt, multiple versions of PyQt will need to be installed on your computer. As nice as it would be to use the same version of Python and PyQt for every version of Maya, it’s just not realistic as things are always improving in the Python and PyQt releases. Keep yourself educated in the Maya documentation for the versions that are used in each major release, and on which platform.

5) Your Python API Code is not Working, and you cannot find the Problem
When working with the Python API, like all humans, you will have errors or code you want to debug; but how the heck do you debug it? Unfortunately, there are no out-of-the-box tools in Maya, but there are some good solutions available. Cyrille Fauvel from Autodesk has integrated a Maya Python debugger into the Eclipse IDE. The details are available on Autodesk.com, at the Maya Developer Center page. Dean Edmonds also from Autodesk has integrated the PDB debugger into the Script Editor within Maya by overriding the stdin and stout functions. Also, if you Google “Python in Maya” group you will see other solutions.

4) Knowing when and how to Use MScriptUtil Class
Many of the API methods in Maya require that one or more of their parameters be passed as pointers or references (return values can be pointers or references as well). Because Python does not have the concept of references or pointers, you will need the utility class called MScriptUtil for working with those pointers and references in Python. MScriptUtil bridges this gap between Python and its underlying C++ API. When you see the characters * or & in the documentation for simple data types like integers and floats, think MScriptUtil!

3) The Reference Documentation is written for C++, but you are Using Python
If you do not know C++, at first glance the reference documentation will be very confusing!  But don’t worry; just put your eye blinders on to certain things when reading it. Because Python is a more simplified language than C++ (but none the less powerful), there are certain components in the documentation you can ignore. For example the class MString and MStringArray are not available in Python and instead you will work with strings as they are in native Python. Another example is that there is no MStatus class in Python and instead you will use standard Python error checking (try, except, catch). Try to think of this as having a mini translator going on in your brain, you see MStatus, so you just ignore it!

2) Trying to live in a Bubble and Teach Yourself Everything
There is no possible way to memorize or learn every single Maya API class, so don’t be shy to use the resources available. As they say “Be Resourceful” and learn from others successes, mistakes and questions. Maya has been around for over ten years, and there is lots of API information out there (www.autodesk.com/developmaya). Also, you can check out the new book “Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API” by Adam 

1) Mechtley and Ryan Trowbridge.
Not Fully Grasping the Maya Architecture and How the Python API Leverages It
If you don’t completely understanding the Maya architecture, command engine and the Dependency Graph, you will run into trouble as your tools get more complex. Take the time to learn these components as they are very different than any other animation product. Because of this complexity, it makes Maya more flexible and powerful than any other product. Check out the free Maya Python API webcast recording located here (www.autodesk.com/developmaya)

Tuesday, February 26, 2013

Data Attributes


While data attributes defined both ways may have unique values for any particular instance, those that exist in the class definition can be accessed without an instance of the class, as the following hypothetical example:
import sys;
class NewClass():
    data_attribute1 = 1;
    def __init__(self):
        self.data_attribute2 = 2;
print(NewClass.data_attribute1);
try:
    print(NewClass.data_attribute2);
except AttributeError:
    print(sys.exc_info()[0]);
instance = NewClass();
print(instance.data_attribute1);
print(instance.data_attribute2);
1
<type 'exceptions.AttributeError'>
1
2

Sunday, February 24, 2013

Basics of class implementation in Python

By reading ten pages of Chapter five today, I learnt instantiation and attributes. Here is what I programmed during reading the book:


class NewClass:
    pass;
dir(NewClass);
# Result: ['__doc__', '__module__'] #
class NewClass(object):
    pass;
     
dir(NewClass);
# Result: ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] #
instance1 = NewClass();
instance2 = NewClass();
instance3 = NewClass();
class NewClass():
    data_attribute = None;
    def function_attribute(*args):pass;
print(dir(NewClass));
['__doc__', '__module__', 'data_attribute', 'function_attribute']

Friday, February 22, 2013

Object-oriented programming

So today, I plan to start learning chapter 5. But before that, I need to review what is object-oriented programming, and some basic concepts.

1) Object-oriented programming (OOP) is a programming paradigm that represents concepts as "objects" that have data fields (attributes that describe the object) and associated procedures known asmethods. Objects, which are usually instances of classes, are used to interact with one another to design applications and computer programs.

2) Class is a construct that is used to create instances of itself – referred to as class instances, class objects, instance objects or simply objects. A class defines constituent members which enable its instances to have state and behavior.

3) Object is a location in memory having a value and referenced by an identifier. An object can be a variable, function, or data structure. With the later introduction of object-oriented programming the same word, "object," refers to a particular instance of a class.

4Method is a subroutine (or procedure) associated with a class. Methods define the behavior to be exhibited by instances of the associated class at program run time. Methods have the special property that at run-time  they have access to data stored in an instance of the class (or class instance or class object or object) they are associated with and are thereby able to control the state of the instance.

5Instance is an occurrence or a copy of an object, whether currently executing or not. Instances of a class share the same set of attributes, yet will typically differ in what those attributes contain.

I also learnt the three main differences between object-oriented and process-oriented. They are Inheritance, Encapsulation,Polymorphism. Since they are so complicated, it is better not describe them in detail here.

Wednesday, February 20, 2013

Using Eclipse as a Maya IDE

I used two hours to setup Eclipse as a Maya IDE. But until now, it doesn't work.
Here is the link I tried:
http://www.creativecrash.com/tutorials/using-eclipse-as-a-maya-ide#tabs
http://nealbuerger.com/2012/07/eclipse-python-editor-maya-2013/
http://autodesk.com/us/maya/2011help/PyMel/eclipse.html

I'm too tired now, but I will finish this tomorrow. Hope I could make it work tomorrow!!!

Tuesday, February 19, 2013

My first Module: spike

My first module is pretty simple, just create a soccer ball and then extrude it twice as the picture shows below. But I did learn lots of new maya commands and understand Module deeper. Here is the script:

"""This script prints some information and creates a spike ball."""
import maya.cmds
def addSpikes(obj):
    """This function adds spikes to a polygon object."""
    try: polycount = maya.cmds.polyEvaluate(obj, face=True)
    except: raise
    for i in range(0, polycount):
        face = '%s.f[%s]'%(obj, i)//遍历obj的所有face
        maya.cmds.polyExtrudeFacet(face, ltz=1, ch=0)//第一次extrude
        maya.cmds.polyExtrudeFacet(face, ltz=1, ch=0, ls=[.1,.1,.1])//第二次extrude 缩小为上一次的0.1倍
    maya.cmds.polySoftEdge(obj, a=180, ch=0)
    maya.cmds.select(obj)

print('module name: %s'%__name__)
print('globals:')
for k in globals().keys(): print('\t%s'%k)
addSpikes(maya.cmds.polyPrimitive(ch=0)[0])//创建一个soccer ball
Result:

Monday, February 18, 2013

Commands Python Help


1) Useful to check out the flags of each maya command
import maya.cmds;
print(maya.cmds.help('maya command'));

2) Good website to check out detail information about each maya command

http://download.autodesk.com/us/maya/2011help/CommandsPython/

Sunday, February 17, 2013

50 Important Modules in Python

This week I learnt a lot about Module in Python even I do not post my study notes on this blog anymore.Module, in my understanding, is a standalone Python file containing a sequence of definitions and executable statements and Python itself ships with a large library of default modules.

Here, I summarized 50 really useful Modules including Databases, GUIs, Images, Sound, OS interaction, Web, etc.

Graphical interface wxPython          http://wxpython.org     
Graphical interface pyGtk        http://www.pygtk.org    
Graphical interface pyQT         http://www.riverbankcomputing.co.uk/pyqt/        
Graphical interface Pmw         http://pmw.sourceforge.net/
Graphical interface Tkinter 3000    http://effbot.org/zone/wck.htm    
Graphical interface Tix    http://tix.sourceforge.net      
                         
Database          MySQLdb http://sourceforge.net/projects/mysql-python/    
Database          PyGreSQL          http://www.pygresql.org/      
Database          Gadfly       http://gadfly.sourceforge.net/     
Database          SQLAlchemy     http://www.sqlalchemy.org/ 
Database          psycopg   http://www.initd.org/pub/software/psycopg/       
Database          kinterbasdb      http://kinterbasdb.sourceforge.net/     
Database          cx_Oracle         http://www.cxtools.net/default.aspx?nav=downloads
Database          pySQLite  http://initd.org/tracker/pysqlite    
                         
MSN Messenger      msnlib      http://auriga.wearlab.de/~alb/msnlib/ 
MSN Messenger      pymsn      http://telepathy.freedesktop.org/wiki/Pymsn       
MSN Messenger      msnp        http://msnp.sourceforge.net/        
Network  Twisted    http://twistedmatrix.com/     
Images     PIL    http://www.pythonware.com/products/pil/ 
Images     gdmodule         http://newcenturycomputers.net/projects/gdmodule.html 
Images     VideoCapture  http://videocapture.sourceforge.net/   
                         
Sciences and Maths         scipy         http://www.scipy.org/    
Sciences and Maths         NumPy     http://numpy.scipy.org/           
Sciences and Maths         numarray          http://www.stsci.edu/resources/software_hardware/numarray
Sciences and Maths         matplotlib         http://matplotlib.sourceforge.net/        
                         
Games     Pygame    http://www.pygame.org/news.html      
Games     Pyglet       http://www.pyglet.org/ 
Games     PySoy        http://www.pysoy.org/  
Games     pyOpenGL         http://pyopengl.sourceforge.net/ 
                         
Jabber      jabberpy  http://jabberpy.sourceforge.net/  
                         
Web scrape      http://zesty.ca/python/scrape.html       
Web pythonweb       http://www.pythonweb.org/ 
Web mechanize        http://wwwsearch.sourceforge.net/mechanize/  
                         
Localisation      geoname.py     http://www.zindep.com/blog-zindep/Geoname-python/      
                         
Serial port         pySerial    http://pyserial.sourceforge.net/    
Serial port         USPP         http://ibarona.googlepages.com/uspp 
                         
Parallel Port     pyParallel          http://pyserial.sourceforge.net/pyparallel.html   
                         
USB Port  pyUSB       http://bleyer.org/pyusb/
                         
Windows pywin32   http://sourceforge.net/projects/pywin32/    
Windows pywinauto        http://www.openqa.org/pywinauto/     
Windows pyrtf          http://pyrtf.sourceforge.net/
                         
PDA/GSM/Mobiles  pymo        http://www.awaretek.com/pymo.html 
PDA/GSM/Mobiles  pyS60        http://sourceforge.net/projects/pys60 
                         
Sound       pySoundic         http://pysonic.sourceforge.net/    
Sound       pyMedia  http://pymedia.org/        
Sound       FMOD       http://www.fmod.org/   
Sound       pyMIDI     http://www.cs.unc.edu/Research/assist/developer.shtml   
                         
GMail       libgmail    http://libgmail.sourceforge.net/    
Google     pyGoogle http://pygoogle.sourceforge.net/ 
Expect      pyExpect  http://pexpect.sourceforge.net/   
WordNet  pyWordNet       http://osteele.com/projects/pywordnet/      
Command line cmd http://blog.doughellmann.com/2008/05/pymotw-cmd.html         
Compiler backend    llvm-py     http://mdevan.nfshost.com/llvm-py/     
3D    VPython   http://vpython.org
pyDes   DES lock/unlock  http://twhiteman.netfirms.com/des.html
pyparsing    similar to lex/yacc but easier   pyparsing.wikispaces.com

Friday, February 15, 2013

Develop functions for a texture processing framework

Today, I finished reading Chapter 3, which is faster than my plan. Because this chapter focuses on lots of iteration and branching which is familiar with me. I wrote a small project to attach texture on my model. Here is the result:

From this chapter, I have a firm grasp of many of the fundamentals of programming with Python, including ins and outs of functions, loops, branching and error handling. But to be honest, I'm still only scratching the surface of Python in Maya.

So far, I already learned some basic Maya commands and the essentials for understanding data and variables in Python. Moreover, I walk through a simple texture-processing framework for Maya. Now, I'm capable of crating Python programs, the next step is to organize them into modules, which is exactly the content of Chapter 4.

Monday, February 11, 2013

Found a Good Webesite

Today, I found a really useful website, which I could search every command in Python. I believe this website will help me a lot in the future O(∩_∩)O
http://docs.python.org/2/library/


Friday, February 8, 2013

Listing and Selecting Nodes

1) maya.cmds.1s()
    retrieving a list of nodes in the scene
Example1:
import maya.cmds;
nodes = maya.cmds.ls(type='transform');
print(nodes); //result: [u'front', u'persp', u'side', u'top']
    pass a string specifying the type of objects you would like in your list
Example2:
nodes = maya.cmds.ls('persp*');
print(nodes); //result: [u'persp', u'perspShape']


2) maya.cmds.select()
    populate the current global selection list
    maya.cmds.select('side*', 'top*'); //select the transform and shape nodes for the top and side 
cameras.
    print(maya.cmds.ls(selection=True)); //result: [u'side', u'sideShape', u'top', u'topShape']

3) Conjunction ls & select
    selection_list = ['front', 'persp', 'side', 'top']; //create a list of items to select
    maya.cmds.select(selection_list);
    print(maya.cmds.ls(sl=True));
   maya.cmds.select(maya.cmds.ls(type='shape')); //select all of the shape nodes in the scene
   print(maya.cmds.ls(sl=True));

   

Wednesday, February 6, 2013

Function Arguments

1) Template: def function_name(optional, input, parameters):
                          pass;
2) Default Arguments: By assigning the default argument in the function's declaration, you are ensuring that the prefix input parameter will always have a value, even if one is not supplied when the function is  called
    Example:
    def process_all_textures(texture_node, prefix='my_'):
          print('Processed%s%s'%(prefix, texture_node));
    process_all_textures(texture); //result: Processed my_file1

3) Positional Argument(位置参数): not real argument, just declare there has a argument and pass data.
4) keyword Arguments (关键字参数): Prefix value for argument so that even you do not pass value to the keyword argument, it still has value.

5) Two issues for arguments:
    (1) Positional arguments must come before keyword arguments, both in the function declaration and when calling the function.
    (2) An argument can be passed by position or by keyword, but not both.

6) Variable-Length Argument Lists with the * Operator
    allow a developer to define a function with an arbitrary number of arguments.
7) Variable-Length Argument Lists with the ** Operator
    tells the interpreters to pack all key-value pairs passed to the function into a dictionary.
 
    

Sunday, February 3, 2013

Container Types

1) Sequences: nums = [1,2,3,3,5,6,7,7,7,8,9] (could exists same number)
2) Sets: numset = set(nums) = [1,2,3,5,6,7,8,9] (pruned duplicate elements, more efficient)
             While you can generate a set from a list, a list cannot be an item in a set!
3) Dictionaries: numberNames = {1:'one', 2:'two', 3:'three', 'one':1, 'two':2, 'three':3};
    (Mutable object, hashable. The keys do not all need to be the same type, the up dictionary mapped numbers to names, as well as names to numbers.)

Practice:
import maya.cmds;
loc = maya.cmds.spaceLocator()[0];
print(maya.cmds.xform(loc, q=True, rotateOrder=True));
RESULT:xyz

Friday, February 1, 2013

Working with Numbers

1) Number Types: integers, long integers, floating-point numbers, and complex numbers

2) Basic Operators:
    x/y: quotient of x and y, if x and y are integers, result is rounded down
    x//y: floored quotient of x and y, use with floating-point numbers to return a decimal result identical to x/y if x and y  were integers
    x%y: remainder of x/y
    divmod(x,y): typle that is (x//y, x%y)
    pow(x,y) = x**y: x to the y power (x的y次方)

3) s.index(x): index of first x in s
    s.count(x): total occurrences of x in s
 

Attributes

1) getAttr and setAttr

    import maya.cmds
    loc = maya.cmds.spaceLocator()[0]; //create a new locator and store the name of its transform mode in a variable called loc
    sx = maya.cmds.getAttr(loc+ '.scaleX'); //store the locator's x-scale in a variable named sx
    print(sx); // print the result, which will be 1 by default
    sx *= 2; //double the sx value
    maya.cmds.setAttr(loc+'.scaleX', sx); //assign the new value to the node's attribute by passing a string with the node's name, a period, and the attribute name

2) Compound Attributes
    print(maya.cmds.xform(loc, q=True, translation=True)); //print the locator's translation using the xform command
    [0.0, 0.0, 0.0] //the result
    maya.cmds.xform(loc, translation=[0,1,0]); //using the xform command to set a new translation value (using a list)
    print(maya.cmds.getAttr(loc+'.translate')); //print the locator's translation using getAttr command
    [(0.0, 1.0, 0.0)] // the command returns a list that contains a tuple
    maya.cmds.setAttr(loc+'.translate', 1, 2, 3); //using setAttr to set a new translation value for the locator
Result:

3) connectAttr and disconnectAttr
    The basic requirement for attributes to be connected is that they be of the same type.  
import maya.cmds;
sphere = maya.cmds.polySphere()[0];
cube = maya.cmds.polyCube()[0];
//create a sphere and a cube and store the names of their transform nodes
maya.cmds.connectAttr(cube+'.ry', sphere+'.ty'); //connect the cube's y-rotation to the sphere's y-translation
maya.cmds.select(cube);
maya.cmds.disconnectAttr(cube+'.ry', sphere+'.ty');
# Result: Disconnect pCube2.rotate.rotateY from pSphere2translate.translateY. #
//execute the following lines to create a multiplyDivide node between the two attributes to scale the effect
mult = maya.cmds.createNode('multiplyDivide');
maya.cmds.connectAttr(cube+'.rt', mult+'.input1X');
maya.cmds.setAttr(mult+'.input2X', 1.0/90.0);
maya.cmds.connectAttr(mult+'.outputX', sphere+'.ty');
maya.cmds.select(cube);
Result: if you rotate the cube, the sphere translates 1 unit for every 90 degrees of rotation.