ON-BLOG

CGのこと、あれこれ書いてます。

Pyside勉強 その十(終)

それでは、最後に前回作成したセレクターに
ボタンの処理となんとなく選択しているボタンの視認性を変更してみて
最後にします。

まずはコード。

import os
import sys

from PySide import QtCore, QtGui
from PySide.QtUiTools import QUiLoader
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin

CURRENT_PATH = "D:/"

class GUI(MayaQWidgetBaseMixin, QtGui.QMainWindow):

    def __init__(self, parent=None):
        super(GUI, self).__init__(parent)
        loader = QUiLoader()
        uiFilePath = os.path.join(CURRENT_PATH, 'UI.ui')
        self.UI = loader.load(uiFilePath)
        self.setCentralWidget(self.UI)
        self.UI.BackGound.setPixmap(QtGui.QPixmap("D:/Selector.png"))
        self._filter = Filter()
        self.UI.widget.installEventFilter(self._filter)
        self.setWindowTitle("UI_testWindow")
        self.resize(660, 840)
        
        self.UI.CTRL_Head.clicked.connect(self.Push)
        self.UI.CTRL_L__Collar.clicked.connect(self.Push)
        self.UI.CTRL_R__Collar.clicked.connect(self.Push)
        self.UI.CTRL_Chest.clicked.connect(self.Push)
        self.UI.CTRL_Body.clicked.connect(self.Push)
        self.UI.CTRL_Hips.clicked.connect(self.Push)
        self.UI.CTRL_L__ElbowPole.clicked.connect(self.Push)
        self.UI.CTRL_L__Hand.clicked.connect(self.Push)
        self.UI.CTRL_R__ElbowPole.clicked.connect(self.Push)
        self.UI.CTRL_R__Hand.clicked.connect(self.Push)
        self.UI.CTRL_L__KneePole.clicked.connect(self.Push)
        self.UI.CTRL_L__Foot.clicked.connect(self.Push)
        self.UI.CTRL_R__KneePole.clicked.connect(self.Push)
        self.UI.CTRL_R__Foot.clicked.connect(self.Push)

        self.UI.ALL.clicked.connect(self.ALL_Sel)
        
    def Push(self):
        Sender =self.sender()
        modifiers = QtGui.QApplication.keyboardModifiers()
        if modifiers == QtCore.Qt.ControlModifier:
            cmds.select(Sender.objectName(),add=True)
        else:
            cmds.select(Sender.objectName())

    def ALL_Sel(self):
        cmds.select("CTRL*")


class Filter(QtCore.QObject):
    def eventFilter(self, widget, event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            self.origin = event.pos()
            self.rubberBand = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle,widget)
            self.origin.setX(self.origin.x())
            self.origin.setY(self.origin.y())
            self.rubberBand.setGeometry(QtCore.QRect(self.origin,QtCore.QSize()))
            self.rubberBand.show()
            print "Click"
            print self.origin.x()
            print self.origin.y()
            
        elif event.type() == QtCore.QEvent.MouseMove:
            if self.rubberBand.isVisible():
                self.movePos = event.pos()
                self.movePos.setX(self.movePos.x()+ widget.x())
                self.movePos.setY(self.movePos.y()+ widget.y())
                self.rubberBand.setGeometry(QtCore.QRect(self.origin,self.movePos).normalized())
                print "Move"
                print event.x()
                print event.y()
            
        elif event.type() == QtCore.QEvent.MouseButtonRelease:
            print "Release"
            print event.x()
            print event.y()
            self.rubberBand.hide()
            rect = self.rubberBand.geometry()
            rect.setX(rect.x()-widget.x())
            rect.setY(rect.y()-widget.y())
            rect.setWidth(rect.width()-widget.x())
            rect.setHeight(rect.height()-widget.y())
            selected = []
            #ウィンドウ内のQPushButtonをすべて取得
            for child in widget.findChildren(QtGui.QPushButton):
                if rect.intersects(child.geometry()):
                    selected.append(child)
                    child.setChecked(True)
            if selected:
                self.rectSelection(selected)
            else:
                cmds.select(cl=True)
                for child in widget.findChildren(QtGui.QPushButton):
                    if child.objectName() != "ALL":
                        child.setStyleSheet("background-color: rgb(225,225,225);color: rgb(0, 0, 0);")
        return False

    def rectSelection(self,sel):
        selectBox = []
        for i in sel:
            print i.objectName()
            if i.objectName() == "ALL":
                pass
            else:
                print i.objectName()
                selectBox.append(i.objectName())
                i.setStyleSheet("background-color: rgb(20,20,20);color: rgb(255, 255, 255);")
        try:
            cmds.select(selectBox)
        except:
            pass


def main():
    app = QtGui.QApplication.instance()
    ui = GUI()
    ui.show()

if __name__ == '__main__':
    main()

実行するとこんな感じ。
f:id:tommy_on:20190429012657p:plain
前回からUIが変わってます。
といいつつも、中身は正直ボタンと色変化が入っただけで、何も変わってません。
f:id:tommy_on:20190429012755p:plain

実際実行すると、キチンと矩形選択ができており
のボタンの色も変わってます。
f:id:tommy_on:20190429013340p:plain

さらに下部にある、【SelectAll】も動いていることが確認できます。
f:id:tommy_on:20190429013428p:plain


色が変わったボタンも、何もない箇所で矩形選択をすると
通常状態に戻ります。
f:id:tommy_on:20190429013547p:plain


では今回も同様に、変わったところ、追加したところを記載してみます。

self.UI.CTRL_Head.clicked.connect(self.Push)
self.UI.CTRL_L__Collar.clicked.connect(self.Push)
self.UI.CTRL_R__Collar.clicked.connect(self.Push)
self.UI.CTRL_Chest.clicked.connect(self.Push)
self.UI.CTRL_Body.clicked.connect(self.Push)
self.UI.CTRL_Hips.clicked.connect(self.Push)
self.UI.CTRL_L__ElbowPole.clicked.connect(self.Push)
self.UI.CTRL_L__Hand.clicked.connect(self.Push)
self.UI.CTRL_R__ElbowPole.clicked.connect(self.Push)
self.UI.CTRL_R__Hand.clicked.connect(self.Push)
self.UI.CTRL_L__KneePole.clicked.connect(self.Push)
self.UI.CTRL_L__Foot.clicked.connect(self.Push)
self.UI.CTRL_R__KneePole.clicked.connect(self.Push)
self.UI.CTRL_R__Foot.clicked.connect(self.Push)
self.UI.ALL.clicked.connect(self.ALL_Sel)

ボタンのコネクション処理を追加しています。
一番下以外は共通の関数に飛んでいます。

def Push(self):
	Sender =self.sender()
	modifiers = QtGui.QApplication.keyboardModifiers()
	 if modifiers == QtCore.Qt.ControlModifier:
		cmds.select(Sender.objectName(),add=True)
	else:
		cmds.select(Sender.objectName())

上記ボタンの押したときに飛ぶ関数です。
内容的には、ボタンにあったコントローラーを選択しているだけです。
一行目の

Sender =self.sender()

はクリックされたボタンを返しています。
詳しく記載すると、HELPを見る限り
【直前のシグナルを送信したウィジェットを返す】
と翻訳できます。
なので、押されたボタンを返す。という意味になります。
Qtデザイナー上で、コントローラーの名前をボタンにしているので
押されたボタン=コントローラーということになります。

次に

modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ControlModifier:

このコマンドはキーボードの入力を取得する関数と
その入力に対する、分岐処理です。
Ctrlキーを押されてたらという分岐になり
その後の

	cmds.select(Sender.objectName(),add=True)
else:
	cmds.select(Sender.objectName())

で、追加選択か、通常選択を切り替えています。

次に

def ALL_Sel(self):
	cmds.select("CTRL*")

この関数は【SelectAll】というボタンの処理になります。
内容的には、リグシーン内コントローラーは必ず
プレフィックスに【CTRL】がついているので
その名がついたものを選択しています。
このリグ特有の処理になります。
個人的には、コントローラーはアトリビュート追加した方が
いいと思います…


次は少し飛んで

if child.objectName() != "ALL":
	child.setStyleSheet("background-color: rgb(225,225,225);color: rgb(0, 0, 0);")

矩形選択後の処理になり、矩形選択したボタンの中で【SelectAll】
を除く、ボタンの色を【setStyleSheet】で色変えをしています。
https://dftalk.jp/?p=16108
StyleSheetについては、こちらが参考になります!
処理的には、Defの色に戻しているだけです。

最後になります。

 def rectSelection(self,sel):
        selectBox = []
        for i in sel:
            #print i.objectName()
            if i.objectName() == "ALL":
                pass
            else:
                #print i.objectName()
                selectBox.append(i.objectName())
                i.setStyleSheet("background-color: rgb(20,20,20);color: rgb(255, 255, 255);")
        try:
            cmds.select(selectBox)
        except:
            pass

矩形選択部分になります。

if i.objectName() == "ALL":

【SelectAll】
は矩形選択から除外したいので、無視しています。

以下のコマンドは前回も出ていますが、setStyleSheetが追加されています。
矩形選択選択後、選択されているものは、ボタンの色を変えています。

selectBox.append(i.objectName())
 i.setStyleSheet("background-color: rgb(20,20,20);color: rgb(255, 255, 255);")


こんなもんでしょうか…
とりあえず、簡単ではありますが、矩形選択ができるセレクターを作るまで
は記事にできました。
ただ、このコマンドだけでは、実務ではまだまだまだまだ耐えれません。
※実感として

最低限【ネームスペース対応】【UndoRedo対応】【モーション補助ツールの追加】
【ビューポート選択と、UI選択のリンク】【タブ対応】【UIのズーム機能】が必須になるかと思います。
こちらは記載するよりも、いろんなセレクターが世にでてますので
それらを参考にしていただければと、思います。


とりあえず、平成の間に書き終えてよかった…
以上です。