[PYTHON] Un pour Maya UI

Maya Advent Calendar 2019

Cette année, c'est aussi un coup de pub ad-care.

Cette année est à l'heure.

Cette fois, c'est un matériau d'interface utilisateur qui a changé mon goût jusqu'à présent. Ça à l'air bon.

J'apprécie le caractère ludique lors de la création d'outils,

Chaque fois que je crée un nouvel outil, j'ajoute de nouveaux éléments et des œufs de Pâques.

Surtout lorsque je crée une interface utilisateur, je veux créer quelque chose qui semble amusant à utiliser.



Donc, cet échantillon. coordUI_00.gif En utilisant ce matériel, vous pouvez créer une interface utilisateur qui peut faire quelque chose comme le maquillage de personnage.

En premier lieu

Les commandes d'interface utilisateur fournies par Maya (ci-après appelées Maya UI dans cet article) sont hors de portée de l'endroit qui démange.

Par exemple, dans cet exemple, la commande image </ font> utilisée pour afficher des images.

Cela affichera la taille de l'image source telle quelle.

Il n'y a pas de problème si la taille de l'image source est la même,

Si possible, j'aimerais le mettre à l'échelle de manière flexible et l'utiliser lorsque la taille est différente.

Vous pouvez également l'afficher sous la forme d'un petit affichage de vignettes.

En d'autres termes, je souhaite contrôler l'affichage en code sans dépendre de la source.

Je ne peux pas contrôler un peu avec d'autres commandes de l'interface utilisateur,

Il y a une sensation de démangeaison que "l'endroit qui démange est hors de portée".

Cela dit, il y a de bonnes choses à propos de Maya UI.

"Si vous appuyez sur une commande, elle sortira avec une bonne sensation sans spécifier de détails."

Pour ceux qui n'ont pas l'habitude de le faire, Maya UI est ennuyeux, mais

Je pense qu'il est plus facile d'interagir avec PyQt et PySide lors de la création d'une interface utilisateur avec seulement quelques boutons. (* Bien sûr, certaines personnes trouvent PyQt et PySide plus faciles.)

Alors, le but de cet article.

** "Créez une interface utilisateur légèrement élaborée tout en gardant le confort de l'interface utilisateur Maya agréable" **

Facile à faire.

Basé sur l'interface utilisateur de Maya, intégrez-y le widget PySide requis.

Incorporer PySide dans l'interface utilisateur de Maya

Alors, comment intégrez-vous PySide dans l'interface utilisateur de Maya?

Même si vous l'incorporez, il vous suffit de créer une relation parent-enfant.

En d'autres termes, spécifiez Maya UI comme parent du widget PySide.

python


QWidget.setParent(parentWidget)

C'est facile.

Mais voici le problème. Le type à mettre dans le parentWidget doit être PySide.QtGui.QWidget </ font>.

python


QWidget.setParent(mayaUI)

Même ainsi, ce n'est pas bon </ font>.

Par conséquent, convertissez une fois Maya UI en PySide.

Comment obtenir Maya UI en tant que PySide !! https://kiwamiden.com/how-to-get-mayas-ui-as-pyside

Il y avait! Un article écrit par ** Takkun Dai-sensei **!

Bon travail!

C'est pourquoi c'est une solution.

Puisqu'il s'agit de PySide2 dans Maya 2017 ou plus tard, je vais le réécrire un peu.

C'est presque comme une réimpression, donc je ne supporte pas ** Dai-sensei ** ...

python


from PySide2 import QtGui
from PySide2 import QtWidgets
try:
    import shiboken2
except ImportError:
    from PySide2 import shiboken2
import maya.OpenMayaUI as omUI

# ---------------------------------------------------------
# mayaUI to pyside(thanks to takkyun)
# ---------------------------------------------------------
# @param <str>name    : maya UI name
# @param <type>toType : pyside type
# @return <obj> : pyside obj
def mayaToPySide(name, toType):

    ptr = omUI.MQtUtil.findControl(name)
    if not ptr:
        ptr = omUI.MQtUtil.findLayout(name)    
    if not ptr:
        ptr = omUI.MQtUtil.findMenuItem(name)
    if not ptr:
        return None
 
    return shiboken2.wrapInstance(long(ptr), toType)

Cette ...

python


QWidget.setParent(mayaToPySide(mayaUI), QtWidgets.QWidget)

Vous pouvez maintenant créer une relation parent-enfant = incorporer PySide.

Essayez de faire un échantillon

Tout d'abord, créez l'interface utilisateur Maya qui sera le conteneur.

Voici ce que j'ai fait pour 3 minutes de cuisson.

python


import maya.cmds as cmds
class toolGUI(object):
    windowName = 'coordWindow'
    windowTitle = 'Coordinate window'
    tabName = ['Coordinate']
    icName = 'coord'
    defWidth = 510
    defHeight = 530

    # ---------------------------------------------------------
    # init
    # ---------------------------------------------------------
    # @param None
    # @return None
    def __init__(self):
        if cmds.window(self.windowName, exists=True):
            cmds.deleteUI(self.windowName)

    # ---------------------------------------------------------
    # UI : Tab layout
    # ---------------------------------------------------------
    # @param None
    # @return <uiObj>coordTabcLayout : tab layout
    def tab_coord(self):
        coordTabcLayout = cmds.columnLayout(adj=1, p=self.alltabLayout)
        # thumbnail UI

        return coordTabcLayout

    # ---------------------------------------------------------
    # UI : show window
    # ---------------------------------------------------------
    # @param None
    # @return None
    def show(self):
        windowlayout = cmds.window(self.windowName, title=self.windowTitle,
                                   iconName=self.icName, menuBar=True)
        # window layout
        allformLayout = cmds.formLayout()
        self.alltabLayout = cmds.tabLayout(p=allformLayout)
        # build coord Tab
        coordTabcLayout = self.tab_coord()
        # set tab
        cmds.tabLayout(self.alltabLayout, e=True,
                        tabLabel=((coordTabcLayout, self.tabName[0])))
        # all form
        cmds.formLayout(allformLayout, e=True, af=[self.alltabLayout, 'top', 0])
        cmds.formLayout(allformLayout, e=True, af=[self.alltabLayout, 'left', 0])
        cmds.formLayout(allformLayout, e=True, af=[self.alltabLayout, 'right', 0])
        cmds.formLayout(allformLayout, e=True, af=[self.alltabLayout, 'bottom', 0])
        cmds.setParent('..')
        cmds.showWindow()

        cmds.window(self.windowName, e=True, w=self.defWidth, h=self.defHeight)

Situation actuelle ici

python


gui = toolGUI()
gui.show()

Quand vous l'exécutez avec ça coordUI_00.png Comme ça.

Ensuite, placez l'interface utilisateur pour afficher les images dans ** # miniature UI ** dans le code ci-dessus.

Utilisez QtWidgets.QGraphicsView </ font> pour afficher les images dans PySide.

Il existe une autre façon d'afficher simplement l'image, mais de faciliter le contrôle de l'affichage.

Pour dessiner quelque chose dans QGraphicsView, spécifiez QtWidgets.QGraphicsScene </ font> et placez-y l'objet à dessiner.

Cette fois, nous allons dessiner une image, donc nous utiliserons QtGui.QPixmap </ font>.

Dans Maya, QGraphicsView est un projet, QGraphicsScene est des données de scène et QPixmap est une texture.

Je pense que c'est en fait différent, mais la relation d'inclusion générale est comme ça.

alors,

Créer QGraphicsView
 ↓ 
Créer QGraphicsScene
 ↓ 
Création de QPixmap
 ↓
Définissez QPixmap sur QGraphicsScene
 ↓
Définir QGraphicsScene dans QGraphicsView

Je le ferai.

QPixmap crée un objet QPixmap pour cette image en définissant le chemin de l'image lors de sa création.

python


QtGui.QPixmap('C:/img/test.png')

Après cela, vous pouvez faire du parent de QGraphicsView l'interface utilisateur de mise en page de Maya.

À ce stade, il est important de noter que les indicateurs d'ajustement qui existent dans la mise en page Maya ne fonctionnent pas.

Par conséquent, si vous lancez simplement QGraphicsView dans la mise en page, coordUI_01.png Vous ne verrez qu'une vue d'un bâton comme celui-ci.

C'est déroutant, mais la ligne bleu clair sous le mot Coordonnée est la vue.

Donc, je vais spécifier arbitrairement la taille de la mise en page.

À ce stade, spécifiez également la taille de QGraphicsView.

En faisant ce qui précède, vous pourrez afficher l'image.

Lorsqu'elle est réellement transformée en fonction, elle ressemble à celle ci-dessous.

python


    # ---------------------------------------------------------
    # UI : coord frame layout
    # ---------------------------------------------------------
    # @param <uiObj>parent : parent UI
    # @return <uiObj>coordformLayout : form layout
    def frame_coord(self, parent):
        coordformLayout = cmds.formLayout(p=parent)
        # thumbnail row
        self.coordThumbnailLayout = cmds.columnLayout(adj=True, p=coordformLayout)
        thumbLayoutPyside = mayaToPySide(self.coordThumbnailLayout, QtWidgets.QWidget)
        self.coordGView = QtWidgets.QGraphicsView()
        self.coordGView.setParent(thumbLayoutPyside)
        self.coordThumbScene = QtWidgets.QGraphicsScene()
        self.coordThumbScene.clear()
        self.coordThumbScene.addPixmap(QtGui.QPixmap('C:/img/test.png'))
        self.coordGView.setScene(self.coordThumbScene)
        cmds.setParent(coordformLayout)
        # size 
        self.coordGView.resize(self.thumbWidth, self.thumbHeight)
        cmds.columnLayout(self.coordThumbnailLayout, e=True, w=self.thumbWidth, h=self.thumbHeight)

        # coord frame formLayout
        cmds.formLayout(coordformLayout, e=True, ap=[self.coordThumbnailLayout, 'top', 0, 0])
        cmds.formLayout(coordformLayout, e=True, af=[self.coordThumbnailLayout, 'left', 0])
        cmds.formLayout(coordformLayout, e=True, af=[self.coordThumbnailLayout, 'right', 0])
        cmds.setParent('..')

La mise en page avec PySide est ajoutée à la mise en page parent.

En créant une mise en page pour PySide, il sera plus facile à contrôler avec les commandes de Maya UI.

La mise en page parente est facilitée en l'incluant dans cette mise en page parente lors de la création d'une autre interface utilisateur telle que optionMenu </ font>.

Après cela, j'ai intégré cette fonction dans la base de Maya UI que j'ai créée plus tôt,

Si vous écrivez self.frame_coord (coordTabcLayout) </ font> dans la partie ** \ # miniature UI **, un exemple sera affiché.

Den ☆ coordUI_02.png

Essayez de faire quelque chose comme du maquillage de personnage

Eh bien, c'est un peu plus tard quand nous arrivons.

Ce que nous faisons dans l'exemple au début, c'est simplement superposer l'image transparente png.

En d'autres termes, créez autant de QPixmaps que vous en avez besoin et enregistrez-les dans QGraphicsScene.

Ce dont nous avons besoin plus tard, c'est d'une interface utilisateur pour la saisie et d'un mécanisme pour changer l'image lors de la saisie.

L'interface utilisateur d'entrée est omise car elle ajoute uniquement optionMenu </ font>.

Créez un optionMenu </ font> et placez-le dans votre mise en page existante.

Vient ensuite le mécanisme pour changer l'image.

Après avoir créé un objet image avec QPixmap,

pixmap.size (). Width () </ font> et pixmap.size (). Height () </ font> peut être utilisé pour les tailles verticales et horizontales. ..

Utilisez ce type pour lui donner la même taille de manière flexible.

Cette fois, au lieu de réduire l'image elle-même,

J'ai essayé de contrôler la taille en mettant à l'échelle QGraphicsView.

python


QGraphicsView.scale(scaleVal, scaleVal)

Le reste est le remplacement de l'image.

Pour le remplacer, remplacez le QPixmap.

QGraphicsPixmapItem est enregistré dans QGraphicsScene lorsque QPixmap est défini.

Plus tôt, j'ai dit que QPixmap est une texture si vous la comparez à Maya.

Les textures seules ne peuvent pas être affichées dans les vues Maya.

Vous avez besoin d'un objet sur lequel coller la texture.

L'objet pour coller la texture est QGraphicsPixmapItem.

En d'autres termes, spécifiquement, vous pouvez remplacer le QPixmap attaché au QGraphicsPixmapItem.

Obtenez le QGraphicsItem de QGraphicsScene et ne récupérez que le QGraphicsPixmapItem qu'il contient.

python


    # ---------------------------------------------------------
    # thumbnail : get imageItem from scene
    # ---------------------------------------------------------
    # @param <QtWidgets.QGraphicsScene>scene : scene object
    # @return <QtWidgets.QGraphicsPixmapItem/List>bgimgList : image object
    def getImgItemFromScn(self, scene):
        bgimgList = []
        for item in scene.items():
            if type(item) == QtWidgets.QGraphicsPixmapItem:
                bgimgList.append(item)
        return bgimgList

Cela ressemble à ceci lorsqu'il est transformé en fonction.

Cela ressemble à ceci pour définir le QPixmap.

python


QGraphicsPixmapItem.setPixmap(pixmap)

L'image de chaque partie est modifiée en se chevauchant avec celle-ci,

Ce à quoi vous devez faire attention ici, c'est l'ordre de superposition.

Lorsque vous obtenez le QGraphicsItem de QGraphicsScene, les éléments affichés sont récupérés dans l'ordre du haut.

En d'autres termes, dans cet exemple, le QGraphicsPixmapItem qui est affiché dans l'ordre de la tête, du corps, des jambes et des poils du dos est acquis.

Après cela, il n'y a aucun problème si vous remplacez le pixmap en tenant compte de l'ordre d'acquisition de celui-ci.

Cette fois, la position d'affichage de l'image reste la même car la position d'affichage est ajustée côté image.

Lors du réglage côté cordon, ajustez la position séparément.

Ce qui précède est le mécanisme pour changer l'image.

Activez cette fonction lorsque l'option optionMenu </ font> change.

J'ai sauté la création d'image ennuyeuse ...



Et voici le produit fini. coordUI_01.gif Yatter mignon

J'ai hérité de QtWidgets.QGraphicsView </ font> et j'ai essayé de rendre possible la mise à l'échelle et le déplacement en déplaçant la classe.

C'est pourquoi j'ai utilisé QGraphicsView-I see.

En ce qui concerne le mouvement de mise à l'échelle, la largeur du papier (largeur de l'article?) Est sur le point de s'épuiser, et ce sera une histoire PySide, donc à une autre occasion.

Yatter mignon

Ce n'était que 2D, mais ce serait encore mieux si cela pouvait être une visionneuse 3D.

Si vous faites jusqu'à présent, si vous faites tout avec PySide ... Gefungefun

Non, vous pouvez utiliser les modules d'interface utilisateur de PySide pour votre interface utilisateur Maya existante!

Peut être utilisé Peut être utilisé

Je pense qu'il existe d'autres meilleures façons de l'intégrer, mais pour le moment, je l'ai essayé comme ça.

J'espère que cela vous aidera lorsque vous souhaitez ajouter des efforts à l'interface utilisateur de Maya.

À propos, il était plus difficile de créer une image pour un échantillon que d'écrire du code honnête.

70% de cet article est constitué de création d'images pour un exemple de code.

Jusqu'à présent (: 3 noshi)

Demain, c'est l'histoire de "Enregistrer les commandes dans le menu principal en utilisant le décorateur" par yamahigashi @ github.

UCL_logo.png

    • Avertissement * Nous ne garantissons pas la sécurité du code publié dans cet article. Nous ne sommes pas responsables des dommages causés par l'utilisation de ces codes. Utilisez à vos risques et périls. *