PyQt et Maya, avec filetage = Faux?
Question
J'ai enquêté sur ce problème pendant 3 jours maintenant, sans aucune chance. Je suis tout à fait nouveau à tout cela alors peut-être il y a quelque chose que je suis absent.
Le problème s'applique à: Maya.cmds, PyMel et évalué à l'aide MEL QThread ou juste Enfiler
Ce code est conçu pour fonctionner sur l'interpréteur python « de mayapy » qui suit Maya. J'ai créé un court exemple qui recrée la même erreur dans plusieurs instances.
Un bouton fonctionne, l'autre ne fonctionne pas. Mais ils courent le même code.
from PyQt4 import Qt
class doStuff( Qt.QThread ):
taskProgress = Qt.pyqtSignal(int)
# --------------------------------------------------------- #
# Here things start to crash...
def run( self ):
# This works
persp = mel.general.PyNode('persp')
print persp.translateX.get()
# This dont work
poiLights = mel.general.ls( exactType="pointLight" )
for light in poiLights:
print light
# This dont work
geo = mel.general.PyNode('pPyramidShape1')
print mel.modeling.polyEvaluate( geo, face=True )
# Emit progress
self.taskProgress.emit( 1 )
return
# END
# --------------------------------------------------------- #
class ui( Qt.QWidget ):
def __init__(self, parent=None):
super(ui, self).__init__(parent)
# Init QThread
self.thread = doStuff()
# Create Widgets
buttonNo = Qt.QPushButton("Start - Dont work")
buttonYes = Qt.QPushButton("Start - Works")
# Setup Layout
layout = Qt.QVBoxLayout()
layout.addWidget( buttonYes )
layout.addWidget( buttonNo )
self.setLayout( layout )
self.show()
# --------------------------------
# PROBLEM AREA: Button signals
# This one dont work, but starts the thread correctly.
self.connect( buttonNo, Qt.SIGNAL("clicked()"), self.thread.start )
# This one works, but dont start the thread correctly.
self.connect( buttonYes, Qt.SIGNAL("clicked()"), self.thread.run )
# --------------------------------
self.thread.taskProgress.connect( self.updateProgress )
return
# Feedback progress status
def updateProgress( self, value ):
print 'Current progress is:', value
return
if __name__ == '__main__':
import sys
app = Qt.QApplication(sys.path)
program = ui()
# init maya
import pymel.core as mel
filePath = '/Users/ecker/Dropbox/Scripts/RibExporter/mayaScene3ani.ma'
mel.openFile( filePath, f=True, o=True )
sys.exit(app.exec_())
Ce code crée 2 boutons qui commencera à exécuter la même fonction lorsqu'il est pressé. Un thread.start
et exécute thread.run
.
thread.start
fera le travail de fil comme il se doit, être en mesure de réinjecter des données à l'interface Qt (pour une barre de progression), mais la plupart du code Maya commencera à retourner toutes sortes d'erreurs comme ceci:
Traceback (most recent call last):
File "/Users/ecker/Dropbox/Scripts/RibExporter/error_recreation2.py", line 22, in run
poiLights = mel.general.ls( exactType="pointLight" )
File "/Applications/Autodesk/maya2012/Maya.app/Contents/Frameworks/Python.framework/Versions/Current/lib/python2.6/site-packages/pymel/core/general.py", line 969, in ls
res = _util.listForNone(cmds.ls(*args, **kwargs))
File "/Applications/Autodesk/maya2012/Maya.app/Contents/Frameworks/Python.framework/Versions/Current/lib/python2.6/site-packages/pymel/internal/pmcmds.py", line 134, in wrappedCmd
res = new_cmd(*new_args, **new_kwargs)
TypeError: Flag 'long' must be passed a boolean argument
Il est un argument booléen, et peu importe quels arguments je tente de donner dans quel format et les moyens, il sera toujours donner des erreurs très similaires à ce sujet. A la même ligne res = new_cmd(*new_args, **new_kwargs)
ayant besoin d'un booléen.
J'ai besoin du thread
à start
, pas seulement courir. À moins d'une autre façon de faire le filetage, une solution de contournement?
La solution
Maya ne fonctionne pas bien avec des fils. La clé ici est d'utiliser maya.utils.executeInMainThreadWithResult.
J'espère que cette aide.