Featured Articles
Stitch
Rhythmic Walk
Major Project - Divine Application
Generi Rig for Blender
KWrite/Kate MEL Syntax Highlighting
Improving the Maya Linux File Browser
Latest News
Search

Ten MEL tricks I wish I'd known years ago PDF

So whilst animating at home the other day, I stumbled across a few rigging MEL scripts that I'd made a while ago, shortly before starting at Framestore. In a moment of madness, I thought I'd open them up and have a look, and see how they held up to a year's hindsight. And unfortunately, as is often the case with my old code, I didn't like what I saw. I mean, I REALLY didn't like what I saw. I had to go take a shower to wash the grime off afterwards - it was THAT bad...

After the convulsions had finished and I could bear to look at the code without bringing up my lunch, I sat back and reflected a bit on what I've learned since joining Framestore. How had I managed to produce this monstrosity of puke-encoated MEL code such a short time ago? What things do I know now that I didn't know before? What are the MEL tricks that I wish I'd known years ago? Before I knew what had happened, this list appeared on the screen in front of me. Then I blinked, and it was up on my website. And now you're reading it. I hope it'll help you avoid producing your own puke-encoated balls of MEL...

 

Tip #1: Prefix your globals

If your script declares global variables or global procedures, then you must give them a prefix. It can be anything; the name of your project, the name of your company, or even your initials - it really doesn't matter. But you MUST prefix them. Why? Because of the danger of naming clashes. I once had to fix a problem where two scripts from HighEnd3d both declared a global procedure called "loadXML()", and I tell you, it wasn't pretty. How would you fancy debugging a MEL script that runs fine the first time, but suddenly breaks in very weird and random ways after half an hour of usage, but then works fine after a fresh "source"?... See, I told you it was nasty. I prefix all my globals in personal scripts with my initials, and you should do something similar.

//No, bad!!
global proc loadXML()
//Good!
global proc KE_loadXML()
 

Tip #2: Don't use "source"

This is probably the single most important thing I've ever learned about MEL. 'source' makes it incredibly easy to make unstructured spaghetti code. It also makes your scripts very liable to break if you rename or move files around - for example, if your MEL script calls "source /work/scripts/myScript.mel" then your script will error if myScript.mel or its parent folders are renamed, or moved. It also forces you to constantly think in terms of "where is that script, and is it sourced or not?". You need to remember where your procedures are stored, whether Maya knows about them or not, whether there are multiple versions of the same file that have been sourced - it's just a mess.

It also makes testing changes in a company or a group environment really difficult to do. Imagine you wanted to make some experimental changes to /work/scripts/myScript.mel without breaking it for everybody who's currently using it. So, you make a local copy somewhere (eg /home/user/myScript.mel), start making local changes there, and run "source /home/user/myScript.mel". The problem is, Maya will forget about your new changes every time you run some other script that calls "source /work/scripts/myScript.mel". Making changes to one script suddenly might mean having to make local copies of every other script that sources yours (Two? Ten? Fifty?!?), just because of stupid source statements. There must be a better way, right?

Luckily, there is Imagine you've got a MEL procedure you want to reuse in other scripts, called KE_buildRig(). Here's a sneaky little-known trick - if you put it in a file with the same name as the function, ie in a file called "KE_buildRig.mel", you don't HAVE to source it to use it. You can just call KE_buildRig() from anywhere, and Maya will look it up and say 'hey, there's a MEL file here with the exact same name as this function, I'll bet it's stored in here.' The really neat part is that if the file hasn't been sourced yet, Maya will source it for you automatically, without you having to worry about any sourcing silliness. Pretty cool, eh?

So what if you've got lots of functions you want to reuse in one file? Well, you'd stick them all in a file, and put an empty 'stub' at the bottom:


//KE_usefulLib.mel
global proc KE_usefulLibFunction1()
{
...
}
 
global proc KE_usefulLibFunction2()
{
...
}
 
//Library stub function
global proc KE_usefulLib()
{
}
 

Now, any script that wants to use KE_usefulLibFunction1() or KE_usefulLibFunction2() only has to call KE_usefulLib() once (at the top of the script for example), and Maya will automatically source the script and make all the functions available as necessary. It becomes almost like using #includes in C/C++, or import in Python - at the head of each script you write, you call all the stubs your script will need, and you can just happily assume they're sourced and ready, without worrying about where they're saved or how

It also forces you to be much more organised about your code - you might make a MEL file just for dealing with strings (KE_stringLib.mel) or for command ports (KE_commandPort.mel) or for arrays (KE_arrayLib.mel), which you can then easily reuse all over the place. As you write more and more MEL, it becomes increasingly handy to have a library of stuff you've written before, so you don't have to continually reinvent the wheel, and this way of working helps you to do precisely that.

The best part though, is when working in companies where you want to be able to make local changes to MEL scripts for testing without breaking stuff for everyone. If set your MAYA_SCRIPT_PATH environment variable to include a folder in your home area before you start Maya, any scripts you place in that folder will be used in preference to the company wide ones you might have. So now, making changes to your local copy of myScript.mel is as simple as copying it to your local folder, changing it, and sourcing it from within Maya - after this, all of your company's scripts will then automatically start using your local copy instead of the company wide one, allowing you to test your changes easily and locally before publishing them for everyone else to use. You can even source the old one afterwards, or start trying both of them to compare the effect of your changes. It really is a joy to work with MEL that's been structured this way.

Trust me - after a week of going without source, you'll be wondering why you ever used it in the first place!

 

Tip #3: Don't use "evalDeferred".

"evalDeferred" gives you a way of telling Maya "okay, I want to run this code, but if I run it right now then bad stuff will happen, so please run it later instead". Which sounds all fine and groovy, but really it isn't. I mean, if your code is going to break now, then can anything guarantee that it won't still break stuff when Maya runs it in a couple of moment's time anyway? If you're stuck in an awkward situation and evalDeferred() is sat there looking sweetly at you, then smile and nod, but politely decline. It's almost always better to fix your code so that it works properly whenever it's run, than to have to fix odd and difficult-to-reproduce problems from evalDeferred() later on.

 

Tip #4: Use long flags instead of short ones

Code is "write-once-read-many"; that is, a given line of code is normally only written by you once, but will probably be read several times by you or by other people either wanting to reuse or bugfix your code. Imagine: if you were debugging someone else's broken script at 3am, which of these would you prefer to read?

//This:
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;
 
//Or this:
polyCube -width 1 -height 1 -depth 1 -subdivisionsX 1 -subdivisionsY 1
         -subdivisionsZ 1 -axis 0 1 0 -createUVs 4
         -constructionHistory true;
 

Sure, writing the first one might save the writer an additional 15 seconds, but it'll cost the poor reader 2 or 3 minutes as they start up Firefox, open Maya Help, look up the command you're using, and try to work out what the heck it is you're trying to do, and whether it's the reason half their scripts are suddenly breaking and they've been dragged out of bed by a very irate phone call. It might look cool to write all those short, weird-looking flags, but I don't care for cool. I want two things out of my scripts: (1) they shouldn't break, and (2) when they do break, they should be easy to fix. Trust me, other scripters will love you and hug you and bring you free cookies if you take the time make your code that little bit more readable

 

Tip #5: Comments

Following on from the previous point, commenting your work is a must. It might seem tedious and dull sometimes ('I wrote it, of course I know what it does!'), but it's a really good time investment and actually speeds you up in the long run. It's such a time-saver to be able to return to code you wrote years ago, and understand everything about it within 30 seconds of starting to read it. If you don't comment, then you'll slowly start to forget the intention behind your code - WHY this particular error check was necessary, or WHY command 'X' didn't work and you're having to use command 'Y' instead to work around it. Sure, without comments you can re-read it and observe what the code does, but the important part - your intentions, what you wanted the code to do rather than what it actually does - those are gone.

At the very least, you should put a comment at the top of the file saying what it does, and above all your functions explaining what they do, what their parameters are, and what they return, and perhaps what they return if they encounter an error:

//KE_curveLib.mel by Karl Erlandsen
//Handy functions for generating and manipulating curveShape nodes
 
//This procedure takes a curve shape ($curve) and generates a new cluster for
// every CV on the curve. It then returns an array of all newly created 
//cluster transforms. If an error occured, it doesn't error but simply returns
//an empty list.
global proc string[] KE_clusterCurve(string $curve)
{
...
}
 


 
Comments

You must javascript enabled to use this form

Hi

Thanks for posting this, I'm really just beginning to scrape the surface of Mel and I found your post extremely helpful.

Thanks again and keep up the good work

Mike

Posted by michael cummings, on 06/11/2010 at 19:37

 1 
Page 1 of 1 ( 1 Comments )

< Prev   Next >

Designed by: Drupal hosting Mambo templates Best web hosting
http://www.kreanimate.co.uk/site, Powered by Joomla and designed by SiteGround web hosting