[PYTHON] Eine für Maya UI

Maya Advent Calendar 2019

Dieses Jahr ist auch ein Ad-Care-One-Stroke.

Dieses Jahr ist pünktlich.

Diesmal ist es eine UI-Geschichte, die meinen Geschmack bisher verändert hat. Es sieht gut aus.

Ich schätze Verspieltheit bei der Herstellung von Werkzeugen,

Immer wenn ich ein neues Werkzeug mache, füge ich neue Elemente und Ostereier hinzu.

Besonders wenn ich eine Benutzeroberfläche erstelle, möchte ich etwas erstellen, dessen Verwendung Spaß macht.



Also dieses Beispiel. coordUI_00.gif Mit diesem Material können Sie eine Benutzeroberfläche erstellen, die so etwas wie Charakter-Make-up ausführen kann.

An erster Stelle

Die von Maya bereitgestellten UI-Befehle (im Folgenden in diesem Artikel als Maya-UI bezeichnet) sind außerhalb der Reichweite des juckenden Ortes.

In diesem Beispiel wird beispielsweise der Befehl Bild </ font> zum Anzeigen von Bildern verwendet.

Dadurch wird die Größe des Quellbilds unverändert angezeigt.

Es ist kein Problem, wenn die Größe des Quellbildes gleich ist.

Wenn möglich, möchte ich es flexibel skalieren und verwenden, wenn die Größe unterschiedlich ist.

Möglicherweise möchten Sie es auch als kleine Miniaturansicht anzeigen.

Mit anderen Worten, ich möchte die Anzeige im Code steuern, ohne von der Quelle abhängig zu sein.

Ich kann mit anderen UI-Befehlen nicht wenig steuern.

Es gibt ein Gefühl von Juckreiz, dass "der juckende Ort außer Reichweite ist".

Das heißt, es gibt einige gute Dinge über Maya UI.

"Wenn Sie einen Befehl drücken, wird er ein gutes Gefühl vermitteln, ohne Details anzugeben."

Für diejenigen, die es nicht gewohnt sind, ist Maya UI ärgerlich, aber

Ich denke, es ist einfacher, mit PyQt und PySide zu interagieren, wenn Sie eine Benutzeroberfläche mit nur wenigen Schaltflächen erstellen. (* Natürlich finden einige Leute PyQt und PySide einfacher.)

Also, der Zweck dieses Artikels.

** "Erstellen Sie eine etwas ausgefeilte Benutzeroberfläche, während Sie den Komfort der Maya-Benutzeroberfläche beibehalten" **

Leicht zu schaffen.

Betten Sie dort basierend auf der Maya-Benutzeroberfläche das erforderliche PySide-Widget ein.

Betten Sie PySide in die Maya-Benutzeroberfläche ein

Wie bettet man PySide in die Maya-Benutzeroberfläche ein?

Selbst wenn Sie es einbetten, müssen Sie nur eine Eltern-Kind-Beziehung erstellen.

Mit anderen Worten, geben Sie Maya UI als übergeordnetes Element für das PySide-Widget an.

python


QWidget.setParent(parentWidget)

Es ist einfach.

Aber hier ist das Problem. Der Typ, der in das parentWidget eingefügt werden soll, muss PySide.QtGui.QWidget </ font> sein.

python


QWidget.setParent(mayaUI)

Trotzdem ist es nicht gut </ font>.

Konvertieren Sie daher die Maya-Benutzeroberfläche einmal in PySide.

Wie bekomme ich Maya UI als PySide !! https://kiwamiden.com/how-to-get-mayas-ui-as-pyside

Dort war! Ein Artikel von ** Takkun Dai-sensei **!

Gut gemacht!

Deshalb ist es eine Lösung.

Da es PySide2 in Maya 2017 oder später ist, werde ich es ein wenig umschreiben.

Es ist fast wie ein Nachdruck, also kann ich ** Dai-sensei ** nicht ausstehen ...

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)

Dies ...

python


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

Jetzt können Sie eine Eltern-Kind-Beziehung erstellen = PySide einbetten.

Versuchen Sie eine Probe zu machen

Erstellen Sie zunächst die Maya-Benutzeroberfläche, die der Container sein soll.

Hier ist, was ich für 3 Minuten gekocht habe.

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)

Aktuelle Situation hier

python


gui = toolGUI()
gui.show()

Wenn Sie es damit ausführen coordUI_00.png So was.

Als nächstes platzieren Sie die Benutzeroberfläche für die Bildanzeige im obigen Code unter ** # thumbnail UI **.

Verwenden Sie QtWidgets.QGraphicsView </ font>, um Bilder in PySide anzuzeigen.

Es gibt eine andere Möglichkeit, nur das Bild anzuzeigen, aber die Steuerung der Anzeige zu vereinfachen.

Um etwas in QGraphicsView zu zeichnen, geben Sie QtWidgets.QGraphicsScene </ font> an und fügen Sie das zu zeichnende Objekt ein.

Dieses Mal zeichnen wir ein Bild und verwenden QtGui.QPixmap </ font>.

In Maya ist QGraphicsView ein Projekt, QGraphicsScene sind Szenendaten und QPixmap ist eine Textur.

Ich denke, es ist tatsächlich anders, aber die allgemeine Inklusionsbeziehung ist so.

damit,

Erstellen Sie QGraphicsView
 ↓ 
Erstellen Sie QGraphicsScene
 ↓ 
QPixmap-Erstellung
 ↓
Setzen Sie QPixmap auf QGraphicsScene
 ↓
Stellen Sie QGraphicsScene in QGraphicsView ein

Ich werde das machen.

QPixmap erstellt ein QPixmap-Objekt für dieses Bild, indem der Pfad des Bildes beim Erstellen festgelegt wird.

python


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

Danach ist es in Ordnung, wenn Sie das übergeordnete Element von QGraphicsView zur Layout-Benutzeroberfläche von Maya machen.

Zu diesem Zeitpunkt ist zu beachten, dass die im Maya-Layout vorhandenen Anpassungsflags nicht funktionieren.

Wenn Sie also nur QGraphicsView in das Layout werfen, coordUI_01.png Sie sehen nur einen Blick auf einen solchen Stock.

Es ist verwirrend, aber die hellblaue Linie unter dem Wort Koordinate ist die Ansicht.

Daher werde ich die Größe des Layouts beliebig festlegen.

Geben Sie zu diesem Zeitpunkt auch die Größe von QGraphicsView an.

Auf diese Weise können Sie das Bild anzeigen.

Wenn es tatsächlich zu einer Funktion gemacht wird, sieht es wie die folgende aus.

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('..')

Das Layout mit PySide wird dem übergeordneten Layout hinzugefügt.

Durch das Erstellen eines Layouts für PySide ist die Steuerung mit Maya-UI-Befehlen einfacher.

Das übergeordnete Layout wird einfacher gestaltet, indem es in dieses übergeordnete Layout aufgenommen wird, wenn eine andere Benutzeroberfläche erstellt wird, z. B. das Optionsmenü </ font>.

Danach habe ich diese Funktion in die Basis der Maya-Benutzeroberfläche integriert, die ich zuvor erstellt habe.

Wenn Sie self.frame_coord (coordTabcLayout) </ font> in den Teil ** \ # thumbnail UI ** schreiben, wird ein Beispiel angezeigt.

Den ☆ coordUI_02.png

Versuche so etwas wie Charakter Make-up zu machen

Nun, es ist etwas später, als wir hier ankommen.

Was wir zu Beginn im Beispiel tun, ist nur das transparente PNG-Bild zu überlagern.

Mit anderen Worten, erstellen Sie so viele QPixmaps wie Sie benötigen und registrieren Sie sie in der QGraphicsScene.

Was wir später brauchen, ist eine Benutzeroberfläche für die Eingabe und ein Mechanismus zum Ändern des Bildes bei der Eingabe.

Die Eingabe-Benutzeroberfläche wird weggelassen, da nur das Optionsmenü </ font> hinzugefügt wird.

Erstellen Sie ein Optionsmenü </ font> und platzieren Sie es in Ihrem vorhandenen Layout.

Als nächstes folgt der Mechanismus zum Ändern des Bildes.

Nachdem Sie ein Bildobjekt mit QPixmap erstellt haben,

pixmap.size (). Width () </ font> und pixmap.size (). Height () </ font> kann für vertikale und horizontale Größen verwendet werden. ..

Verwenden Sie diesen Kerl, um es flexibel auf die gleiche Größe zu bringen.

Dieses Mal, anstatt das Bild selbst kleiner zu machen,

Ich habe versucht, die Größe durch Skalieren der QGraphicsView zu steuern.

python


QGraphicsView.scale(scaleVal, scaleVal)

Der Rest ist das Ersetzen des Bildes.

Ersetzen Sie zum Ersetzen die QPixmap.

QGraphicsPixmapItem wird in QGraphicsScene registriert, wenn QPixmap festgelegt ist.

Vorhin habe ich gesagt, dass QPixmap eine Textur ist, wenn man sie mit Maya vergleicht.

Texturen allein können in Maya-Ansichten nicht angezeigt werden.

Sie benötigen ein Objekt, um die Textur einzufügen.

Das Objekt zum Einfügen der Textur ist QGraphicsPixmapItem.

Mit anderen Worten, insbesondere können Sie die an das QGraphicsPixmapItem angehängte QPixmap ersetzen.

Holen Sie sich das QGraphicsItem aus der QGraphicsScene und nehmen Sie nur das darin enthaltene QGraphicsPixmapItem auf.

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

Es sieht so aus, wenn es zu einer Funktion gemacht wird.

Es sieht so aus, als würde man die QPixmap einstellen.

python


QGraphicsPixmapItem.setPixmap(pixmap)

Das Bild jedes Teils wird geändert, während es sich mit diesem überlappt.

Was Sie hier beachten müssen, ist die Reihenfolge der Überlagerung.

Wenn Sie das QGraphicsItem aus der QGraphicsScene abrufen, werden die angezeigten Elemente in der Reihenfolge von oben abgerufen.

Mit anderen Worten, in diesem Beispiel wird das QGraphicsPixmapItem erfasst, das in der Reihenfolge Kopf, Körper, Beine und Rückenhaar angezeigt wird.

Danach ist es kein Problem mehr, wenn Sie die Pixmap unter Berücksichtigung der Erfassungsreihenfolge ersetzen.

Diesmal bleibt die Anzeigeposition des Bildes gleich, da die Anzeigeposition auf der Bildseite angepasst wird.

Passen Sie die Position beim Einstellen auf der Kabelseite separat an.

Das Obige ist der Mechanismus zum Ändern des Bildes.

Aktivieren Sie diese Funktion, wenn das Optionsmenü </ font> wechselt.

Ich habe die nervige Bilderstellung übersprungen ...



Und hier ist das fertige Produkt. coordUI_01.gif Süßes Geschwätz

Ich habe QtWidgets.QGraphicsView </ font> geerbt und versucht, das Skalieren und Verschieben durch Verschieben der Klasse zu ermöglichen.

Deshalb habe ich QGraphicsView verwendet - wie ich sehe.

Was die Skalierungsbewegung betrifft, so ist die Papierbreite (Artikelbreite?) Im Begriff, zur Neige zu gehen, und es wird eine PySide-Geschichte sein, also bei einer anderen Gelegenheit.

Süßes Geschwätz

Dies war nur 2D, aber es wäre noch besser, wenn es ein 3D-Viewer sein könnte.

Wenn Sie dies bisher tun, wenn Sie alles mit PySide tun ... Gefungefun

Nein, Sie können die UI-Module von PySide für Ihre vorhandene Maya-Benutzeroberfläche verwenden!

Kann verwendet werden Kann verwendet werden

Ich denke, es gibt andere bessere Möglichkeiten, es einzubetten, aber vorerst habe ich es so versucht.

Ich hoffe, es hilft, wenn Sie der Maya-Benutzeroberfläche etwas mehr Aufwand hinzufügen möchten.

Übrigens war es schwieriger, ein Bild für ein Beispiel zu erstellen, als ehrlichen Code zu schreiben.

70% dieses Artikels besteht aus der Bilderstellung für Beispielcode.

Bisher (: 3 noshi)

Morgen ist die Geschichte von "Registrieren von Befehlen im Hauptmenü mit Decorator" von yamahigashi @ github.

UCL_logo.png

    • Haftungsausschluss * Wir übernehmen keine Garantie für die Sicherheit des in diesem Artikel veröffentlichten Codes. Wir sind nicht verantwortlich für Schäden, die durch die Verwendung dieser Codes verursacht werden. Bitte verwenden Sie auf eigenes Risiko. * *