Friday, September 27, 2013

Motionbuilder and Qt

Motionbuilder 2013 got a revamp of the entire UI and was rebuilt using Qt. This is awesome because that empowers you to use PyQt to build your own UI alongside with the powerful Qt Designer. 

Any scripter/programmer is aware that making a good, error-proof UI will sometimes take you more time than the actual application itself. With Qt Designer this is turned around and besides it is a great mockup tool.

Within a few minutes you can drag/drop a tool and once you or your client is happy with the UI, you just fill it with functionality.

I mean, really, Qt makes you a better tech artist, if you are not convinced then you might as well go back to shell scripting.

So now that we're convinced, lets go ahead!

Download PyQt
Motionbuilder 2013 is using Qt 4.7.x so you will need the appropriate python modules for that.
Head over to Nathan Horne's Blog and download them (PyQt 4.7.3 Qt x64). Big thanks to Nathan to compiling those!

Install PyQt

Next up you have to copy all the downloaded files in a sys.path. You could for instance just add them to an existing python path like C:\YOURPYTHONPATH\Lib\site-packages. Or put it in any folder and add this folder to your pythonpaths. For motionbuilder you could simply add a python file to C:\YOURMOBUPATH\bin\config\PythonStartup folder. This file will have to look something like this.

Now we should be able to open motionbuilder and do a
If you don't get any error messages, then you have successfully installed PyQt, otherwise go check if your Qt path is added to the sys.path list. You can check it like this, is your folder in here?.

Create a .ui file

Now lets open up the PyQt folder and find the designer.exe in there. Using the designer is a really powerful way to quickly drag and drop your interfaces together. For motionbuilder we will create a QDockWidget, since that allows us to dock our Qt tools into motionbuilders standard interface.

On the left side we can see all the ui elements we can use, for this example lets just simply drag a push button into our DockWidget.
Now go to File->Save and store it in a sys.path (store it in the same path as the py file we will create it in the next step.

Create the .py file

Now go to your favorite text editor (Did I mention how awesome SublimeText is?)
We will have to do a bunch of stuff now, to load the UI file we just created. 

First lets import all needed modules

If you wonder what pythonidelib is for, we will get to that in a minute. So this next block here is simply a nice way I found to load the ui file. It will just take the name of the py file and assume the ui file is named the same way. Of course you can just simply skip these steps and and just use the last line to load it from a custom path. So here we get to the reason why we imported pythonidelib.

Sometimes we want to print something thats triggered by a Qt-event, but unfortunately that doesn't work. But if you run pythonidelib.FlushOutput() after a print, it will work, so lets just make our own print function. Unfortunately I didn't suceed to overload the print in mobu since it's still using Python 2.x where print is a statement, compared to Python 3.x where it is a function. Anyway, here is our custom print function.
Now comes the important part, we are creating a class and inherit it from base and form. If you look at the beginning, those variables come from the loadUiType function, which basically just tells us if we used a QDockWidget or a QMainWindow etc. There is a bunch of stuff happening and I won't explain them all in detail, there are lots of other blogs already doing that.

Awesome so this is the class for our tool, next up lets write our main function. In this function we mainly do a check if the window already exists and we also find the motionbuilder window and use it as a parent for our tool. Just make sure that in the section where it says if gui.__class__.__name__ == 'MyTool': you replace MyTool with the classname of your tool.

Run your tool

Now lets save this py file in a sys.path and make sure the name is the same as the ui file. In motionbuilder a simple import PYFILENAME should open your tool and you are all set to rapidly create UIs. If you press the button it should now create a null and print something.

Last but not least let me refer you to the official PyQt documentation or the PyQt class list, its a really good help to see how to use each different UI element. 

Here you can download the py file

1 comment:

  1. Great Guide! Making UI's with PyQt Rocks :-)

    I can recommend converting the .ui to a module offline, instead of loading it dynamically. This should give you code completion of you GUI objects and also much much better introspection/completion of PyQt as well (great for when you are a QT noob like me).

    I haven't used Sublime, though people seem to say it never really becomes a fully fledged Python IDE, despite configuration/ad on's and what not. I'd seriously like to plug PyCharm, if for nothing else it's excelent remote debuging. I've been using Wing for some years and PyCharm beats it to a pulp..