Maya は Digia のカスタマイズ バージョンの Qt フレームワークを使用し、プラグインでの Qt の使用に必要なすべての独自バージョンのライブラリとヘッダー ファイルが付属しています。Linux と OS X では、ライブラリは Maya の lib フォルダにあります。Windows では、リンク ライブラリが Maya の lib フォルダ、DLL が Maya の bin フォルダにあります。すべてのプラットフォームにおいて、ヘッダー ファイルは、圧縮アーカイブ(例: qt-5.6.1-include.tar.gz)として Developer Kit インストールの include フォルダ内に含まれています。Qt プラグインの作業を開始する前に、圧縮アーカイブを書き出し権限があるフォルダに解凍し、そのフォルダが他のフォルダの前にくるようにインクルード パスを指定します。
Qt Designer を使用して Maya のカスタム UI を作成できます。(Windows および Linux) Qt Designer は Maya と一緒にインストールされます。(Mac OS X) Qt Designer を Qt Development Tools の Web サイトから直接ダウンロードできます。または、ソースから Qt をビルドすることもできます。
qmake または Qt Designer を取得するには、システムに Digia の 標準バージョンの Qt をインストールするか、Autodesk のオープン ソース Web サイト(http://www.autodesk.com/lgplsource)からカスタマイズされた Qt ソースをダウンロードしてビルドします。後者の方法を選択した場合、Maya のサポート対象のプラットフォームで Qt を設定、ビルド、インストールする方法が記載されたテキスト ファイルを参照できます。
独自の Qt アプリケーションを一から作成するには、独自の QCoreApplication または QApplication のインスタンスを作成してそのアプリケーションのイベント ループを処理できるようにする必要があります。代わって、Maya プラグインの作成には、Qt の qApp マクロで読み出せる Maya 独自のアプリケーション オブジェクトを使用します。以下のサンプル コードでは、qApp マクロを使用して Maya のアプリケーション名を読み出しています。
QCoreApplication* app = qApp; if (app) { cout << "Application name is '" << app->applicationName().toStdString() << "'" << endl; }
Qt を使用した新規ウィンドウやダイアログの作成は、Qt の標準的なアプリケーションの作成と同じ方法で行います。開発キットの helixQtCmd プラグインにごく単純なサンプルが用意されています。このプラグインには、Qt ベースのボタンを作成する helixQt コマンドがあります。このボタンを押すと、常に API コールを使用してらせん状のカーブが作成されます。
このボタンは、カーブの作成を処理するために createHelix() スロットを追加した通常の Qt pushButton です。
class HelixButton : public QPushButton { Q_OBJECT public: HelixButton(const QString& text, QWidget* parent = 0); virtual ~HelixButton(); public slots: void createHelix(bool checked); };
helixQt コマンドを実行すると、常に、まずそのボタンの有無が確認されます。ボタンがない場合は作成し、クリックした信号をその createHelix スロットに接続して、ボタンをクリックしたときにらせんを作成するコードが必ず実行されるようにします。
QPointer HelixQtCmd::button; MStatus HelixQtCmd::doIt(const MArgList& /* args */) { if (button.isNull()) { button = new HelixButton("Create Helix"); button->connect(button, SIGNAL(clicked(bool)), button, SLOT(createHelix(bool))); button->show(); }
ボタンがある場合、このコマンドは、そのボタンを確実に表示して他のウィンドウの後ろに隠れないようにします。
else { button->showNormal(); button->raise(); } return MS::kSuccess; }
Qt を使用して直接作成したコントロールは、通常、Maya の UI コマンドで認識されません。IsUI コマンドではそれらのコントロールはリストされず、button などの特定タイプのコントロールのコマンドではそれらは認識されません。ただし、汎用のコントロール コマンドは例外です。一意の名前を指定してさえいれば、control コマンドを使用してその有無をテストし、表示設定などコントロールに関する基本操作を実行できます。
たとえば、helixQtCmd プラグインの createHelix メソッドでボタンに「myButton」という一意の名前が指定されているとします。
button = new HelixButton("Create Helix"); button->setObjectName("myButton");
その場合、ボタンを非表示にするために以下の MEL スクリプトを使用できます。
if (`control -q -exists myButton`) { control -e -visible false myButton; }
ただし、同じコードで button コマンドを使用しても、動作しません。これは、button コマンドが自身が作成したボタンしか認識しないためです。
if (`button -q -exists myButton`) { // Will always be false. button -e -visible false myButton; // Will never be executed. }
Qt を使用して Maya コマンドで作成した UI 要素に直接アクセスできるようにした方が望ましい場合もあります。MQtUtil API クラスには、Maya のコントロール、レイアウト、ウィンドウ、メニュー項目の基本となる Qt オブジェクトを読み出すためのメソッドが用意されています。たとえば、以下の MEL スクリプトで作成した「myCheckBox」という名前の Maya checkBox コントロールがあるとします。
window; columnLayout; checkBox myCheckBox; showWindow;
MQtUtil クラスを使用して checkBox の QWidget ポインタを読み出し、それにより checkBox の現在の状態を定義することができます。
QWidget* control = MQtUtil::findControl("myCheckBox"); if (control) { QCheckBox* cb = qobject_cast(control); if (cb) { if (cb->isChecked()) { MGlobal::displayInfo("myCheckBox is checked"); } else { MGlobal::displayInfo("myCheckBox is not checked"); } } }
前述の例では、MQtUtil を使用する場合は常に十分な注意が必要であることもわかります。このコードは、Maya の checkBox コマンドで QCheckBox ウィジェットまたは QCheckBox 由来の要素を作成する場合のみ動作します。これは Maya の現行バージョンの場合で、将来的には変更される可能性があります。Qt を使用して Maya のコマンドで作成した UI 要素に直接アクセスするようにコードを記述する場合、Maya の新しいリリースでも確実に意図した通りに動作するか確認するのはユーザ自身の責任になります。
レイアウトは、注意して作成しなければ、さまざまな問題のもとになりかねません。
レイアウトに関するこれらの問題およびその他の問題の詳細については、「MQtUtil」を参照してください。
このセクションの最初で説明したとおり、Maya にはカスタマイズ バージョンの Qt ライブラリとヘッダー ファイルが付属しています。Maya のバージョンのヘッダーを含むフォルダが、システムの他の場所の別の Qt インストールにあるフォルダの前にくるようにインクルード パスを指定し、Maya のバージョンのライブラリを含むフォルダが、他のフォルダの前にくるようにライブラリ パスを指定することが重要です。
Maya インストールに付属している qmake のバージョンを使用することが重要です。qmake の実行後、Qt プラグインのビルドに使用できる Makefile が生成されます。
Maya Developer Kit に付属している Qt プラグインをビルドするには、次の手順に従います。
Maya 開発キットから同じファイルを取得することもできます。
上記の helixQtCmd.* ファイルを helixQtCmd フォルダにコピーします。
$MAYA_LOCATION/bin/qmake helixQtCmd.pro
その結果、Makefile が作成され、プラグインのビルドに使用できるようになります。
生成された Makefile を使用し、次の手順で make を実行します。
Makefile は、末尾に拡張子 .pro が付いている qmake プロジェクト ファイルを必要とします。以下に示す helixQtCmd.pro は、開発キットで helixQtCmd プラグインに用意されているプロジェクト ファイルです。これで、大部分のプロジェクト ファイルは単純な構成であることがよくわかります。
include(qtconfig) TARGET = helixQtCmd HEADERS += helixQtCmd.h SOURCES += helixQtCmd.cpp LIBS += -lOpenMayaUI
TARGET 設定には、プラットフォーム固有の拡張子を除いたプラグインの名前を記述します。
HEADERS 設定には、プラグインの一部であるすべてのヘッダー ファイルの一覧をスペースで区切って記述します。
SOURCES 設定には、プラグインの一部であるすべてのソース ファイルの一覧をスペースで区切って記述します。
既定では、プラグインは Maya の Foundation ライブラリと OpenMaya ライブラリに自動的にリンクされます。他のライブラリが必要な場合は、LIBS 設定に追加します。 ライブラリの名前の前には「-l」を付け、追加ライブラリのディレクトリは「-L」で指定する必要があります。たとえば、次のようになります。
LIBS += -L/usr/local/lib -lxml
Qt のサンプル プラグインは、すべてリリース(非デバッグ)モードでビルドされています。デバッグ用にビルドするには、.pro ファイルで以下の手順に従って qmake のデバッグ構成パラメータをオンにします。
CONFIG += debug
Linux と OS X でのデバッグ用にプラグインをビルドする場合はこれで十分です。ただし、残念ながら、Windows の場合は、デバッグ構成の設定はデバッグ情報付きのプラグインをコンパイルするだけではなく、デバッグ バージョンの Qt ライブラリに強制的にリンクします。このため、Qt ライブラリのリリース バージョンでリンクされた Maya との互換性が失われてしまいます。プラグインに使用する Qt のクラスによっては、Maya にロードできたりできなかったりしますが、ロードされた場合でも、正しく動作しないと思われます。これは、Maya の QCoreApplication またはその他の Qt のグローバル値にアクセスできないためです。この問題を回避するには、debug 構成パラメータを前述のように設定し、以下のコマンドを使用して myPlugin のプラグイン名を置き換えて中間的な makefile をビルドします。
nmake /f Makefile.qt myPlugin.mak
これは特に、プラグイン用の .mak.Debug ファイル(myPlugin.mak.Debug など)を生成します。生成されたファイルを編集してLIBS 行を探し、ファイル名の末尾の d を削除してすべてのデバッグ用の Qt ライブラリを非デバッグ バージョンに置き換えます。たとえば、helixQtCmd.mak.Debug の LIBS 業の冒頭は以下のようになります。
LIBS = /LIBPATH:..\..\lib ..\..\lib\OpenMaya.lib ..\..\lib\Foundation.lib ..\..\lib\OpenMayaUI.lib c:\qt-adsk-5.6.1\lib\QtGuid4.lib c:\qt-adsk-5.6.1\lib\QtCored4.lib`
QtGuid4.lib を QtGui4.lib、QtCored4.lib を QtCore4.lib に置き換えると、以下のようになります。
LIBS = /LIBPATH:..\..\lib ..\..\lib\OpenMaya.lib ..\..\lib\Foundation.lib ..\..\lib\OpenMayaUI.lib c:\qt-adsk-5.6.1\lib\QtGui4.lib c:\qt-adsk-5.6.1\lib\QtCore4.lib`
ここで、変更した .mak.Debug ファイルを使用し、以下のようにプラグインを明示的にビルドします。
nmake /f myPlugin.mak.Debug debug\myPlugin.mll
これでも、Windows の場合はまだ問題が残ります。Qt の QList テンプレート クラスには、Qt オブジェクトを作成、破棄できるインライン メソッドがあります。 このメソッドはインライン化されているため、デバッグ用にビルドしたプラグイン コードによってコールされると、作成または削除したすべてのオブジェクトが Microsoft の C Runtime Library のデバッグ バージョンからメモリ アロケータを使用します。メソッドを Maya 内でコールした場合、C Runtime Library のリリース バージョンが使用されます。したがって、Maya 内でリリース バージョンのランタイム ライブラリを使用してオブジェクト割り当てて、デバッグ バージョンのランタイム ライブラリで削除する、またはその逆の状況が考えられます。ところが、Microsoft の C Runtime Library のリリース バージョンとデバッグ バージョンでは互換性がないため、このような操作を行うとクラッシュしてしまいます。
現在のところ、このような問題の可能性が確認されている Qt クラスはQList だけですが、他の Qt テンプレート クラスでも同様の問題が発生する可能性はあります。これに対する現段階での回避策は、コードに Qt テンプレート クラスを使用しないこと、または Windows ではプラグインのビルドをリリース モードでのみ行うことのいずれかです。