Maya PySide2 / PySide チュートリアル 初級編 ③ – GUIからMayaのコマンドを実行、BuddyやTab orderの設定方法

PySide,Tutorial,PySide2,Qt,Maya

このチュートリアルでは PySide でGUIからMayaのコマンドを実行、BuddyやTab orderの設定方法を学びます

基本的にPySideで何かを実行する場合はSignals & Slotsを使用します
Signal&Slotに関してはMaya PySide2 / PySide チュートリアル 初学編 ⑦ – Signals & Slotsを理解するで説明していますがさらっとおさらいをすると
Signalsとは、何かが起こったとき(ボタンが押されるや入力ボックスのテキストが変化するなど) にウィジェットが発する通知のこと
Slotsは、スロットはシグナルと接続した場合、そのシグナルに反応してスロットに保持している何かを実行します
例えば、値が変わったことを通知するシグナル valueChangedに反応して変更されたオブジェクトの現在のValue値を受け取る関数を実行するなど

今回はVertex Colorを調整するToolを作るのでApplyをクリックしたときに選択中のObjectのVertexColorが設定されるにします
20220402_06

QPushButtonの場合clickedというSignalがあります
これを使用することでクリックした際にVertexColorを設定する関数を実行できます

# !/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys

import maya.cmds as cmds
import maya.OpenMayaUI as OpenMayaUI

try:
    from PySide2.QtWidgets import *
    from PySide2.QtCore import *
    from PySide2.QtUiTools import QUiLoader
    import shiboken2 as shiboken
except ImportError:
    from PySide.QtGui import *
    from PySide.QtCore import *
    from PySide.QtUiTools import QUiLoader
    import shiboken

ptr = OpenMayaUI.MQtUtil.mainWindow()
mayaMainWindow = shiboken.wrapInstance(long(ptr), QMainWindow)

class vtxMainWindow(QMainWindow):
    __currentPath = os.path.dirname(__file__)
    __uiFilePath = os.path.join(__currentPath, ui, vtxMain.ui)

    def __init__(self, parent=None):
        super(vtxMainWindow, self).__init__(parent)
        loader = QUiLoader()
        uiWidget = loader.load(self.__uiFilePath)
        self.setCentralWidget(uiWidget)
        self.setGeometry(500, 300, 400, 270)
        self.setWindowTitle(.ui MainWindow)

        self.centralWidget().pushButton.clicked.connect(self.setVertexColor)

    def setVertexColor(self):
        objects = cmds.ls(sl=True)
        for object in objects:
            cmds.select(object)
            cmds.polyColorPerVertex(
                r=0.8,
                g=0.5,
                b=0.4,
                a=0.8
            )
            cmds.setAttr(%s.displayColors % object, 1)
        cmds.select(objects)

def main():
    app = QApplication.instance()
    mainWin = vtxMainWindow(parent=mayaMainWindow)
    mainWin.show()
    sys.exit()
    app.exec_()

上のコードをvtxMain.pyに記述すると下の画像のようにメッシュを選択した状態でApplyを行うと色がメッシュに対してつきます

20220403_02

def setVertexColor(self):では、今回のメインはGUIからMayaのコマンドを実行するということを目標としているので簡素なコードを記述しました
ザックリ説明すると選択しているオブジェクト一つ一つにpolyColorPerVertexとアトリビュートのdisplayColorsを有効化にするというものです
この関数をApplyボタンがクリックされた際に実行されるようにしている部分がself.centralWidget().pushButton.clicked.connect(self.setVertexColor)になります
先頭のself.centralWidget()の部分ではvtxMainWindowというQMainWindowのcentralWidgetにアクセスしています
このcentralWidgetはひとつ前のパートで設定した.uiになります
そして.uiでのWidgetの名前はQt DesignerのObjectInspectorで設定したものになります
20220403_01
実際に名前をpushButtonからbutton_Applyに変えてMayaで改めてUIを起動し直してみてください
下のようなエラーコードが発生すると思います

# Error: 'PySide2.QtWidgets.QWidget' object has no attribute 'pushButton'
# Traceback (most recent call last):
#   File , line 3, in 
#   File C:/Users/mutu/Documents/maya/scripts\sample\vtxMain.py, line 115, in main
#     mainWin = vtxMainWindow(parent=mayaMainWindow)
#   File C:/Users/mutu/Documents/maya/scripts\sample\vtxMain.py, line 97, in __init__
#     self.centralWidget().pushButton.clicked.connect(self.setVertexColor)
# AttributeError: 'PySide2.QtWidgets.QWidget' object has no attribute 'pushButton' # 

エラーを確認したらself.centralWidget().pushButton.clicked.connect(self.setVertexColor)からself.centralWidget().button_Apply.clicked.connect(self.setVertexColor)に変更し、実行し直してみてください
問題なくUIが起動できるはずです

さて、ここまでは実際にGUIからMayaのコマンドを実行することはできたと思いますが一つここで問題があります
GUIにはRGBAそれぞれに対して値を設定できるはずですが今のままではただ、任意に指定したカラーが設定されるだけになっています
もちろんものによってはそれでいいのかもしれませんが今回はGUI上で変更した内容が反映されるようになっていなければなりません

つまり、QDoubleSpinBoxの現在の値をApplyを押すたびにsetVertexColorでその値が反映されるようにする必要があります

            cmds.polyColorPerVertex(
                r=0.8,
                g=0.5,
                b=0.4,
                a=0.8
            )

現在ハードコードされている各チャンネルに対応するQDoubleSpinBoxの値を引数に入れれば簡単に実現できます

QDoubleSpinBoxの現在の値を取得するにはvalue()を実行することで取得することができるので下のコードのように書き換えることで実現できます

            cmds.polyColorPerVertex(
                r=self.centralWidget().doubleSpinBox_R.value(),
                g=self.centralWidget().doubleSpinBox_G.value(),
                b=self.centralWidget().doubleSpinBox_B.value(),
                a=self.centralWidget().doubleSpinBox_A.value()
            )

任意の数値を入れてApplyをしてみてください
20220403_03

ここで気づいた人もいるかもしれませんがQDoubleSpinBoxのup-arrowやdown-arrowをクリックすると1.0ずつ値が上がっていくのです
vertex colorの設定は0.0-1.0の値で変更を加えたくたいていの場合は0.01ずつもしくは0.1ずつ変更したいことが多いのにこれではQDoubleSpinBoxである意味がなくなってしまいます

20220403_04

この問題はQt Designerで適切に設定することで解決することができます

20220403_05
複数のQDoubleSpinBoxを選択し、Property>QDoubuleSpinBox>signaleStepを1.0から0.01に変更することで解決します
ついでにvalueのMaxの値やデフォルトのValueも変更しておきます
Alphaに関してはValueを1.0にしておきましょう

propertyvalue
Maximum1.0
signaleStep0.01
valueRGBは 0.5 Alphaは1.0

変更後、再度起動すると下の画像のように0.01ずつ値が変更されるようになります
20220403_06

Buddyの設定

こういった入力フォームではよくAlt+何かのキーでショートカットできるなんてこともよくあるかと思います
それを設定するのがEdit Buddiesです
これを設定するには各入力項目に対応するラベルが必要になります
設定方法はいたって簡単で&を付けた文字を含めるだけです

20220403_07
&R (&R)のようにそれぞれ対応する名前をつけてください

次にEdit Buddiesに切り替えてください
20220403_08

切り替えた後にGUIにマウスオーバーすると設定できるウィジェットが赤くなります
赤くなったウィジェットでマウスをクリックホールドし、対応するウィジェットにドラックするか、右クリックからSet automaticallyで自動設定ができます
20220403_09

設定がうまくいくと&R (&R)からR (R)のように名前が変更されているはずです

この状態で起動するとAlt+対応するキーで入力部分にフォーカスが行くようになります

Tab orderの設定

こういった入力フォームを使用するときにtabを使用して入力フォームを移動することもあるかもしれません
そういったときはTab orderを使用します
Tab orderの設定はEdit Tab Orderでできます
20220403_10

タブキーを押す際に順番にフォーカスが移動するように設定したい順にクリックしていってください

20220403_11

設定ができたらUIを起動し、タブキーを押していくと、設定した順番にフォーカスが移動するのがわかるはずです

20220403_12


Maya PySide2 / PySide チュートリアルのこのパートでは、GUIからMayaのコマンドを実行する方法を学びました

次はMaya PySide2 / PySide チュートリアル 初級編 ④ – .uiとPythonのコーディングを組み合わせてみる
前はMaya PySide2 / PySide チュートリアル 初級編 ② – .uiをMayaで表示する