Scripts

lockAndHide tool – quick Qt UI in Maya

By December 4, 2014 December 13th, 2014 No Comments

Yesterday I was coding some tools for my students in Python, when I decided it was time to remember what I learnt about Qt some years ago. It was pretty basic stuff, and it was in Softimage, but I thought it wouldn’t be that different in Maya. And it is not that different…

… but I did not want to deal with complicated PyQt code. I just wanted to design my UI in the Qt Designer, connect some signals, read that .ui file in Maya 2014 and make the buttons and checkboxes to run some functions. This is the tool I built: a small interface to be able to lock position, rotation and scale channels.

01_lockHideUI

I searched and read and searched and read, and I found very interesting documentations about it. However, most of them relayed on deeper knowledge about the subject. Do you ever feel like ‘I want to do this and I want to finish it now’, and not waiting for the next day to continue it? In the end, I think I have spent more time trying to find a simpler way rather than learning the hard one. Which is the reason why I’m writing this: so you have more information when you decide to research about the subject.

I am not an expert in Qt, but the first thing you should know is that it is a bit more comfortable to deal with than the ‘traditional’ way to build interfaces in MEL, where you stack UI elements with no interactivity in the design at all. There are plenty of videos about how to build interfaces in Qt (like this). And if you are using Maya 2014 or newer, you do not need to install anything else, and you can jump into this right away. Quoting Autodesk:

However,be aware that with Maya 2014, there is no more need to build PySide as it is coming by default in Maya, nor you have to rebuild Qt itself as the main Qt tools to build PyAt are now included in the Maya distributions (I.e. qmake, moc, …).Libxml, openSSL, OpenAL, python2.7, qt-4.8.2-64, and tbb are also coming by default in the Maya include and lib folder, so unless you have a very specific need, you would not need to rebuild any of those libraries like before.

Which basically means… let’s start!

Building the UI and importing it in Maya

Maya comes with a Qt Designer already, which is located under your Maya instalation folder/bin/designer.exe, should you be using Windows. Watch some Qt tutorials, and go create a widget, drag and drop some buttons, checkboxes and other elements, play with the different layouts and save the .ui file.

If you want to use the .ui file I did for this tool, get it here.

Making it Maya friendly

Once the visuals of the UI are satisfying, and before moving to Maya, you need to define signals and slots, which are the way the UI elements have to communicate between themselves and to outside of the interface. Think of signals as actions that an element of the interface executes: a button can be pressed, a checkbox can be checked, etc. And this is one of the important parts: you can do it that way, but there is a simpler one, which will work for most common UI elements.

Let’s say, for example, a button. When you build an interface in Maya, and draw a button, you tie some piece of code to it using the ‘command‘ flag. That way, when you hit the button, some function is called. Since Maya can ‘translate’ some UI elements from Qt Designer, you could add a ‘command‘ property there, and write the code you want it to execute. For example, a function you wrote in Maya. In Qt Designer, that attribute is added under the ‘Property Editor‘ rollout. See that big green plus sign? Click it, add a string, and call the property name +command if you plan to use Python, or -command if you are using MEL.

So instead of using signals you can use Dynamic Properties on that button to add the ‘command’ flag you would use on a regular Maya-made button.

02_dynamicProperties

In this tool, I have checkboxes as well. The flag I’m adding to them is ‘changeCommand’, as this is the way Maya knows it has to execute a command when the value of the checkbox changes.

Build the tool

Here’s the final .py code for this tool. Not very elegant, but it gets the job done!

import maya.cmds as cmds

### .UI FILE LOAD ###
pathToFile = "D:/Projects_Working/scripts/lockHide/lockHide.ui"
qtWin = cmds.loadUI (uiFile = pathToFile)
cmds.showWindow (qtWin)

### FUNCTIONS ###
def lockAttribute (obj, attr):
    cmds.setAttr (obj + "." + attr, lock = True, channelBox = False, keyable = False)

def unlockAttribute (obj, attr):
    cmds.setAttr (obj + "." + attr, lock = False, keyable = True)

def getLockState (obj, attr):
    cmds.getAttr (obj + "." + attr)

def lockTemplate (attributeShort, attributeLong):
    sel = cmds.ls (sl = True)[0]
    value =  cmds.checkBox ("lockAndHide|gridLayout|" + attributeShort +"_checkBox", q = True, value = True)
    if value == 1:
        lockAttribute (sel, attributeLong)
    elif value == 0:
        unlockAttribute (sel, attributeLong)

### UI CHECKBOX ACTIONS ###
def _lockPosX():
    lockTemplate ("posX", "translateX")

def _lockPosY():
    lockTemplate ("posY", "translateY")

def _lockPosZ():
    lockTemplate ("posZ", "translateZ")

def _lockRotX():
    lockTemplate ("rotX", "rotateX")

def _lockRotY():
    lockTemplate ("rotY", "rotateY")

def _lockRotZ():
    lockTemplate ("rotZ", "rotateZ")

def _lockScaleX():
    lockTemplate ("scaleX", "scaleX")

def _lockScaleY():
    lockTemplate ("scaleY", "scaleY")

def _lockScaleZ():
    lockTemplate ("scaleZ", "scaleZ")

### UI BUTTON ACTIONS ###

def _lockAllPos():
    sel = cmds.ls (sl = True)[0]
    value =  cmds.checkBox ("lockAndHide|gridLayout|posX_checkBox", q = True, value = True) # accessible name property in main widget QTDesigner!
    if value == 0:
        lockAttribute (sel, "translateX")
        lockAttribute (sel, "translateY")
        lockAttribute (sel, "translateZ")

        cmds.checkBox ("lockAndHide|gridLayout|posX_checkBox", e = True, value = True)
        cmds.checkBox ("lockAndHide|gridLayout|posY_checkBox", e = True, value = True)
        cmds.checkBox ("lockAndHide|gridLayout|posZ_checkBox", e = True, value = True)

    elif value == 1:
        unlockAttribute (sel, "translateX")
        unlockAttribute (sel, "translateY")
        unlockAttribute (sel, "translateZ")

        cmds.checkBox ("lockAndHide|gridLayout|posX_checkBox", e = True, value = False)
        cmds.checkBox ("lockAndHide|gridLayout|posY_checkBox", e = True, value = False)
        cmds.checkBox ("lockAndHide|gridLayout|posZ_checkBox", e = True, value = False)

def _lockAllRot():
    sel = cmds.ls (sl = True)[0]
    value =  cmds.checkBox ("lockAndHide|gridLayout|rotX_checkBox", q = True, value = True) # accessible name property in main widget QTDesigner!
    if value == 0:
        lockAttribute (sel, "rotateX")
        lockAttribute (sel, "rotateY")
        lockAttribute (sel, "rotateZ")

        cmds.checkBox ("lockAndHide|gridLayout|rotX_checkBox", e = True, value = True)
        cmds.checkBox ("lockAndHide|gridLayout|rotY_checkBox", e = True, value = True)
        cmds.checkBox ("lockAndHide|gridLayout|rotZ_checkBox", e = True, value = True)

    elif value == 1:
        unlockAttribute (sel, "rotateX")
        unlockAttribute (sel, "rotateY")
        unlockAttribute (sel, "rotateZ")

        cmds.checkBox ("lockAndHide|gridLayout|rotX_checkBox", e = True, value = False)
        cmds.checkBox ("lockAndHide|gridLayout|rotY_checkBox", e = True, value = False)
        cmds.checkBox ("lockAndHide|gridLayout|rotZ_checkBox", e = True, value = False)

def _lockAllScale():
    sel = cmds.ls (sl = True)[0]
    value =  cmds.checkBox ("lockAndHide|gridLayout|scaleX_checkBox", q = True, value = True) # accessible name property in main widget QTDesigner!
    if value == 0:
        lockAttribute (sel, "scaleX")
        lockAttribute (sel, "scaleY")
        lockAttribute (sel, "scaleZ")

        cmds.checkBox ("lockAndHide|gridLayout|scaleX_checkBox", e = True, value = True)
        cmds.checkBox ("lockAndHide|gridLayout|scaleY_checkBox", e = True, value = True)
        cmds.checkBox ("lockAndHide|gridLayout|scaleZ_checkBox", e = True, value = True)

    elif value == 1:
        unlockAttribute (sel, "scaleX")
        unlockAttribute (sel, "scaleY")
        unlockAttribute (sel, "scaleZ")

        cmds.checkBox ("lockAndHide|gridLayout|scaleX_checkBox", e = True, value = False)
        cmds.checkBox ("lockAndHide|gridLayout|scaleY_checkBox", e = True, value = False)
        cmds.checkBox ("lockAndHide|gridLayout|scaleZ_checkBox", e = True, value = False)

 

There are a couple of things to comment:

  • Lines 4, 5 and 6 are the ones which load the .ui file that we previously saved. You will need to change the path so it points to the folder where you store the .ui file. If you want to try this tool, grab the .ui file from here.
  • The block labeled as ###FUNCTIONS### consists of several general functions to lock and unlock attributes.
  • After that, we have ### UI CHECKBOX ACTIONS ###. Each one of these functions is what it’s called when we change the value of each checkBox. That is, when the +changeCommand Dinamic Property we wrote in Qt Designer is called.
  • As you can see, the way I am accessing to a checkbox from Maya is by writing “lockAndHide|gridLayout|scaleZ_checkBox“. Note that this is not exactly matching what we have in Qt Designer, but since I am indeed using a gridLayout with my tool (right button on the main widget to choose a layout) it seems this is the correct way to access our UI elements.
03_hierarchy

Dude, where is my gridLayout?

Useful links

You will find more information here:
http://nathanhorne.com/?p=451
http://www.joehultgren.com/blog/mixing-maya-ui-elements-into-a-qt-designer-interface
http://lo-motion.de/wordpress/?p=260
http://www.creativecrash.com/tutorials/using-qt-designer-for-mel-interfaces#tabs
http://www.codeproject.com/Articles/361231/Intro-to-QT-in-Maya

—– UPDATE —–

Rob Galanakis has gently taken some time to talk about how to improve the code above. Also, why Qt Designer should be bypassed at all costs. You better read his article! Quoting him, “a little more investment in learning can pay dividends for your career

http://www.robg3d.com/2014/12/qt-designer-is-harmful-exhibit-a/

Thanks, Rob!

Leave a Reply