PySide/PyQt and Maya Undo not good friends

Calling Maya commands from PySide/PyQt using MEL and/or their Python wrappers will display strange messages on the Maya console during undo/redo operation, and oftenly creates concerns if this a bug, or something gets wrong.

Not-good-enough
Not at all – that is a side effect of how the command is called by the different interpreters. Consider this Python PySide/PyQt UI script:

import sys
from PySide import QtCore, QtGui
from maya import cmds, mel
class FormExample(QtGui.QWidget):
def __init__(self):
super(FormExample, self).__init__()
btn = QtGui.QPushButton('My Button', self)
btn.resize(btn.sizeHint())
btn.move(50, 50)
btn.clicked.connect(self.onMyButtonClicked)
self.setWindowTitle('My Form Example')
self.show()
def onMyButtonClicked(self):
mel.eval("polySphere -ch on -o on -r 1.3;")
# prints // Undo: polySphere -ch on -o on -r 1.3 //
win = FormExample()

In the PySide/PyQt version, Qt is executing the onMyButtonClicked() method which then calls mel.eval() with a command string. So MEL is being asked to execute a command string, which is what gets printed out on Undo.

Now consider this Python/Maya UI script:

import sys
from maya import cmds, mel
class FormExample:
def __init__(self):
if cmds.window("FormExample", q=True, exists=True):
cmds.deleteUI("FormExample")
cmds.window("FormExample")
cmds.columnLayout()
cmds.button(label="My Button", command=self.onMyButtonClicked)
cmds.window("FormExample", visible=True, e=True)
def onMyButtonClicked(self, *args):
mel.eval("polySphere -ch on -o on -r 1.3;")
# prints // Undo: <bound method FormExample.onMyButtonClicked of <__main__.FormExample instance at 0x00000000310AAC08>> //
win = FormExample()

In this MEL version, the onMyButtonClicked() function is a callback which is being executed directly by MEL. So in this case MEL is being asked to execute the onMyButtonClicked() function, which has been given to it as a function object, not a string. Here understand undo records the call to ‘command=self.onMyButtonClicked’ vs. the MEL eval() command. Does not mean the command in eval is not record, but it is embedded in the first one.

Now replace:

mel.eval("polySphere -ch on -o on -r 1.3;")

by

cmds.polySphere (ch=True, o=True, r=1.3)
# now prints // Undo:  // in the PySide/PyQt example

While you now understand why the Maya UI will still print the lengthy ‘//
Undo: <bound method FormExample.onMyButtonClicked of <main.FormExample instance at 0x00000000310AAC08>> //’ message, you would see the PySide/PyQt sample printing nothing. I.e. “”. This is because in Python the “string representation” of that function object is “”.

Bad-friend-friendship


Comments

Leave a Reply