チュートリアル / Maya API入門チュートリアル
第3回:アトリビュート値の取得と設定
- Maya
- ゲーム
- コラム
- スクリプト・API
- チュートリアル
- 学生・初心者
- 映画・TV・アニメ
今回はコマンドプラグインでノードのアトリビュート値の取得と設定を行ってみたいと思います。
アトリビュートは1つのノードタイプに複数存在し、ノードを構成する重要な要素です。アトリビュートに設定された各値でノードの振る舞いを決定します。
ノードのアトリビュートには様々なタイプがありますが、基本的なtransformノードのアトリビュート値の操作をご紹介します。
サンプルとしてコマンドプラグインのソースコードを用意しましたので内容を確認してみてください。
MFnTransformによるtransformノードの移動値の取得と設定
transformノードはシーン中での移動値、回転値、スケール値のアトリビュートを備えたDAG(Directed Acyclic Graph)ノードで、通常は階層の子ノードとしてmeshノード等のシェイプノードを持ちます。シェイプノードが持つポリゴン等の各頂点のローカル座標をtransformノードで変換してシーンでのポリゴンの配置を決定します。
Maya APIではこのtransformノードのためにMFnTransformというクラスが用意されています。移動値はこのクラスを使って取得することができます。サンプルコードを見てみましょう
MStatus testSampleAttr::doIt( const MArgList& )
{
MStatus status;
MSelectionList slist;
MGlobal::getActiveSelectionList( slist );
for (unsigned int i = 0; i < slist.length(); i++ ) {
MObject nodeObj;
slist.getDependNode( i, nodeObj );
if ( nodeObj.apiType() == MFn::kTransform) {
////////////////////////////////////////////////////////////////////
//MFnTransformによるtranslate値の取得/設定
MFnTransform transFn( nodeObj );
//translate値の取得
MVector translateValue = transFn.getTranslation( MSpace::kObject );
cout << "MFnTransform getTranslation: " << translateValue << endl;
//translate値の設定
transFn.setTranslation( MVector(2.0, 3.0, 4.0), MSpace::kObject );
}
}
return status;
}
ここでは選択したノードがtransformノードかを識別するために、MObjectのnodeObj.apiType()とMFn::kTransformで比較してチェックをしています。このMObjectはMaya APIでよく扱う汎用的な基本オブジェクトです。ノードやアトリビュート等はMObjectで扱うことができます。
移動値のtranslateアトリビュートの値はMFnTransformのgetTranslation()で取得できます。戻り値のMVector translateValue()には(x, y, z)の値が入ります。
例えばpCube1が[x=1.0, y=2.0, z=3.0]に配置されている場合、結果としてOutput Windowには以下のように表示されるでしょう。
Output Window出力結果 例:
MFnTransform getTranslation: [1, 2, 3]
また移動値をセットするにはMFnTransformのsetTranslation()が使用できます。
今回はローカル座標の値を取得/設定していますが、ワールド座標で操作することもできます。値の取得/設定をするtransformノードに親ノードがある場合等でワールド座標の値で操作したい場合が考えられます。この場合はMSelectionListのgetDependNode()ではく、getDagPath()でMDagPathを取得します。そしてgetTranslation()/setTranslation()にはローカル座標を示すMSpace::kObjectではなく、ワールド座標を示すMSpace::kWorldを引数に指定します。
MPlugによるアトリビュート値の取得と設定
上ではtransformノードを扱うのに便利なMFnTransformクラスを使いましたが、この様なクラスは全てのノードタイプに用意されているわけではありません。よりシンプルにノードのアトリビュート値を操作するにはMPlugを使って直接アトリビュートにアクセスにすることができます。
ここではtransformノードのtranslateXアトリビュートを指定したいと思います。
アトリビュート名を明確に調べるにはいくつか方法があります。簡単な方法としてはMayaのアトリビュートエディタを直接手動で数値を変更して、スクリプトエディタに出力される内容を確認する方法です。
アトリビュートエディタでTranslateのX値を変更すると、スクリプトエディタに値を編集した結果が表示されます。 “translateX”がアトリビュート名と判断できます。
その他MELコマンドのlistAttrでノードが持つアトリビュートのリストを表示して当たりを付ける方法があります。結果として表示されたアトリビュートのリストの中に “translateX”が見つけることができます。
アトリビュートエディタに表示されない、または直接編集をすることが難しいアトリビュートの場合は調べる方法として有効だと思います。
また各ノードのリファレンスページを参照してアトリビュート名を確認するのも有効です。
Mayaのヘルプページからノードの仕様を確認する事ができます。アトリビュートの名前やタイプが確認できます。
https://help.autodesk.com/cloudhelp/2022/JPN/Maya-Tech-Docs/Nodes/transform.html
アトリビュート名にはロングネームとショートネームが存在し、”translateX"がロングネーム、”tx”はショートネームです。どちらのネームタイプを使っても問題ありません。
サンプルコードでは最初にMFnDependencyNodeクラスを使ってノードオブジェクトに対するハンドルを作り、MFnDependencyNodeのメンバ関数findPlug()で操作したいアトリビュートを指定します。
//MFnDependencyNodeでMPlugからtranslateX値を取得/設定
MFnDependencyNode depFn( nodeObj );
////MPlugによるアトリビュート値の取得
MPlug translateXPlug = depFn.findPlug( "translateX" );
double translateXValue;
translateXPlug.getValue( translateXValue );
cout << "MPlug getValue translateX: " << translateXValue << endl;
//MPlugによるアトリビュート値の設定
translateXPlug.setValue( 3.0 );
findPlug()でMPlugのオブジェクトを取得後にgetValue()でアトリビュート値の取得ができます。
Output Window出力結果 例:
MPlug getValue translateX: 2
またアトリビュート値を設定する場合はsetValue()を使います。
ちなみにMFnTransformでもfindPlug()を使うことができます。これはMFnTransformがMFnDependencyNodeを継承しているからです。
その他、アトリビュートエディタにはチェックボックスとして表示されているアトリビュートもありますが、これも同じようにMPlugのgetValue()/setValue()を使うことができます。以下はDisplayLocalAxisアトリビュートに値を設定しています。アトリビュートタイプはBoolです。
//DisplayLocalAxisアトリビュートをオン
MPlug displayLocalAxisPlug = depFn.findPlug( "displayLocalAxis" );
displayLocalAxisPlug.setValue( true );
マトリックス アトリビュートの取得と設定
transformノードはトランスフォーメーション マトックスのアトリビュートも備えています。こちらもMPlugを使って値を取得することができます。アトリビュート名は”matrix”でローカル座標のマトリックスです。
//MPlugによるトランスフォームマトリックス値の取得
MFnDependencyNode depFn2( nodeObj );
MPlug matrixPlug = depFn2.findPlug( "matrix" );
MObject matrixObj;
matrixPlug.getValue( matrixObj );
cout<< "matrixObj.apiTypeStr(): " <<matrixObj.apiTypeStr()<<endl;
MFnMatrixData matDataFn( matrixObj );
MMatrix matrixValue = matDataFn.matrix();
cout << "MPlug getValue matrix:" << matrixValue << endl;
まずMPlugのgetValue()でMObjectを取得します。MObjectが保持しているデータのタイプはapiTypeStr()でも調べる事もできます。この場合はkMatrixDataが出力されるはずです。
続いてMFnMatrixDataのmatrix()で、MMatrixとしてローカル トランスフォーメーション マトリックスの値が取得できます。MMatrixにはdoubleの[4][4]の値が格納されています。
Output Window出力結果 例:
MPlug getValue matrix:[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [3, 3, 4, 1]]
ではマトリックス値を設定する場合はどうでしょうか。
//MFnTransformによるマトリックス値の設定
MFnTransform transFn2( nodeObj );
MMatrix m;
m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0;
m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0;
m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 0.0;
m[3][0] = 2.0; m[3][1] = 3.0; m[3][2] = 4.0; m[3][3] = 1.0;
MTransformationMatrix trMat( m );
transFn2.set( trMat );
シンプルにMPlugのsetValue()を使いたいところですが、transformノードの親であるdagNodeのリファレンスページを確認すると、matrixアトリビュートは値の直接の入力を許可していません。
https://help.autodesk.com/cloudhelp/2022/JPN/Maya-Tech-Docs/Nodes/dagNode.html#attrmatrix
これはMELコマンドのsetAttrやノード接続による値の入力も同様です。このため値を設定するためにはMFnTransformクラスのset()を使用します。
今回はノードのアトリビュートの操作についてご紹介しました。transformノードでの説明でしたが、他のノードタイプのアトリビュートでも扱いは同様です。各ノード専用のファンクションクラスやMPlugでノードのアトリビュート値の操作が可能です。
次回はポリゴンメッシュのデータの取得の方法についてご紹介したいと思います。