Why PyMEL?¶
The Nature of the Beast¶
Rather than reinvent the wheel, Autodesk opted to provide “wrappers” around their pre-existing toolsets: the C++ API and MEL. By wrapping them they provided an alternate python interface for each, but the core code that comprises the API and MEL remained largely the same. The wrappers serve as a (hopefully) thin layer to communicate between python and the Maya code being wrapped. The nature of the wraps is slightly different for each.
- maya.OpenMaya
- In the case of the C++ API, Autodesk went with an open source wrapper called swig which generates python functions and classes from C++ counterparts. The python layer rests on top of C++, which remains the native execution language. During execution, swig marshals data back and forth between python and C++.
MEL itself is split into two components: commands, and everything else.
- maya.cmds
- In the case of MEL commands, which are (effectively) written using the C++ API, Autodesk wrote the wrapping mechanism themselves such that MEL commands could also be registered and used in python as functions. The same command executed in MEL and python ultimately end up triggering the same underlying C++ API calls.
- maya.mel.eval
- In order to allow execution of arbitrary MEL code such as procedures, Autodesk provided high level access to the MEL interpreter. This is as simple of a wrapper as you can get: evaluate a string representing a chunk of MEL code in the MEL interpreter and convert the result to a python object (string, float, int, and lists thereof).
So now that python is available in Maya all of our problems are solved, right? Well, not quite. Since these new modules are just wraps of the same underlying API and MEL code that we’ve had all along and neither were intended to eventually become “pythonified”, the syntax that results from this layering of python over MEL and C++ tends to be awkward, especially to those familiar with python’s idioms.
This syntactical awkwardness, particularly in maya.cmds, was one of the initial inspirations behind PyMEL. Think of it this way: would you rather read a book that was translated from japanese into english by a software program like babelfish or by a human who is fluent in both languages? That is a key difference between an automatic wrap like maya.cmds and a “restructured wrap” like PyMEL, which uses the maya python modules as building blocks to construct an intuitive, insightful, and pythonic API.
The Paradigm Shift¶
MEL is a procedural language, meaning it provides the ability to encapsulate code into reusable “procedures” ( aka “functions” ). (This is probably old news to you, but bear with me, there’s a mildly entertaining analogy coming up ). The term “procedural programming” is used primarily in the context of distinguishing a language from the newer, object-oriented paradigm.
Object-oriented programming adds organization by creating logical groupings of functions which are accessed from a common “object”. If you have used MEL extensively you know you can get pretty far with procedural programming alone, but there is often an exponential relationship between the complexity of a task and the amount of code it will take to complete in MEL. In other words, progress breaks down once the task at hand becomes too complicated. Object-oriented code tends to be easier to read and write, provides the ability to easily create new data types and reuse code, and ultimately scales better to complex tasks.
To prove my point, here’s a quick example that we’ll cover in more depth later.
procedural:
cmds.getAttr( cmds.listRelatives( cmds.ls(type='camera')[0], p=1 )[0] + '.translate' )[0][2]
object oriented:
pymel.ls(type='camera')[0].getParent().translate.get().z
See how nicely that reads from left to right? Object oriented programming isn’t necessarily about brevity, it’s about legibility derived from structure.
A quick perusal of the more than three thousand MEL commands in the Maya documentation will give you an idea why object-oriented groupings are a good idea. MEL is like a tool chest, a wardrobe, and a kitchen set all dumped into a bathtub – everything in there is useful in the proper context, but you’ve really got to know what you’re looking for to get anything done. The shame of it is that Maya’s great innovation is that it is itself inherently object-oriented – every scene represents networks of nodes, each with its own unique abilities and those that it inherits from its super-classes. Maya’s API is object-oriented, too. So how did MEL end up so crippled?
The original idea behind MEL and the API was to create a tiered relationship where complex tasks, or tasks where execution time is of great concern, were to be performed using the C++ API and bundled into easy-to-use MEL commands. These commands were in turn to become the building blocks of more generalized tasks performed in MEL. The API would be the toolset of the superuser – with access to complex types and external libraries – whereas the scope of MEL would be much more limited and thus more accessible to the average user.
The advent of python in Maya brought a common language to MEL and the API, and as a result, the clarity of this tiered structure has become muddied. API classes, MEL commands, and MEL procedures can be used within the same python script, completely outside the context of a plugin. Moreover, python manages to borrow the strengths of both languages: like C++, it is object-oriented and extensible through third party libraries and custom types, but like MEL, python is easy to learn, protects the user from certain daunting programming concepts, and compiles at runtime. Having managed to provide an object-oriented design without a steep learning curve, python makes the simplicity of MEL seem like an unfortunate over-simplification.
So, on the one hand we have the C++ API, now easily accessible from within Python, object-oriented, but too cryptic and verbose for everyday tasks, and on the other hand, we have a host of thousands of MEL-commands-turned-python-functions, too valuable to do without, but woefully unorganized and “unpythonic”. Which do we use? How can they work together? PyMEL bridges this gap by forging a new object-oriented API that’s as powerful and easy to use as python is.
Glossary¶
- MEL
- short for Maya Embedded Language, is a scripting language written for Maya, and with which much of Maya’s functionality and user interface is built. It was designed to be concise, simple, and Maya-specific.
- C++ API
- provides deeper access to Maya’s internals. With the API you can create new node types and new MEL commands. Prior to the introduction of python in Maya, the API could only be used with C++.