API ガイド > マニピュレータ >

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

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

マニピュレータとノードのやり取りは、単純な 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 から派生したマニピュレータ クラスのメソッドを使用して確立されます。接続するプラグに対応するメソッドとデータ型は以下のとおりです。

- MFnFreePointTriadManip::connectToPointPlug (3 doubles)
- MFnDirectionManip::connectToDirectionPlug (3 doubles)
- MFnDistanceManip::connectToDistancePlug (double)
- MFnPointOnCurveManip::connectToCurvePlug (curve)
- MFnPointOnCurveManip::connectToParamPlug (double)
- MFnPointOnSurfaceManip::connectToSurfacePlug (surface)
- MFnPointOnSurfaceManip::connectToParamPlug (2 doubles)
- MFnDiscManip::connectToAnglePlug (double)
- MFnCircleSweepManip::connectToAnglePlug (double)
- MFnToggleManip::connectToTogglePlug (boolean)
- MFnStateManip::connectToStatePlug (long)
- MFnCurveSegmentManip::connectToCurvePlug (curve)
- MFnCurveSegmentManip::connectToStartParamPlug (double)
- MFnCurveSegmentManip::connectToEndParamPlug (double)
- MFnRotateManip::connectToRotatePlug (3 doubles)
- MFnRotateManip::connectToRotateCenterPlug (3 doubles)
- MFnScaleManip::connectToScalePlug (3 doubles)
- MFnScaleManip::connectToScaleCenterPlug (3 doubles)

このメソッドは、上で説明した 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);
        ...
    }