データ ブロックを使用する

Maya がディペンデンシー グラフ ノードの compute() メソッドを呼び出す場合、入力と出力のすべてのアトリビュートの値を保存する MDataBlock オブジェクトを渡します。このページでは、MPxNode::compute() 実装による、このデータ ブロックでの属性値の読み取りと書き込みの方法について説明します。

最初、ノードでデータの送受信を行うと、少し複雑に感じることがあります。しかし、このように複雑だと感じるため、シーンの後ろにある、ディペンデンシー グラフの処理全体に必要不可欠な高速メカニズムを使用することが許可されています。

データ ブロックおよびそれに含まれるすべてのデータは、ノードの compute() メソッド実行中のみ有効であることに注意してください。compute() メソッドの終了後は、データ ブロックへのポインタまたは使用したいかなるデータも決して保持しないでください。

データ ハンドル

データ ハンドルとは、アトリビュートまたはプラグなど、ノードのデータの特定の部分を参照するデータ ブロックへのリファレンスです。データ ブロック内でアトリビュート値の読み取りまたは書き込みを実行するには、MDataHandle オブジェクトを作成して、処理するアトリビュートにアクセスできるように設定し、MDataHandle インタフェース内の関数を使用して、特定のデータ型で表示されるデータ値を取得または設定する必要があります。

次のコードでは、データ ブロック内でアトリビュート値を読み取りおよび書き込みできるように、MDataHandle オブジェクトを作成して使用する方法を示しています。

MStatus myNode::compute( const MPlug& plug, MDataBlock& data )
{
    ...
    MStatus status = MS::kSuccess;

    // get a handle on an input attribute
    MDataHandle inputDataHandle = data.inputValue( myInAttributeName, &status );
    if (status != MStatus::kSuccess) { /* handle the error */ }

    // retrieve its value as a float:
    float& inAttributeValue = inputDataHandle.asFloat();

    ... // perform your node's computations, and come up with a result

    // get a handle on an output attribute
    MDataHandle outputDataHandle = data.outputValue( myOutAttributeName, &status );
    if (status != MStatus::kSuccess) { /* handle the error */ }

    // assign our computed result to the output attribute
    outputDataHandle.set( result );

    ...
}

また、次の省略した方法では、エラーをチェックせずに値を取得します。

    // retrieve the value of an input handle as a float:
    float& inAttributeValue = data.inputValue( myInAttributeName ).asFloat();

アトリビュートかプラグ上のデータの取得や設定に使用する型は、アトリビュートの型と一致する必要があります。たとえばアトリビュートを整数(int)型アトリビュートとして宣言した場合は、float、行列(matrix)、ショート(short)として取得や設定を行うデータ ハンドルを使用できません。整数として取得や設定を行う必要があります。データの型キャストまたは再解釈を実行する必要がある場合は、値の取得後に実行してください。

データ クリエータ

データ クリエータは、データ ブロック、ほとんどの場合はノードの出力プラグに入れるデータの作成に使用するクラス群です。データ クリエータは、整数や浮動小数点値などの単純なデータ型には必要ありませんが、メッシュ シェイプや NURBS サーフェスなどの重いデータに必要になります。

これらのクラスを使用すると、ディペンデンシー グラフ接続に沿ったデータの修正と転送をより能率的に実行できます。データ クリエータ クラスは、MFnData のサブクラスです。メッシュ シェイプや NURBS サーフェスなど、シェイプ ノードにも対応する重いデータを作成するデータ クリエータ クラスでは、データ型に関連する MFnDependencyNode サブクラスを使用してデータ ブロック項目にデータを入れます。たとえば MFnMeshData クラスを使用して、新しいメッシュ データ ブロック項目を作成し、MFnMesh クラスを使用して項目に頂点とポリゴンを入れます。

たとえば、次の shellNode/shellNode.cpp サンプルのコードは、出力アトリビュートにメッシュを埋める方法を示しています。

MStatus shellNode::initialize()
{
    MFnTypedAttribute typedFn;
    MStatus stat;

    // the output mesh attribute is initialized as an MFnTypedAttribute, with type MFnData::kMesh.
    outMesh = typedFn.create( "outMesh", "o", MFnData::kMesh );
    typedFn.setStorable(false);
    typedFn.setWritable(false);
    stat = addAttribute( outMesh );
    ...
}

...

MStatus shellNode::compute( const MPlug& plug, MDataBlock& data )
{
    ...
    // use the data creator to create a new data object of the right type:
    MFnMeshData dataCreator;
    MObject newOutputData = dataCreator.create(&returnStatus);
 
    ... // compute the vertices and polygons for the new output mesh

    // create a new mesh using the MFnMesh function set, and store the result
    // in the data object created above:
    MFnMesh meshFn;
    mesh= meshFn.create(
        n,         // number of vertices
        np,        // number of polygons
        vertices,  // The points
        pcounts,   // # of vertex for each poly
        pconnect,  // Vertices index for each poly
        newOutputData, // Dependency graph data object
        &returnStatus
    );

    // store the data object in the output attribute:
    outputHandle.set(newOutputData);
    ...
}

一部の操作は、データ ブロック項目によって動作が異なることがあります。シェイプ関連のディペンデンシー ノード関数セット クラスを使用すると、グラフの別のノードへの接続から入力されたデータ ブロック項目にアクセスしたり、ノード内でローカルに作成されたデータ ブロック項目にアクセスしたりすることができるからです。

注:MFnMesh::getPoint() など、ワールド空間情報を返す操作はすべて、シェイプ ノード以外からのデータ ブロック項目に適用すると無効になります。変換からワールド空間の位置を計算できるようにするには、シェイプ ノードが必要です。このようなメソッドを使用する場合は注意してください。