Maya Scripting Primer

Posted by Shih-Chin on Mon, Nov 12, 2018

For many of my artist colleagues who want to learn scripting in Maya, one of their motivations is mostly to automate repetitive or time-consuming manual tasks. Since Maya can show all command history of our user interactions in Script Editor. Therefore, if we know how to perform target instructions manually, we could write a script of all corresponding commands. But finding the equivalent commands is not straightforward in some situations. Besides looking up documentation, we need other strategies.

MEL or Python?

Maya programming interfaces

There are two interfaces can be used to manipulate Maya internal state: Maya Commands and Maya API. On the top of that, Maya provides three programming language options: MEL (Maya Embedded Language), Python and C++.

MEL is Maya’s native scripting language. Everything we do via Maya GUI can be automated by using MEL commands. By contrast, Python is a general purpose programming language. Python scripts are executed by a Python interpreter. The reason we can execute a Python script in Maya is because there is an embedded Python interpreter in Maya, and this specialized interpreter is capable of interpreting Maya Commands (maya.cmds) and Maya API (maya.OpenMaya or maya.api.OpenMaya).

That’s why we can’t execute Maya Python script within Houdini’s Python interpreter and vice versa. (Since they don’t know the dialects used by one another, but they can talk with their common languages though.) Moreover, there is another high-level library called PyMEL which is built upon Maya Python binding. Its interfaces are object-oriented and most intuitive to use among all these choices.

Since Maya shows command history in Script Editor with MEL syntax, thus we have to learn how to read MEL expressions at least. Fortunately, if you are already familiar with any other scripting languages, MEL is quite handy to pick up.

In my personal workflow, I use MEL for interactive command testing and use Python for scripting. PyMEL is pretty intuitive to use but at the cost of API abstraction (e.g. wrappers). I am used to using PyMEL at first, because it has clearer syntax with high readability. If I ran into performance issues (e.g. the lag caused by creating several thousands of nodes and making massive connections), I would rewrite those code with regular Maya commands or Maya Python API. As for tasks with intensive computation, I always develop plug-ins with Maya C++ API for better execution performance.

Recommend Readings for Beginners

A few years ago, I have taught several artist friends of mine to learn programming from the ground up. The most important thing we have learned is to learn how to play (yeah, coding is fun!) the command first. For those people without any programming experience, here are some video lectures and books that might be a good starting point:

If you want to take a different learning path, here is my suggested one:

  1. Learn basic MEL programming (from sec. ‘MEL Overview’ to ‘Creating interfaces’).
  2. Learn Python itself (not in Maya); either read Python tutorial Sec. 1 to Sec. 8 or watch Python tutorial for beginners. Make yourself familiar with the concepts of:
    • data type, variable (mutable or immutable), operators, expression
    • data structures: tuple, list, dictionary, set
    • flow control: if, else, while, for, continue, break
    • functions, arguments and the scope of variables
    • modules
    • errors and exceptions
  3. Learn Maya Python commands and translate your MEL script done in step 1 by using corresponding functions in module maya.cmds.
  4. Learn the concepts of class and data model in Python
  5. Learn PyMEL and refactor the Python script written in step 3.

As for studying of Python, I personally suggest learn Python outside the Maya first. Since Python is a general purpose programming language, it can do many things outside 3D content creation software. Additionally, Python has also been integrated into many software like Maya, Houdini, Nuke, etc. Starting from the core Python language has the benefit to clearly see the boundaries between native language features and the extension modules provided by other embedding software like Maya or Houdini.

Essential Concepts of Computation in Maya

Maya is a node-based system, all computations are composed together as a Dependency Graph (DG). Any action in Maya can be seen as a process of manipulating computation graph. In other words, it’s all about creating/deleting nodes and connecting/disconnecting plugs.

The ‘history’ of a node means its upstream nodes. When we delete history of a certain node, all its upstream nodes are deleted and the computation results are cached in data blocks of that node. To see a computation graph, we could open Node Editor:

Menu of Node Editor

For instance, the figure below shows a graph that produces two sphere meshes, and one of them is triangularized. The history of polySurfaceShape1 is polySphere1, while the ones of pSphereShape1 contains polyTriangulate1 and polySphere1. (polySphere1 is a geometry generator which generates mesh data according to radius and subdivision parameters.)

Poly sphere triangularization

Generally speaking, if we want to automate certain manual routines in Maya, our goal is trying to write a script to setup such computation graph on demand.

Convert Manual Instructions to Script

Suppose we want to write a script to create and assign a lambert shader to a shape. After searching keyword ‘shading’ or ‘hyperShade’ in documentation, our first attempt might look like this along with cmds.shadingNode and cmds.hyperShade:

import maya.cmds as cmds
xform, shape = cmds.polySphere()
shader = cmds.shadingNode('lambert', asShader=True)
cmds.select(shape)
cmds.hyperShade(shader, assign=True)

and the results are errors about missing shader, eh? # Error: No shader is selected to be assigned # # Error: No renderable object is selected for assignment #

It is because Maya uses shadingEngine node to record the information about shader assignment, thus we can’t just assign shader node to selected object directly. Here are the details about shader assignment of custom shape.

Actually, it indeed created a lambert shader successfully. To clarify its root cause, we dig into the command history (NOT the node’s history in Node Editor) of our manual instructions to find out the differences from our script. First, we have to enable Echo All Commands of Script Editor, Echo all commands and clear command history in Script Editor before starting our manual instructions. Clear command history

Execute the manual instruction which creates a Lambert shader in Hypershade, and search for the corresponding commands at very beginning of Script Editor: Command

Now we know the equivalent MEL expression is createRenderNodeCB -asShader “surfaceShader” lambert “”;, but there is no command named createRenderNodeCB in documentation. What is createRenderNodeCB and how do we use it?

The Usage of MEL Command ‘WhatIs’

To find the definition of certain function, we have to use the MEL command whatIs: whatIs createRenderNodeCB; // Result: Mel procedure found in: C:/adsk/Maya2017/scripts/others/createRenderNode.mel It tells us createRenderNodeCB is a MEL procedure defined in createRenderNode.mel. Thus we could just open that MEL script, search function by name and continuously trace into the source code:

global proc string createRenderNodeCB ( string $as, string $flag,
                                 string $type, string $postCommand )
{
    int $projection = (`optionVar -query create2dTextureType` == "projection");
    int $stencil = (`optionVar -query create2dTextureType` == "stencil");
    int $placement = `optionVar -query createTexturesWithPlacement`;
    int $shadingGroup = `optionVar -query createMaterialsWithShadingGroup`;
    int $createAndDrop = 0;
    string $editor = "";

    return renderCreateNode(
        $as,
        $flag,
        $type,
        $postCommand,
        $projection,
        $stencil,
        $placement,
        $shadingGroup,
        $createAndDrop,
        $editor);
}

It’s more than that, whatIs can also be used to query command or variable: whatIs “sphere”; // Result: Command //
whatIs “initToolBox”; // Result: Mel procedure found in: /u/mayauser/maya/scripts/initToolBox.mel //
whatIs “kaosFieldTest”; // Result: Script found in: /u/mayauser/maya/scripts/kaosFieldTest.mel //
whatIs “fdsafda”; // Result: Unknown //
int $abc[42]; whatIs “$abc”; // Result: int[] variable //
$s=`pwd`; whatIs “$s”; // Result: string variable //

Reveal Details of Runtime Command

Now here is a quick quiz, please find out the corresponding command for ‘new scene’.

Based on what we have learned so far, we can easily get the answer is NewScene. But after applying whatIs to it, we get a new type of command named Run Time Command. Conceptually, a runtime command is a wrapper of other commands or scripts. To reveal its actual commands underneath, we need to use runtimeCommand with flag -c: whatIs NewScene; // Result: Run Time Command //
runTimeCommand -q -c NewScene; // Result: performNewScene 0; //
whatIs performNewScene; // Result: Mel procedure found in: C:/adsk/Maya2017/scripts/startup/performNewScene.mel

By using two MEL commands whatIs and runtimeCommand, we have figured out the equivalent function for ’new scene’ is performNewScene.

To wrap it up, the entire workflow is:

  1. Enable Echo All Commands and clear command history of Script Editor.
  2. Execute a target instruction manually.
  3. Search the relevant command at the beginning of Script Editor.
  4. Query with whatIs, if the result is
    1. command -> look it up in documentation
    2. MEL procedure -> trace the source script
    3. runtime command -> query with runtimeCommand -c

Conclusion

Writing scripts to automate repetitive and time-consuming manual tasks can greatly improve our productivity at work. To build an efficient and robust pipeline, we have to reduce those kinds of manual tasks as much as possible. Now we know how to convert any manual instructions into scripts in Maya. Let’s start scripting and enjoy automation!

References

  1. Bryan Ewert. 2006. How do you find out all these things about MEL? I can’t find some things in the documentation!
  2. Kristine Middlemiss. 2009. Maya API: Where to start!?!??!?
  3. Maya programming resources.

comments powered by Disqus