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.
MEL itself is split into two components: commands, and everything else.
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.
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.