Character Picker for Maya with Python

After having seen some pickers I decided to write my own picker and wanted to see what I can accomplish with it. I designed the GUI with QtDesigner. It’s extremely handy and it’s not difficult to get it work on Maya. These are the body and facial tabs.

It’s pretty simple, just colored buttons

After the design is finished, you can use the UI converter and XML modules to load the .ui file in Maya. The code below is all you need to pop your UI.

Don’t forget to rename the XXXs in lines 27, 34, 36, 40, 45 according to your project. String in line 36 should be the name of your top object in QtDesigner. Save it to a seperate .py file and make sure both .ui and .py file are in the same folder.

This won’t work with Maya 2022 because pysideuic(UI converter) is removed. Also the code won’t work with Maya 2016 and below because it’s using PySide2.

from PySide2 import QtCore, QtWidgets, QtGui
from maya import cmds
import sys
import os
import logging
import xml.etree.ElementTree as xml
from cStringIO import StringIO
import pyside2uic as pysideuic
import maya.OpenMayaUI as omui
from shiboken2 import wrapInstance

def load_ui_type(uiFile):
	parsed = xml.parse(uiFile)
	widget_class = parsed.find('widget').get('class')
	form_class = parsed.find('class').text
	with open(uiFile, 'r') as f:
		o = StringIO()
		frame = {}
		pysideuic.compileUi(f, o, indent=0)
		pyc = compile(o.getvalue(), '<string>', 'exec')

		exec pyc in frame
		form_class = frame['Ui_%s' % form_class]
		base_class = getattr(QtWidgets, widget_class)
	return form_class, base_class

uiFile = '{}/xxx.ui'.format(os.path.dirname(__file__))
form_class, base_class = load_ui_type(uiFile)

def maya_main_window():
	main_window_ptr = omui.MQtUtil.mainWindow()
	return wrapInstance(long(main_window_ptr), QtWidgets.QWidget)

class XXXClass(form_class, base_class):
	def __init__(self, parent=maya_main_window()):
		self.window_name = 'xxx_window'
		if cmds.window(self.window_name, exists=True):
			cmds.deleteUI(self.window_name)

		super(XXXClass, self).__init__(parent)
		self.setupUi( self )

def runUI():
	global win
	win = XXXClass()
	win.show()

runUI()

I added a dropdown menu at the top, which shows a list you can choose reference from. The list is updated every time when the main window is clicked.

I used pymel.core.listReferences because I couldn’t find a function in cmds module where it only gives you the references in the scene.

To select the controls in the scene, first there is a keyboard check to decide if selected item is gonna add to or remove from the current selection. I can identify which button is pressed in the UI with sender(). After getting the name of the PySide2 object, I change the “_BTN” suffix to “_CTRL” and select it in the viewport using cmds.select. Undo also works which is cool.

def select_item(self):
	self.check_keyboard()
	self.get_namespace()
	sender = self.sender()
	senderObj = sender.objectName()
	renamed = senderObj.replace('BTN', 'CTRL')
	cmds.select(refName + renamed, add=shift, deselect=ctrl)
Naming convention saves lives

And there are few methods for IK/FK matching and connecting the buttons. That’s all!

From the blog

About the author

Sophia Bennett is an art historian and freelance writer with a passion for exploring the intersections between nature, symbolism, and artistic expression. With a background in Renaissance and modern art, Sophia enjoys uncovering the hidden meanings behind iconic works and sharing her insights with art lovers of all levels. When she’s not visiting museums or researching the latest trends in contemporary art, you can find her hiking in the countryside, always chasing the next rainbow.