チュートリアル / Maya API入門チュートリアル
第2回:コマンドプラグイン
- Maya
- ゲーム
- コラム
- スクリプト・API
- チュートリアル
- 学生・初心者
- 映画・TV・アニメ
前回は開発環境の準備とサンプルプラグインのビルドと実行を試しました。今回は基本的なプラグインタイプであるコマンドプラグインについてご紹介したいと思います。コマンドプラグインを作る事によりMELコマンド群とほぼ同等の機能を作る事ができます。
前回のようにdevkit内にあるサンプルプラグインのパッケージフォルダの中で作業をするのではなく、今回は自身で選んだフォルダの中で環境構築と独自のソースコードのビルドを行ってみたいと思います。
サンプルとしてコマンドプラグインのソースコードを用意しましたので、まずこちらをビルドしてみましょう。
コマンドプラグインのプロジェクトを生成
今回用意したのはコマンドプラグインのソースコード testSample.cppとCMakeファイル CMakeLists.txtです。これら2つのファイルを任意のフォルダに置きます。ビルドをするためにはVisual Studioのプロジェクトファイルが必要となるため、Windowsのコマンドプロンプトで2つのファイルを置いたフォルダに移動し、CMakeでプロジェクトファイルを生成します。
CMakeは以下のように実行します。
>cmake . -B. -G "Visual Studio 16 2019"
フォルダ内にtestSampleCmd.vcxprojとProject.slnファイルが生成されればCMakeは成功です。
エラーが出た場合はWindowsの環境変数にDEVKIT_LOCATIONが設定されているか確認をしてください。
またCMakeについては前回のコラムで説明していますのでそちらも参考にしてください。
プロジェクトファイルはdevkitのサンプルプラグインで生成した物を参考にしてCMakeを使わずに新規で作成する事もできます。
コマンドプラグインのビルドと実行
生成されたProject.slnをVisual Studioで開いてビルドを行います。
ビルドを行うとDebugフォルダにtestSampleCmd.mllが作られます。続いてMayaのPlug-in Managerを開いてtestSampleCmd.mllをロードします。このプラグインは文字列を出力するので、Maya 2022でコマンドを実行する前にWindow->Output Windowを選択してMayaのOutput Windowを開いておきます。
Script Editorで”testSample”コマンドを実行します。
Output Windowに "---------- testSample ----------" と表示されていれば実行は成功です。
ビルドからプラグインコマンドの実行も前回のコラムで説明していますのでそちらも参考にしてください。
コマンドプラグインのソースコード
今回用意したコマンドプラグインのソースコードは非常にシンプルなものです。コマンドプラグインとして形を成す最低限のコードが書かれています。コマンドプラグインではMPxCommandクラスを元に継承させて自身のクラスtestSampleを作ります。
#include <maya/MIOStream.h>
#include <maya/MPxCommand.h>
#include <maya/MFnPlugin.h>
//コマンドのクラス MPxCommandから派生
class testSample : public MPxCommand
{
public:
testSample() {};
~testSample() override;
MStatus doIt(const MArgList& args) override;
static void* creator();
private:
};
testSample::~testSample() {}
void* testSample::creator()
{
return new testSample();
}
//コマンドで実行する内容
MStatus testSample::doIt(const MArgList&)
{
MStatus status;
cout << "---------- testSample ----------" << endl;
return status;
}
//プラグインロード時のイニシャライズ
MStatus initializePlugin(MObject obj)
{
MStatus status;
MFnPlugin plugin(obj, PLUGIN_COMPANY, "1.0", "Any");
status = plugin.registerCommand("testSample", testSample::creator);
if (!status) {
status.perror("registerCommand");
return status;
}
return status;
}
//プラグインアンロード時のアンイニシャライズ
MStatus uninitializePlugin(MObject obj)
{
MStatus status;
MFnPlugin plugin(obj);
status = plugin.deregisterCommand("testSample");
if (!status) {
status.perror("deregisterCommand");
return status;
}
return status;
}
MayaでプラグインをロードするとinitializePlugin()が呼ばれregisterCommand()でコマンド名testSampleがMayaに登録されます。プラグインをアンロードするとuninitializePlugin()が呼ばれderegisterCommand()によりコマンドの登録が解除されます。プラグインのロード、アンロード時に何か他に特別な処理をしたい場合は、このinitializePlugin()/initializePlugin()中に記述することができます。例えばロード時に独自のライセンスチェック等を行うことができるでしょう。
またコマンド実行時にtestSampleクラスのコンストラクタが呼ばれるので、この中で処理を記述することもできます。クラス内のメンバ変数の初期化等に使うことができると思います。
コマンドプラグインのメインとなるのはdoIt()です。基本的にこの中にコマンドとして行いたい処理を記述します。
現状ではcoutで”testSample”の文字列をOutput Windowに出力するだけの単純なコードが書かれています。これを少し変更してみましょう。
MStatus testSample::doIt(const MArgList&)
{
MStatus status;
cout << "---------- testSample ----------" << endl;
//選択中のオブジェクトの名前を出力
MSelectionList slist;
MGlobal::getActiveSelectionList( slist );
for (unsigned int i = 0; i < slist.length(); i++ ) {
MDagPath dagPath;
slist.getDagPath(i, dagPath );
cout << dagPath.fullPathName() << endl;
appendToResult( dagPath.fullPathName() );
}
return status;
}
Mayaのシーンで選択中のオブジェクトの名前を出力するように変更しました。
幾つか使用するクラスが増えたので、ビルドするにはインクルードファイルの追加も必要です。
#include <maya/MSelectionList.h>
#include <maya/MGlobal.h>
#include <maya/MDagPath.h>
MGlobal::getActiveSelectionList()はMayaのシーンで選択中のオブジェクトやノードを取得する事ができます。オブジェクトを取得するためMDagPathで選択リストの内容を受け取ります。
ポリゴンオブジェクトやカーブオブジェクトはDAG(Directed Acyclic Graph)オブジェクトに分類され、階層構造の親子関係を構築する事ができます。DAGオブジェクトはオブジェクトの座標等を含むtransformノードと実際の頂点座標を含むシェイプノードの組み合わせで構成されるのが一般的です。DAGオブジェクトはMDagPathで管理します。
オブジェクトの名前はfullPathName()で取得します。フルパスはDAGオブジェクトが階層を持つ場合でもシーンのルートからのオブジェクトパスを正しく表示できます。
コード変更したコマンドプラグインの実行
それでは再びコードのビルドを行いMayaでプラグインを読み込んで実行してみましょう。
再ビルドを行うには現在ロードしているtestSampleCmd.mllをPlug-in Managerでアンロードする必要があります。ビルドが完了したら再びプラグインをロードします。
MayaでpCube1とpSphere1の2つのオブジェクトを作成し選択をしました。
Script Editorで ”testSample”コマンドを実行すると、Output Windowに |pCube1 と |pSphere1が表示されます。これはシーンのルート階層からのフルパスネームです。
またScript Editorにもオブジェクト名が表示されます。これはappendToResult()が出力をしています。出力結果はコマンドの戻り値としてMELスクリプトで使用することもできます。
サンプルコードに幾つかクラスを追加しましたが、それぞれのクラスの機能については、Maya API Referenceで確認することができます。このクラスリファレンスはプラグイン作成中に頻繁に参照して各クラスの使用の確認に使うことになると思います。
https://help.autodesk.com/view/MAYAUL/2022/ENU/?guid=Maya_SDK_cpp_ref_index_html
また前回のコラムでご紹介したdevkitのサンプルコード群も理解を深める上で役に立つと思います。
今回はコマンドプラグインについてご紹介しました。サンプルコードはシンプルですが、コマンドプラグインの挙動を確かめることができました。
次回はコマンドプラグインでオブジェクトやノードが持つアトリビュート値の操作についてご紹介したいと思います。