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.import sys
sys.path.append(r'C:/MyQtPath')
Now we should be able to open motionbuilder and do afrom PyQt4 import QtGui, QtCore, uic
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?.import sys
for each in sys.path:
print each
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.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
from PyQt4 import QtGui, QtCore, uic
import os
from pyfbsdk import *
import pythonidelib
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.
## This assumes the ui file has the same name as the python file
## Figure out the paths
mypath = os.path.dirname(__file__)
mybasename = os.path.basename(__file__)
myname = os.path.splitext(mybasename)[0]
## Build the path
uifile = "%s/%s.ui"%(mypath,myname)
## This stores the class of the ui type we built in designer (QMainWindow or QDockWidget etc)
form, base = uic.loadUiType(uifile)
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.
## We use this function to print, since Qt-Events dont trigger a flush by themselves
def mprint(string):
print(string)
pythonidelib.FlushOutput()
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.class MyTool(base, form):
toolname = "Test Widget"
version = 1.00
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
self.ui = uic.loadUi(uifile, self)
## Set the window title based on the toolname and version variable
self.ui.setWindowTitle("%s %s"%(self.toolname,str(self.version)))
## Connect the button to the buttonclicked function
self.ui.btnDoIt.clicked.connect(self.buttonclicked)
def buttonclicked(*args):
FBModelNull('My own null')
mprint('I just created a null for you!')
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.def main():
parent = QtGui.QApplication.activeWindow()
while parent.parentWidget() != None:
parent = parent.parentWidget()
for gui in parent.children():
if gui.__class__.__name__ == 'MyTool':
gui.close()
MyToolWindow=MyTool(parent)
MyToolWindow.show()
main()
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.


COMMENTS
LEAVE A COMMENT