After getting fed up with using someone else’s out of date versions, I decided to compile my own Qt, SIP, and PyQt for x64. I managed to get it all working and figured I could share it up, so here’s a link to the installers, as well as the latest version of sip.pyd which you will need.

Both are the latest PyQt4 4.7.3-1, however they are compiled against different versions of QT.
PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA.exe is compiled against Qt 4.5.3 (2009.04) which Maya 2011 uses, the other is compiled against the latest Qt 4.6.2 (2010.02.1).

Also, please note that I did not include any components that do not come standard with the Qt SDK such as QScintilla.

Edit: A few people were unable to get this working, not sure why but here’s an alternate version without the installer that seems to fix any issues with Qt failing to import

Here’s a quick little bit of code showing how to create a custom GUI class using pyqt (Almost all the pyqt examples use this over using some form of .ui file, because it allows for much more control). You can also use it in combination with ui files thanks to pyqt’s uic module.

QT does not require objects to have “names”, but if you ever want to find your pyqt objects using MQtUil.findControl then you need to assign it a name using OBJECT.setObjectName(“AwesomeWindow”). In the above example, in the MayaSubWindow.__init__ function you would call self.setObjectName(“AwesomeWindow”).

Also, since qt does not require names, it also does not require that control names be unique, so it’s completely possible to use findControl and get the “wrong” object. So you may want to ensure that the name you are using is unique if you want to use it to find that object again later. (Also, you can skip the whole findControl step by just using instance variables to keep track of all your controls, like what the pyqt examples use)

Here’s a pyqt example using uic to load in a ui file (Rather than maya’s new loadUi command, which wont give you all your pyqt objects.

Timers have all sorts of uses, and unfortunately up until 8.5 Maya had no good way of checking a timer, and running a background event.

Previously you could check system time at certain events with a scriptJob, like selectionChanged, but it tends to slow Maya down right when the user was trying to interact.. so in a production environment that wasn’t a viable solution (usually scriptJobs aren’t, as nifty as they are).

Now, with the flexibility of python in Maya, and python’s ability to create threads, it’s quite simple to create a basic Timer class.

Note: I updated it to use threading.Event().wait() instead of a time.sleep() loop, and now I directly subclass threading.Thread.

I was inspired by a post on tech-artists by Adam Pletcher over at Volition, he talked about using SQL to track usage stats for tools, and startup time for 3dsmax.

Getting the data:

I started with a simple database, just tracking the tool name, the username, and the date/time. But there is room to expand that information later (I want to track arguments, and time taken per tool).

There’s a problem right away: accessing a remote database on every function call (that I want to track) is SLOW, to work around this I dump the data to a local temp file (I used csv), and use a timer in a separate thread to upload every N seconds (on my machine I do every 10 seconds, for the artist’s I’m still tweaking, but somewhere around 2-5 minutes seems to work well). The actual database access usually takes .1 to .5 of a second, so it’s not terrible. I also have it set to run with utils.executeDeferred(), so it goes unnoticed for me, even on my 10 second interval.

Sooo… I have a bunch of cool data in a table, now what?

CHARTS! 🙂

It even has alpha! :)

I used pycha and pycairo to create charts from the database, had to track down some missing dll’s to get it working, but not too bad. So far the most useful chart is function usage by user (given a function, % that each person uses it), it helps me to spot tools that aren’t being used by certain users, which will allow me to train them on the new tool. This is good because if they never use it, they probably don’t know it exists.. 🙂

Where to go from here:

Break functions down by how long they take to execute, it should show me where most of our processor time is going as far as tools are concerned, so once I turn on function timing, that’s an immediate goal.