marqueeTool.cpp

//-
// ==========================================================================
// Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+

//
// Marquee selection within a user defined context.
// Draws the marquee using OpenGL.
// Selection is done through the API (MGlobal).
//

#include <maya/MIOStream.h>
#include <math.h>
#include <stdlib.h>

#include <maya/MFnPlugin.h>
#include <maya/MString.h>
#include <maya/MGlobal.h>
#include <maya/M3dView.h>
#include <maya/MDagPath.h>
 
#include <maya/MItSelectionList.h>
#include <maya/MSelectionList.h>

#include <maya/MPxContextCommand.h>
#include <maya/MPxContext.h>
#include <maya/MEvent.h>

#if defined(OSMac_MachO_)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif


// The user Context
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 );

private:
        short                                   start_x, start_y;
        short                                   last_x, last_y;

        short                                   p_last_x, p_last_y;
        bool                                    fsDrawn;

        MGlobal::ListAdjustment listAdjustment;
        M3dView                                 view;
};

marqueeContext::marqueeContext()
{
        setTitleString ( "Marquee Tool" );

        // Tell the context which XPM to use so the tool can properly
        // be a candidate for the 6th position on the mini-bar.
        setImage("marqueeTool.xpm", MPxContext::kImage1 );
        
}

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

MStatus marqueeContext::doPress( MEvent & event )
//
// Begin marquee drawing (using OpenGL)
// Get the start position of the marquee 
//
{

                // Figure out which modifier keys were pressed, and set up the
        // listAdjustment parameter to reflect what to do with the selected points.
        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;
        }

        // Extract the event information
        //
        event.getPosition( start_x, start_y );

        // Enable OpenGL drawing on viewport
        view = M3dView::active3dView();

        p_last_x = start_x;
        p_last_y = start_y;

        fsDrawn = false;

        return MS::kSuccess;            
}

// Example class code which basically does the same operatations
// as M3dView's beingXorDrawing() and endXorDrawing() methods.
// This class could be used in place these methods if desired.
//
class xorDraw
{
public:
        xorDraw(M3dView *view) { fView = view; };
        ~xorDraw() {};

        void beginXorDrawing();
        void endXorDrawing();

protected:
        xorDraw() { fView = NULL; }

        // Setup for XOR drawing
        GLboolean depthTest[1];
        GLboolean colorLogicOp[1];
        GLboolean lineStipple[1];

        M3dView *fView;


};

void xorDraw::beginXorDrawing()
{
        // Save the state of these 3 attribtes and restore them later.
        glGetBooleanv (GL_DEPTH_TEST, depthTest);
        glGetBooleanv (GL_COLOR_LOGIC_OP, colorLogicOp);
        glGetBooleanv (GL_LINE_STIPPLE, lineStipple);

        glDrawBuffer( GL_FRONT );

        // Turn Line stippling on.
        glLineStipple( 1, 0x5555 );
        glLineWidth( 1.0 );
        glEnable( GL_LINE_STIPPLE );

        // Save the state of the matrix on stack
        glMatrixMode (GL_MODELVIEW);
        glPushMatrix();

        // Setup the Orthographic projection Matrix.
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
    gluOrtho2D(
                        0.0, (GLdouble) fView->portWidth(),
                        0.0, (GLdouble) fView->portHeight()
    );
    glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
    glTranslatef(0.375, 0.375, 0.0);

        // Set the draw color
        glColor3f(1.0f, 1.0f, 1.0f);

        // Draw the marquee in XOR mode
        
        glDisable (GL_DEPTH_TEST);

        // Enable XOR mode.
        glEnable(GL_COLOR_LOGIC_OP);
        glLogicOp (GL_XOR);
}

void xorDraw::endXorDrawing()
{
        glFlush();
        glDrawBuffer( GL_BACK );

        // Restore the state of the matrix from stack
        glMatrixMode( GL_MODELVIEW );
        glPopMatrix();

        // Restore the previous state of these attributes
        if (colorLogicOp[0])
                glEnable (GL_COLOR_LOGIC_OP);
        else
                glDisable (GL_COLOR_LOGIC_OP);

        if (depthTest[0])
                glEnable (GL_DEPTH_TEST);
        else
                glDisable (GL_DEPTH_TEST);

        if (lineStipple[0])
                glEnable( GL_LINE_STIPPLE );
        else
                glDisable( GL_LINE_STIPPLE );
}

MStatus marqueeContext::doDrag( MEvent & event )
//
// Drag out the marquee (using OpenGL)
//
{
        
        event.getPosition( last_x, last_y );

        // Uncomment these, and comment out M3dView calls if
        // custom XOR drawing is required.
        //xorDraw XORdraw(&view);
        //XORdraw.beginXorDrawing();
        view.beginXorDrawing();

        // We erase the previously drawn rubber band on the screen by 
        // redrawing it in XOR OpenGL mode.

        if (fsDrawn)
        {
                
                glBegin( GL_LINE_LOOP );
                        glVertex2i( start_x, start_y );
                        glVertex2i( p_last_x, start_y );
                        glVertex2i( p_last_x, p_last_y );
                        glVertex2i( start_x, p_last_y );
                glEnd();
                
        }

        fsDrawn = true;

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

        //XORdraw.endXorDrawing();
        view.endXorDrawing();

        // Store the current x and y coordinates such that in the next iteration
        // we can erase this marquee by redrawing it in XOR mode.
        p_last_x = last_x;
        p_last_y = last_y;

        return MS::kSuccess;            

}

MStatus marqueeContext::doRelease( MEvent & event )
//
// Selects objects within the marquee box.
{

        MSelectionList                  incomingList, marqueeList;

        // Clear the marquee when you release the mouse button

        event.getPosition( last_x, last_y );

        //xorDraw XORdraw(&view);
        //XORdraw.beginXorDrawing();
        view.beginXorDrawing();

        // Redraw the marquee so that it will be cleared from the screen
        // when the mouse is released.
        glBegin( GL_LINE_LOOP );
                glVertex2i( start_x, start_y );
                glVertex2i( p_last_x, start_y );
                glVertex2i( p_last_x, p_last_y );
                glVertex2i( start_x, p_last_y );
        glEnd();
                
        //XORdraw.endXorDrawing();
        view.endXorDrawing();

        // Get the end position of the marquee
        event.getPosition( last_x, last_y );

        // Save the state of the current selections.  The "selectFromSceen"
        // below will alter the active list, and we have to be able to put
        // it back.
        MGlobal::getActiveSelectionList(incomingList);

        // If we have a zero dimension box, just do a point pick
        //
        if ( abs(start_x - last_x) < 2 && abs(start_y - last_y) < 2 ) {
                // This will check to see if the active view is in wireframe or not.
                MGlobal::SelectionMethod selectionMethod = MGlobal::selectionMethod();

                MGlobal::selectFromScreen( start_x, start_y, MGlobal::kReplaceList, selectionMethod );
        } else {
                // The Maya select tool goes to wireframe select when doing a marquee, so
                // we will copy that behaviour.
                // Select all the objects or components within the marquee.
                MGlobal::selectFromScreen( start_x, start_y, last_x, last_y,
                                                                   MGlobal::kReplaceList, 
                                                                   MGlobal::kWireframeSelectMethod );
        }

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

        // Restore the active selection list to what it was before
        // the "selectFromScreen"
        MGlobal::setActiveSelectionList(incomingList, MGlobal::kReplaceList);

        // Update the selection list as indicated by the modifier keys.
        MGlobal::selectCommand(marqueeList, listAdjustment);
        return MS::kSuccess;            
}
MStatus marqueeContext::doEnterRegion( MEvent & )
{
        return setHelpString( helpString );
}

// Command to create contexts

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

marqueeContextCmd::marqueeContextCmd() {}

MPxContext* marqueeContextCmd::makeObj()
{
        return new marqueeContext();
}

void* marqueeContextCmd::creator()
{
        return new marqueeContextCmd;
}

// plugin initialization
MStatus initializePlugin( MObject obj )
{
        MStatus         status;
        MFnPlugin       plugin( obj, PLUGIN_COMPANY, "4.5", "Any");

        status = plugin.registerContextCommand( "marqueeToolContext",
                                                                                    marqueeContextCmd::creator );
        return status;
}

MStatus uninitializePlugin( MObject obj )
{
        MStatus         status;
        MFnPlugin       plugin( obj );

        status = plugin.deregisterContextCommand( "marqueeToolContext" );

        return status;
}

Autodesk® Maya® 2011 © 1997-2010 Autodesk, Inc. All rights reserved. Generated with doxygen 1.5.6