マニピュレータとノードのやり取り
 
 
 

マニピュレータはノード上のプラグとやり取りを行い、その値を設定して、マニピュレータの値もプラグの値に対して適切に設定します。

マニピュレータとノードのやり取りは、単純な 1 対 1 の関係、またはより複雑な変換関数を使用して行われます。以下は、ノードとマニピュレータのやり取りを説明する図です。

図中のコンバータは、ノード上のプラグとマニピュレータ値のやり取りを管理するメカニズムです。矢印は情報の流れる方向を表します。それぞれのコンテナ マニピュレータには 1 つのコンバータがあり、コンテナの子マニピュレータとその影響を受けるプラグの間のインタフェースになります。

コンバータとベース マニピュレータには、スクエアのボックスで表されている多くのデータ項目があります。子マニピュレータ値に関連する、コンバータの項目は、converterManipValue 項目と呼ばれ、ノード プラグ値に関連するコンバータの項目は converterPlugValue 項目と呼ばれます。

ベース マニピュレータの項目は manipValue 項目と呼ばれます。一部の manipValue 項目は、マニピュレータの可動性に直接関係します。たとえば MFnDiscManip::angleIndex は、DiscManip の回転可動性に直接関係します。

その他の manipValue 項目はマニピュレータの可動性に関係しませんが、MFnDiscManip::centerIndex、MFnDiscManip::axisIndex など、マニピュレータの位置や向きに関する重要な情報を提供します。

それぞれの converterManipValue 項目と converterPlugValue 項目には整数インデックスがあり、その項目が一意に識別されるようになっています。ベース マニピュレータのそれぞれの manipValue 項目にも整数インデックスがあり、その項目が一意に識別されるようになっています。

注:converterManipValue 項目とベース マニピュレータの manipValue 項目に 1 対 1 で対応しており、対応する項目は同じ整数インデックスを共有します。converterPlugValue 項目、およびマニピュレータが影響するノードのプラグにも 1 対 1 の対応があります。

図から分かるように、converterManipValue 項目と converterPlugValue 項目の 1 対 1 の関係は直接的です。

converterManipValue 項目と converterPlugValue 項目の複雑な変換は、変換関数を通して実行されます。この関数では、任意の数の converterPlugValue 項目か converterManipValue 項目を使用し、対応する converterManipValue 項目か converterPlugValue 項目の値を計算します。

1 対 1 の関係

converterManipValue 項目と converterPlugValue 項目の間の 1 対 1 の関係は、MFnManip3D から派生したマニピュレータ クラスのメソッドを使用して確立されます。コネクトするプラグに対応するメソッドとデータ型は以下のとおりです。

このメソッドは、上で説明した connectToDependNode メソッドからコールする必要があります。たとえば footPrintManip では以下のようになっています。

MStatus footPrintLocatorManip::connectToDependNode
 (const MObject &node)
{
 ...
 MFnDistanceManip distanceManipFn(fDistanceManip);
 MFnDependencyNode nodeFn(node);
 MPlug sizePlug = nodeFn.findPlug("size", &stat);
 if (MStatus::kFailure != stat) {
 distanceManipFn.connectToDistancePlug(sizePlug);
 ...
 finishAddingManips();
 MPxManipContainer::connectToDependNode(node);
 }
 return stat;
} 

変換関数

変換関数は、マニピュレータ値とプラグ値との変換に使用します。これらはコールバック メソッドとして実装されています。変換関数を使用するマニピュレータの簡単な例としては、プラグにコネクトされた DiscManip(タイプ MFnUnitAttribute::kAngle のアトリビュートに関連します)を持つコンテナ マニピュレータがありますが、これは disc マニピュレータの回転を取り、その回転を 10 倍にします。変換関数は、MFnDiscManip::angleIndex で MPxManipContainer:: getConverterManipValue を使用して、その角度を 10 倍にします。

変換関数は、マニピュレータの位置がオブジェクトの位置に影響される場合、またはマニピュレータのグループを特定の方法で一緒に移動する場合に非常に便利です。変換関数を使用しないと、マニピュレータを 1 単位として一緒に移動できず、マニピュレータの特定コンポーネントは空間の原点か固定位置に残ります。

注:FreePointTriadManip で位置を指定する場合、または PointOnCurveManip でカーブに沿ったパラメータを指定する場合、変換関数は必要ありません。PointOnCurveManip とともに移動する DiscManip がある場合は、変換関数を使用して、位置と法線に関する情報を DiscManip に与える必要があります。

変換コールバック メソッドには、manipToPlug および plugToManip という 2 種類があります。

plugToManip

plugToManip 変換コールバックは、さまざまな converterPlugValue 項目から converterManipValue 項目の値を取得するために使用します。このコールバックは、すべての converterPlugValue 項目にアクセスし、converterManipValue 項目の値を返します。

manipToPlug

manipToPlug 変換コールバックは、さまざまな converterManipValue 項目から converterPlugValue 項目の値を取得するために使用します。このコールバックは、すべての converterManipValue 項目にアクセスし、converterPlugValue 項目の値を返します。

一般的に、manipToPlug 変換はあまり使用しません。converterPlugValue と converterManipValue の使用に加えて、DAG パスなどのクラスデータを使用すると便利なことがあります。fNodePath を使用してノード変換を計算する方法の例については、footPrintManip を参照してください。コンポーネント上で操作するマニピュレータについては、最初のコンポーネントの位置を保存しておくのも便利かもしれません(この方法の例については、componentScaleManip を参照)。

MManipData

変換コールバック メソッドは、MManipData というデータ型を返します。MManipData では、マニピュレータ変換関数から返されたマニピュレータ データがカプセル化されます。これは、単純なデータか複雑なデータを表します。MManipData 上の単純なデータ メソッドは、bool、short、long、unsigned、float、および double を表すために使用します。

注:単純データ型に関連するアトリビュートが、距離、角度、時間など、高いレベルになることがあります(たとえば MFnUnitAttribute::kAngle、MFnUnitAttribute::kDistance、MFnUnitAttribute::kTime)。

MManipData は、行列、カーブ、データの配列など、MFnData またはその派生クラスによって作成された複雑なデータ型を表すためにも使用します。

サンプル プラグインの footPrintManip には、startPointCallback という plugToManip 変換コールバックの例が含まれています。startPointCallback は MManipData を返し、これは MFnNumericData が作成する MObject に設定されています。

class footPrintLocatorManip : public MPxManipContainer
{
public:
 ...
 MManipData startPointCallback(unsigned index) const;
 MVector nodeTranslation() const;
 MDagPath fDistanceManip;
 ...
};
MManipData footPrintLocatorManip::startPointCallback
 (unsigned index) const
{
 // The index is the startPointIndex that is
 // specified in addPlugToManipConversionCallback,
 // but it is not necessary to use this in the callback.
 MFnNumericData numData;
 MObject numDataObj =
 numData.create(MFnNumericData::k3Double);
 MVector vec = nodeTranslation();
 numData.setData(vec.x, vec.y, vec.z);
 return MManipData(numDataObj);
}
MStatus footPrintLocatorManip::connectToDependNode
 (const MObject &node)
{
 ...
 unsigned startPointIndex =
 distanceManipFn.startPointIndex();
 addPlugToManipConversionCallback(
 startPointIndex, 
 (plugToManipConversionCallback) startPointCallback);
 ...
}