Autodesk s'efforce d'améliorer son API Python au fil des versions (C'est d'ailleurs très dommageable, en prod, de devoir attendre une nouvelle version pour corriger des bugs d'API...).

La plupart des utilisateurs de l'API Python n'étant pas des développeurs (qui eux bossent, en général, en C++) mais plutôt des graphistes avancés, TD, ils leur arrive souvent de "douter".

L'idée, dans ce billet, est de parler des limitation de l'API Python de Maya que j'ai pu rencontré et qui m'ont vraiment bloqué. Le but étant que vous ne restiez pas vous même bloqué sur des trucs bêtes, comme j'ai pu l'être.

Ce billet ne se veut pas exhaustif et est bien entendu destiné au personnes qui connaissent un temps soit peu l'API. N'hésitez pas à laisser un commentaire si vous rencontrez d'autres bugs ainsi que leur workaround. :siffle:

On commence!

:youplaBoum:
:longBar:
Sommaire
:longBar:
Les MFloat(Matrix, Array, Point, etc...) (v2010)

Pour éviter de retaper à chaque fois: MFloat(Matrix, Array, Point, etc...) et M(Matrix, Array, Point, etc..) dans mes exemples, je prendrais la formulation MType et MFloatType.

Un des premier point sur lequel j'ai "buté" est la conversion de l'objet Maya: MFloatMatrix et tout les objets de type MFloat(Matrix, Array, Point, etc..) en leur équivalent M(Matrix, Array, Point, etc..)

En effet, certaines méthodes et constructeurs de classes ne demande, en entré, un MType. Si on n'a pas été assez vigilant, on se retrouve avec des MFloatMatrix dans notre code python et bien entendu, si vous passez un MFloatMatrix à la place d'un MMatrix, ça vous envoi balader...

Ce "double typage" des objets Maya est fait afin de donner facilement un équivalent aux de type de nombre flottant en C:

  • Double (8 octets, le "format" par défaut de Maya)
  • Float (4 octets)

Autant la conversion de MType à MFloatType est assez simple en C++ (voir ce billet) autant en Python c'est beaucoup plus laborieux.

La solution la plus simple que je vous conseil est donc de bannir les MFloatType autant que possible en Python. Je n'ai pas vraiment trouvé de solution pour convertir les deux type en Python (mais c'est surement possible :baffed: ).

EDIT 2010 10 08: Sur ce billet Peter J. Richardson propose une solution (qui est en fait très simple :pasClasse: ):

myMPoint = OpenMaya.MPoint()
myMFloatPoint = OpenMaya.MFloatPoint( myMPoint[0], myMPoint[1], myMPoint[2] )

Je l'ai testé et ça fonctionne très bien! J'ai un peu honte de ne pas l'avoir trouvé moi même... (Je pourrais tenter de m'excuser lamentablement en disant que quand on se met à tripatouiller l'API de Maya, les choses sont plus simple si on n'en "sort pas" :baffed: ).

EDIT 2011 02 11: La méthode ci dessus n'est pas applicable pour une MMatrix. Vous pouvez utiliser la classe MScriptUtil qui permet de créer une MMatrix ou MFloatMatrix depuis une liste (un tuple plutôt).

Voici un code qui permet de convertir une MFloatMatrix en MMatrix:

myFloatMatrix = OpenMaya.MFloatMatrix()
myMatrix = OpenMaya.MMatrix()
floatList = (myFloatMatrix(0,0), myFloatMatrix(0,1), myFloatMatrix(0,2), myFloatMatrix(0,3),
myFloatMatrix(1,0), myFloatMatrix(1,1), myFloatMatrix(1,2), myFloatMatrix(1,3),
myFloatMatrix(2,0), myFloatMatrix(2,1), myFloatMatrix(2,2), myFloatMatrix(2,3),
myFloatMatrix(3,0), myFloatMatrix(3,1), myFloatMatrix(3,2), myFloatMatrix(3,3))
OpenMaya.MScriptUtil().createMatrixFromList(floatList, myMatrix)

Ne me sautez pas a la gorge de suite, c’était juste pour l'exemple :grenadelauncher: . Il y a un moyen beaucoup plus rapide de faire ça:

myFloatMatrix = OpenMaya.MFloatMatrix()
myMatrix = OpenMaya.MMatrix(myFloatMatrix.matrix)

Il faut en effet utiliser l'attribut .matrix. Le résultat des deux méthodes est le même. Juste qu'il y en a une chiante a écrire et l'autre en deux lignes. :seSentCon:

:longBar:
Les problème de typage avec les Array (v2010)

Dans l'API, un MPointArray est une classe tableau de MPoint (logique!). L'opérateur (crochet) permet, de récupérer rapidement un MPoint dans ce tableau. (relogique!)

En C++, ça doit sûrement marcher. :gne: Mais en Python c'est une autre histoire.

Comme rien ne vaut mieux qu'un exemple:

myMPointTmp = myMPointArray[i]

Ceci fera un segmentation fault! (Le truc qui quitte Maya instantanément :siffle: ).

Après m'être arraché les cheveux, là dessus, il se trouve que la solution est assez... "Spéciale". Jugez par vous même:

inMeshMPointTmp = OpenMaya.MPoint( inMeshMPointArray[i] )

Ceci marchera impeccable! En gros, il faut ré-encapsuler ce qu'on récupère d'un Array Maya dans un objet de son type. :aupoil:

Faut avouez que c'est assez pathétique comme méthode... Mais bon.

Il faut savoir que la plupart des soucis de segmentation fault avec l'API Python sont due à ce problème de typage (Autodesk n'a pas complètement fini son travail on va dire. :seSentCon: )

N'hésitez donc pas, quand vous avez ce genre de soucis (crash sans raisons apparentes) à ré-encapsuler toutes vos variables. ça résout quelques soucis.

:longBar:
Fin et suite

Je continuera à ajouter des "choses bizarres" que je trouve dans l'API Python au fil du temps.

N'hésitez surtout pas à me laisser un commentaire si vous rencontrez, vous aussi, quelque chose de "tricky"! (Je sais que les MString font aussi de jolies choses! :hihi: )

A bientôt!

Dorian