株式会社デジタル・フロンティア-Digital Frontier

Header

Main

NukeでPySide

2013/6/24

Tag: ,,

皆さんお久しぶりです、開発室山口です。
しばらくNukeの開発から離れ半分忘れかけの状態ですが、今回も頑張ってNukeネタを
紹介したいと思います。

ところでMayaでも2014から標準でインストールされるようになりましたPySideですが
いいですよね!

Nukeには以前からインストールされていましたが、専用のUIコマンドには出来ない物が作れたり、
Mayaと記述方法を合わせられたり、またQtDesignerで作成したUIを使用できたりと、とても魅力的です。

そこで今回はQtDesignerで作成したUIをNuke上にドッキングする方法と、
メニューから独立して立ち上あげる方法の2つを紹介したいと思います。
※今回の記事はNuke7.0以上のバージョンが対象です。


QtDesignerでUIを作成

早速始めたいと思います。
まずはQtDesignerでドッキングするためのUIを用意します。

ちなみにQtDesignerはネット上で無料でダウンロードできますし、Mayaをお使いの方は2012以降
binフォルダの中にdesigner.exeという名前でインストールされています。

使いかたは下記のリンクのDFtalkでも紹介されているので参考にしてください。

https://dftalk.jp/cp-bin/wordpress/?p=2934

ではQtDesignerでUIを作成します。作成するタイプはWidgetを使用してください。

サンプルでは下記のようなUIを作成しました。

作成できたらファイルを保存します。Cドライブの直下にnukeフォルダを作成し
その中にsample.uiという名前で保存します。

C:/nuke/sample.ui

これで下準備は完了です。


UIをNukeのパネルにドッキング

まず初めにパネルにドッキングする方法から紹介したいと思います。

上記で作成したuiファイルを読み込むためのクラスを作成しましょう。

スクリプトパスの通っている.nukeフォルダ直下に下記のコマンドを
sampleWindow1.pyという名前で保存します。

# -*- coding: utf-8 -*-
 
from PySide import QtCore, QtGui
from PySide.QtUiTools import QUiLoader
 
class MyWindow(QtGui.QWidget):
 
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
 
        # QWidgetにuiファイルの親となるレイアウトをセットします。
        self.setLayout(QtGui.QVBoxLayout())
 
        # .uiファイルをロードしオブジェクト化します
        loader = QUiLoader()
        uifile = 'C:/nuke/sample.ui'
        self.ui = loader.load(uifile)
 
        # セットしたレイアウトにUIファイルを追加します
        self.layout().addWidget(self.ui)
 
        # 周囲の余白を取り除きます
        self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
                                             QtGui.QSizePolicy.Expanding))

クラスへ継承するオブジェクトはQWidgetを使用しましたが、QMainWindowを使用することもできますので
そちらを使用したい方は、後述する「独立したウインドウを立ち上げる」の方の記事を参考にしてください。

次にドッキングする部分のスクリプトです。
下記のコマンドをmenu.pyに記述し、nukeを再起動すれば、ドッキングするための
メニューが作成されます。

import nuke
from nukescripts import panels
import sampleWindow1 as sw1
panels.registerWidgetAsPanel('sw1.MyWindow', 'MyWindowTitle', 'MyWindowID')

ここでmenu.pyとregisterWidgetAsPanelコマンドについて、説明したいと思います。

registerWidgetAsPanel コマンド

このコマンドはUI(Widgetクラス)をドッキングさせるコマンドを生成し、パネルメニューに登録するものです。

参考にしたのは下記のURLなのですが…

http://docs.thefoundry.co.uk/nuke/63/pythondevguide/custom_panels.html#dockable-pyside-widgets

気をつけなければいけないのが、1つ目の引数に指定するクラスを、オブジェクトではなく
文字列で指定しなければいけない所です。

ということはパネルメニューから実行する際には、クラス名を、eval関数のように
pythonコマンドを文字列として扱うような形で実行することになります。

したがって引数に指定するクラスをあらかじめグローバルにインポートしておく必要があります。

menu.pyの役割

そこで重要になってくるのがmenu.pyファイルです。

menu.pyはinit.pyファイル同様に.nukeフォルダ直下に作成することで
Nuke起動時にそれらに書かれたコマンドを実行させることができる特殊なファイルです。

さらにmenu.pyでインポートしたファイルや記述した関数/クラスは
グローバルに宣言され他のスクリプトから自由にアクセスできるようになります。

上記コマンドはこれを利用しています。

あらかじめmenu.pyの中でsampleWindow1をグローバルにインポートしておくことで
メニュー化された後でも、特にインポートなどを必要とせずに、クラスが実行できるようにしています。

ということで早速Nukeを起動し、完了したらパネルメニューを確認してください。
下図のように無事メニューが登録されていれば実行してみてください。

下図のようなUIが作成されれば成功です。

以上でUIドッキングは終了です。


独立したウインドウを立ち上げる

次に紹介するのが独立したウインドウで立ち上げる方法です。
独立したといっても下図のような普通のUIです。
これをNukeウインドウの上部のメニューから実行できるようにしましょう。

では始めたいと思います。
まず1つ目のスクリプトと同様に、windowのクラスを作成します。
今回は独立したUIを作成するのでクラスに継承させるオブジェクトは
QMainWindowを使用します。

下記のコマンドをスクリプトパスの通っている.nukeフォルダ直下に
sampleWindow2.pyという名前で保存します。

# -*- coding: utf-8 -*-
 
from PySide import QtCore, QtGui
from PySide.QtUiTools import QUiLoader
 
class MyWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
 
        # 親のオブジェクト(NukeWindow自体のオブジェクト)を取得
        parentUI = QtGui.QApplication.activeWindow()
 
        # 取得したオブジェクトをセットします
        QtGui.QMainWindow.__init__(self, parentUI)
 
        # .uiファイルをロードしオブジェクト化し、ウインドウにセットします
        loader = QUiLoader()
        uifile = 'C:/nuke/sample.ui'
        self.ui = loader.load(uifile)
        self.setCentralWidget(self.ui)

今回の部分では下記のコマンドがとても重要になります。
これはUIがNukeウインドウに隠れなくするための処理です。

parentUI = QtGui.QApplication.activeWindow()
QtGui.QMainWindow.__init__(self, parent = parentUI)

これはmayaで使用されているsibokenモジュールの親オブジェクトを取得する方法と同じで
このコマンドでNukeのメインウインドウのオブジェクトを取得しています。

試しに下記のコマンドをスクリプトエディタで実行してみてください。Nukeウインドウの
タイトル名が取得できると思います。

import PySide.QtGui as QtGui
print QtGui.QApplication.activeWindow().windowTitle()

これをparentに指定することでUIがNukeウインドウの後ろに隠れなくなります。
後はこれを上部のメニューに登録するだけですね。

menu.pyに下記のコマンドを記述します。

import nuke
import sampleWindow2 as sw2
 
def showWindow():
    win = sw2.MyWindow()
    win.show()
 
menubar = nuke.menu('Nuke')
menubar.addCommand('MyMenu/MyWindow', showWindow)

では再起動してみましょう。
下図のようなメニューが作成されていれば、続けて実行してください。

UIが作成されたでしょうか。後はNukeのウインドウをクリックした時に
後ろに隠れなければ成功です。


最後に、

PySide、使いこなそうと思うと色々大変ですね。学習も基本的には英語が中心になりますし
難解な仕様書を読み解かなければいけません。僕も日々開発の方々に助けられながら勉強しています。

ただし使いこなせればUIの表現の幅がとても広がるので、覚えるだけの価値は十分有ると思います。
皆さんもぜひチャレンジしてください!!


※免責事項※
本記事内で公開している全ての手法・コードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任でご使用ください。

Pocket

コメント

コメントはありません

コメントフォーム

コメントは承認制ですので、即時に反映されません。ご了承ください。

*