Archive for November, 2009

UI in maya using python

Sunday, November 29th, 2009

UI is super important.  At least if you’re developing tools for anyone other than yourself.  And even then, its still a good idea to try and make your tools accessible because sometimes you don’t come back to a tool for months, or occasionally years.  And for the record, I’m not even nearly as good as I would like to be (or even should be) at building usable UIs.

Unfortunately maya is fighting you all the way in this regard.  Maya is, and lets not be too harsh here, is a piece of steaming turd when it comes to UI – it was great 10 years ago, but it hasn’t changed since…  The UI that you can build in mel/python is painfully limiting to use for anything but a bunch of buttons and checkboxes.  But unfortunately you have to either live with that, or go through the pain of learning and integrating qtpython/wxpython into your tools – but thats a different (and entirely valid) discussion.

Writing UI using mel is horrible – and pretty well understood because mel is so simplistic and straight forward.  Its horrible because its essentially impossible to write UI without hardcoding widget names which makes it impossible to modularize your UI into re-usable chunks, its difficult to store local data on a piece of UI.

But writing maya UI using python is a different story.  Python provides you with the ability to abstract the UI code so you can make it more modular, provide widgets and collections of widgets with their own local storage and methods etc.  By writing thin wrappers around the existing maya widgets you can “class-ify” them and make them work more like code should in an object oriented language.

Now, I’m pretty new to all this as well, so I’m certainly not claiming anything I say here is the best way to do things.  But these ideas have made my life easier and more productive, and more importantly its increased the functionality in the tools I’ve created.

Anyway the wrapper code I work from is here.

As you can see its not terribly complicated – in fact its painfully simple.  As you can see the UI classes inherit from the python built-in type “str” – they’re strings.  This is because everything in maya is a string, so by inheriting from str, we can pass the actual UI python objects to the maya commands which makes mixing and matching this sort of UI code with older UI code a snap.  But because we’re now working with actual objects, we now have local storage for the widget (whether it be a simple button, or a more complicated layout of widgets) plus we can write methods for these widgets.  So by doing things this way for example, you can write a “setVisibilty” method on the base class if you wanted to, and now every object has the same interface to hiding and unhiding itself.  So we now have local storage and polymorphism.

By using this sort of paradigm you can also extend classes for more complex UI.  As you can see here, this makes writing modular UI alot easier as well.  This is a great example of some UI that is just not possible to write in mel in a way that makes it this modular.  At least not where you can have multiple instances of the UI open at once.

So the mappingEditor example above – it is a generic widget that inherits from the formLayout class (so it knows how to lay itself out) but it adds a heap of other functionality related to mapping two lists to one another.  I’ve used this widget in a few tools now (only one of them public) – often many instances of them are on screen at once.  This just isn’t possible using mel.

blender 2.5 almost here!

Tuesday, November 24th, 2009

Its true!  the blender 2.5 alpha came out yesterday (you can get it here).  I have barely played with it, but I’m excited to see the progress, and should be able to make some time for it sometime soon.

Anyway if you have a chance, check it out.  There are some super neat things the blender guys are doing, at least for an animation tool.  Not sure how modelling in it stacks up.  If nothing else their script integration sounds fantastically delicious.  Oh and did I mention that its open?

users and developers

Saturday, November 21st, 2009

I’m not the world’s best animator, but I do enjoy animating.  Some people even go as far as telling me I’m not too bad, but I’m quite sure they’re just being polite.  Anyway, the point is that being an animator in addition to being a technical dude means that I’m usually a customer of my own tools, at least in some way.

Now to me this is super important.  Implementing anything well means understanding the mind of whoever it is who is consuming whatever it is you’re making.  The best products in the world comes from people who understand their target audience.  They don’t have to BE the target audience per-se, but the easiest way to understand that audience is to be it.  I think this probably applies to any product, be it an iphone, a prius, an animation library or a character rig…

Anyway, I’m constantly surprised at how many “things” get created by people who don’t really understand the audience they’re creating for…

Exception Handling in Maya

Tuesday, November 17th, 2009

As a tool writer python is awesome because it gives you proper control over your code.  You can create classes, inheritance, you no longer have to rely on nasty hacks for data storage in UIs etc…  Plus you get to cross into the API and mix and match functionality to some extent should you find that useful.

But there is one neat thing that non embedded python lets you do that is super useful – global exception handling.  In normal python you can roll your own exception handler so that when a piece of code throws an unhandled exception, the global exception handler catches it and tries to do something useful with it.  For me I usually try to display some generic failure message to the user, but then I usually get all the data I can from the exception and put it in an email and send that email to my address to help with the inevitable debugging that follows.

This is super useful to be able to do, and I do it all the time with my standalone python tools.  But in maya, not being able to write a global exception handler is a pain, because it means maya tool errors go unhandled (and sometimes even unreported) which means I’m left to try and repro failures from users myself.  At least, until I figured out this neat little trick.

So its kinda scary sounding, but hey, if I can understand it, anyone can.  It involves metaclasses.  What is a metaclass you ask?  Well, they’re basically the objects that create classes.  So just like a class is an object that creates instances of itself, metaclasses are classes that create instances of themselves.  Its crazy mind blowing (for a simple script monkey like me anyway) but it makes sense once you use them a few times.

Anyway, so basically what I did was create a metaclass that would wrap all methods of a class in an exception handling decorator.  In my case the exception handler grabs a heap of extra data from the exception like the callstack and variables sent to the functions in the callstack, and a few other things and sends an email to my work address (take a look if you’re interested, its the d_handleExceptions decorator in the exceptionsHandler script in the zooToolbox).  So now, whenever a tool throws an unhandled exception, I get a detailed mail about the problem which makes debugging a lot easier.  No longer do errors go unreported.

I haven’t released the code for the metaclass thingy, but I will.  But its fairly simple – do some searching for decorators and metaclasses in python.