API Guide > Command plug-ins >

# MPxContext

The MPxContext class allows you to create your own context.

The realization of a context in the Maya application is done through a special command which creates the context. In this regard, a context is similar to a shape—it is created and modified by a command and has state which defines its behavior or appearance. When you write a context by subclassing MPxContext, you must also define a command for it by subclassing from MPxContextCommand described in the following.

The following is the marqueeTool example which does simple selection using a user drawn SGI® OpenGL® selection box. For the purposes of brevity, the header files have been left out. See the example code in the devkit/plug-ins directory for the complete example.

    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 );

The methods on MPxContext provide default actions if they are not overridden so you need only define those methods which are necessary for the proper functioning of your context. What each of these methods does is described below.

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

The constructor sets the title that will appear in the UI when this tool is selected.

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

When the tool is selected this method is called to put user help information on the prompt line and so that you can do any initialization that may be required.

    MStatus marqueeContext::doPress( MEvent & event )
    {

This method is called after the tool has been selected and you have pressed a mouse button. The MEvent object contains the relevant information to the user’s mouse down event, such as the co-ordinates the user clicked on.

        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;

Since the mode of selection can be varied by what modifier keys are held down, the mouse up event is checked to see what if any modifiers were down, and then adjusts the type of selection accordingly.

         event.getPosition( start_x, start_y );

The positions of the selection are determined. This method returns screen co-ordinates.

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

This determines the active view and enables OpenGl rendering into it.

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

This method is called while the mouse button is down and you drag the cursor around the screen.

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

Each time this method is called the overlay planes are cleared before rendering the new selection box.

        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);

This sets up the view transformations to make sure that the rendering correctly appears in the active view.

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

Next the line style is selected.

        // 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();

The selection box is drawn.

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

The buffers are swapped.

        glDisable( GL_LINE_STIPPLE );

Finally the special draw mode for the lines is disabled.

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

This method is called when the mouse button is released.

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

All OpenGL rendering is done so the overlay planes are cleared and OpenGL rendering is turned off for the active view.

        event.getPosition( last_x, last_y );

This determines the co-ordinates where the mouse button was released.

        MGlobal::getActiveSelectionList(incomingList);

This gets the current selection list and saves a copy for later use.

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

If the co-ordinates are the same at the beginning and end, then a click-pick was done rather than a bounding box pick.

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

Do a bounding box pick.

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

This gets the list of objects just selected.

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

Restore the original selection list.

        MGlobal::selectCommand(marqueeList, listAdjustment);

Modify the original selection list using your modifier and the selected object’s.

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

This method is called whenever you move the mouse on top of one of the modeling views.

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