MPxContext

このトピックでは、旧式の既定ビューポート(Legacy Default Viewport)のコンテキストの作成に使用される API クラスとインタフェースについて説明します。ビューポート 2.0 (Viewport 2.0)でツール コンテキストを使用する方法については、「3.11 ツール コンテキスト」を参照してください。

MPxContext クラスを使用して、ユーザ独自のコンテキストを作成できます。

Maya アプリケーションでは、コンテキストを作成する特殊なコマンドでコンテキストを実現します。このため、コンテキストはコマンドで作成と修正ができ、動作や外観を定義する状態を持つという意味で、Shape に似ています。MPxContext のサブクラス化によってコンテキストを作成する場合は、MPxContextCommand でサブクラス化してコマンドを定義する必要もあります。これについては以下で説明します。

以下は、ユーザが描いた SGI® OpenGL® セレクション ボックスを使用して単純な選択を行う marqueeTool のサンプルです。簡潔にするため、ヘッダ ファイルは省略しました。完全なサンプルについては、Developer Kit インストールの devkitBase/devkit/plug-ins フォルダにあるサンプル コードを参照してください。

const char helpString[] =
    "Click with left button or drag with middle button to select";
class marqueeContext : public MPxContext
{
public:
    marqueeContext();
    virtual void toolOnSetup( MEvent & event );
    virtual MStatus doPress( MEvent & event );
    virtual MStatus doDrag( MEvent & event );
    virtual MStatus doRelease( MEvent & event );
    virtual MStatus doEnterRegion( MEvent & event );

MPxContext のメソッドには、オーバーライドされない限り使用される既定のアクションがあります。したがって、定義する必要があるメソッドは、作成したコンテキストの適切な動作に必要なものだけです。それぞれのメソッドが実行することについて以下で説明します。

private:
    short start_x, start_y;
    short last_x, last_y;
    MGlobal::ListAdjustment listAdjustment
    M3dView view;
};
marqueeContext::marqueeContext()
{
    setTitleString ( "Marquee Tool" );
}

コンストラクタで、このツールの選択時に UI に表示されるタイトルが設定されます。

void marqueeContext::toolOnSetup ( MEvent & )
{
    setHelpString( helpString );
}

ツールが選択されるとこのメソッドがコールされ、ユーザ ヘルプ情報がプロンプト ラインに出力されます。ユーザはこれを見て、必要となる初期化を実行できます。

MStatus marqueeContext::doPress( MEvent & event )
{

このメソッドは、ツールが選択された後、マウス ボタンを押したときにコールされます。MEvent オブジェクトには、ユーザがクリックした座標など、ユーザのマウス ダウン イベントに関連する情報が含まれます。

    if (event.isModifierShift() || event.isModifierControl() ) {
        if ( event.isModifierShift() ) {
            if ( event.isModifierControl() ) {
                // both shift and control pressed, merge new selections
                listAdjustment = MGlobal::kAddToList;
            } 
            else 
            {
                    // shift only, xor new selections with previous ones
                    listAdjustment = MGlobal::kXORWithList;
            }
        } 
        else if ( event.isModifierControl() ) {
                // control only, remove new selections from the previous list
                listAdjustment = MGlobal::kRemoveFromList; 
        }
    }
    else
        listAdjustment = MGlobal::kReplaceList;

選択のモードは、押されているモディファイア キーによって変化します。マウスアップ イベントによって、押されている場合はどのモディファイア キーが押されているかが判断され、それに従って選択の種類が調整されます。

     event.getPosition( start_x, start_y );

選択したものの位置が判断されます。このメソッドで、画面の座標が返されます。

    view = M3dView::active3dView();
    view.beginGL();

アクティブ ビューが判断され、OpenGL レンダリングが有効になります。

    view.beginOverlayDrawing();
    return MS::kSuccess;
}
MStatus marqueeContext::doDrag( MEvent & event )
{

このメソッドは、マウス ボタンを押したまま画面内でカーソルをドラッグしている間にコールされます。

    event.getPosition( last_x, last_y );
    view.clearOverlayPlane();

このメソッドがコールされるたびに、オーバーレイ プレーンがクリアされてから新しいセレクション ボックスがレンダーされます。

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluOrtho2D(
        0.0, (GLdouble) view.portWidth(),
        0.0, (GLdouble) view.portHeight() );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glTranslatef(0.375, 0.375, 0.0);

アクティブ ビューにレンダリングが正しく表示されるよう、ビューの変換が設定されます。

    glLineStipple( 1, 0x5555 );
    glLineWidth( 1.0 );
    glEnable( GL_LINE_STIPPLE );
    glIndexi( 2 );

次に線の種類が選択されます。

    // Draw marquee
    //
    glBegin( GL_LINE_LOOP );
    glVertex2i( start_x, start_y );
    glVertex2i( last_x, start_y );
    glVertex2i( last_x, last_y );
    glVertex2i( start_x, last_y );
    glEnd();

セレクション ボックスが描画されます。

    #ifndef _WIN32
        glXSwapBuffers(view.display(), view.window() );
    #else
        SwapBuffers(view.deviceContext() );
    #endif

バッファがスワップされます。

    glDisable( GL_LINE_STIPPLE );

最後に、線を描画するためのモードが無効になります。

    return MS::kSuccess;
}
MStatus marqueeContext::doRelease( MEvent & event )
{

このメソッドは、マウス ボタンを放したときにコールされます。

    MSelectionList incomingList, marqueeList;
    MGlobal::ListAdjustment listAdjustment;
    view.clearOverlayPlane();
    view.endOverlayDrawing();
    view.endGL();

すべての OpenGL レンダリングが完了したので、オーバーレイ プレーンがクリアされ、アクティブ ビューの OpenGL レンダリングがオフに切り替わります。

    event.getPosition( last_x, last_y );

これにより、マウス ボタンを放した場所の座標が決まります。

    MGlobal::getActiveSelectionList(incomingList);

現在のセレクション リストが取得され、後で使用するためにコピーが保存されます。

    if ( abs(start_x - last_x) < 2 && abs(start_y - last_y) < 2 )
       MGlobal::selectFromScreen( start_x, start_y, MGlobal::kReplaceList );

最初と最後の座標が同じである場合は、バウンディング ボックスによる選択ではなく、クリックによる選択が実行されたことになります。

    else
        // Select all the objects or components within the marquee.
        MGlobal::selectFromScreen( start_x, start_y, last_x, last_y,
            MGlobal::kReplaceList );

バウンディング ボックスによる選択が実行されます。

    // Get the list of selected items
    MGlobal::getActiveSelectionList(marqueeList);

選択されたオブジェクトのリストが取得されます。

    MGlobal::setActiveSelectionList(incomingList, \
        MGlobal::kReplaceList);

元のセレクション リストが復元されます。

    MGlobal::selectCommand(marqueeList, listAdjustment);

元のセレクション リストがモディファイアと選択されたオブジェクトによって修正されます。

    return MS::kSuccess;
}
MStatus marqueeContext::doEnterRegion( MEvent & )
{
    return setHelpString( helpString );
}

このメソッドは、いずれかのモデリング ビューにマウスを移動するたびにコールされます。

class marqueeContextCmd : public MPxContextCommand
{
    public: 
        marqueeContextCmd();
        virtual MPxContext* makeObj();
        static void* creator();
};