apiSimpleShapeUI.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.
// ==========================================================================
//+

//
// apiSimpleShapeUI.cpp
//

#include <maya/MIOStream.h> 

#include <apiSimpleShapeUI.h>

#include <maya/MMaterial.h>
#include <maya/MSelectionList.h>
#include <maya/MSelectionMask.h>
#include <maya/MDrawData.h>
#include <maya/MMatrix.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MObjectArray.h>
#include <maya/MDagPath.h>

// Object and component color defines
//
#define LEAD_COLOR                              18      // green
#define ACTIVE_COLOR                    15      // white
#define ACTIVE_AFFECTED_COLOR   8       // purple
#define DORMANT_COLOR                   4       // blue
#define HILITE_COLOR                    17      // pale blue
#define DORMANT_VERTEX_COLOR    8       // purple
#define ACTIVE_VERTEX_COLOR             16      // yellow

// Vertex point size
//
#define POINT_SIZE                              2.0     

//
// UI implementation
//

apiSimpleShapeUI::apiSimpleShapeUI() {}
apiSimpleShapeUI::~apiSimpleShapeUI() {}

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

//
// Overrides
//

/* override */
void apiSimpleShapeUI::getDrawRequests( const MDrawInfo & info,
                                                         bool objectAndActiveOnly,
                                                         MDrawRequestQueue & queue )
//
// Description:
//
//     Add draw requests to the draw queue
//
// Arguments:
//
//     info                 - current drawing state
//     objectsAndActiveOnly - no components if true
//     queue                - queue of draw requests to add to
//
{
        // Get the data necessary to draw the shape
        //
        MDrawData data;
        apiSimpleShape* shape = (apiSimpleShape*) surfaceShape();
        MVectorArray* geomPtr = shape->getControlPoints();

        // This call creates a prototype draw request that we can fill
        // in and then add to the draw queue.
        //
        MDrawRequest request = info.getPrototype( *this );

        // Stuff our data into the draw request, it'll be used when the drawing
        // actually happens
        getDrawData( geomPtr, data );

        request.setDrawData( data );


        // Decode the draw info and determine what needs to be drawn
        //

        M3dView::DisplayStyle  appearance    = info.displayStyle();
        M3dView::DisplayStatus displayStatus = info.displayStatus();

        switch ( appearance )
        {
                case M3dView::kWireFrame :
                {
                        request.setToken( kDrawWireframe );

                        M3dView::ColorTable activeColorTable = M3dView::kActiveColors;
                        M3dView::ColorTable dormantColorTable = M3dView::kDormantColors;

                        switch ( displayStatus )
                        {
                                case M3dView::kLead :
                                        request.setColor( LEAD_COLOR, activeColorTable );
                                        break;
                                case M3dView::kActive :
                                        request.setColor( ACTIVE_COLOR, activeColorTable );
                                        break;
                                case M3dView::kActiveAffected :
                                        request.setColor( ACTIVE_AFFECTED_COLOR, activeColorTable );
                                        break;
                                case M3dView::kDormant :
                                        request.setColor( DORMANT_COLOR, dormantColorTable );
                                        break;
                                case M3dView::kHilite :
                                        request.setColor( HILITE_COLOR, activeColorTable );
                                        break;

                                default:
                                                break;
                        }

                        queue.add( request );

                        break;
                }

                case M3dView::kGouraudShaded :
                {
                        // Create the smooth shaded draw request
                        //
                        request.setToken( kDrawSmoothShaded );

                        // Need to get the material info
                        //
                        MDagPath path = info.multiPath();       // path to your dag object 
                        M3dView view = info.view();;            // view to draw to
                        MMaterial material = MPxSurfaceShapeUI::material( path );

                        // Evaluate the material and if necessary, the texture.
                        //
                        if ( ! material.evaluateMaterial( view, path ) ) {
                                cerr << "Couldnt evaluate\n";
                        }

                        bool drawTexture = true;
                        if ( drawTexture && material.materialIsTextured() ) {
                                material.evaluateTexture( data );
                        }

                        request.setMaterial( material );

                        // request.setDisplayStyle( appearance );

                        bool materialTransparent = false;
                        material.getHasTransparency( materialTransparent );
                        if ( materialTransparent ) {
                                request.setIsTransparent( true );
                        }

                        queue.add( request );

                        // create a draw request for wireframe on shaded if
                        // necessary.
                        //
                        if ( (displayStatus == M3dView::kActive) ||
                                 (displayStatus == M3dView::kLead) ||
                                 (displayStatus == M3dView::kHilite) )
                        {
                                MDrawRequest wireRequest = info.getPrototype( *this );
                                wireRequest.setDrawData( data );
                                wireRequest.setToken( kDrawWireframeOnShaded );
                                wireRequest.setDisplayStyle( M3dView::kWireFrame );

                                M3dView::ColorTable activeColorTable = M3dView::kActiveColors;

                                switch ( displayStatus )
                                {
                                        case M3dView::kLead :
                                                wireRequest.setColor( LEAD_COLOR, activeColorTable );
                                                break;
                                        case M3dView::kActive :
                                                wireRequest.setColor( ACTIVE_COLOR, activeColorTable );
                                                break;
                                        case M3dView::kHilite :
                                                wireRequest.setColor( HILITE_COLOR, activeColorTable );
                                                break;

                                        default :       
                                                break;
                                }

                                queue.add( wireRequest );
                        }

                        break;
                }

                case M3dView::kFlatShaded :
                        request.setToken( kDrawFlatShaded );
                        break;

                default:
                        break;

        }

        // Add draw requests for components
        //
        if ( !objectAndActiveOnly ) {

                // Inactive components
                //
                if ( (appearance == M3dView::kPoints) ||
                         (displayStatus == M3dView::kHilite) )
                {
                        MDrawRequest vertexRequest = info.getPrototype( *this ); 
                        vertexRequest.setDrawData( data );
                        vertexRequest.setToken( kDrawVertices );
                        vertexRequest.setColor( DORMANT_VERTEX_COLOR,
                                                                        M3dView::kActiveColors );

                        queue.add( vertexRequest );
                }

                // Active components
                //
                if ( surfaceShape()->hasActiveComponents() ) {

                        MDrawRequest activeVertexRequest = info.getPrototype( *this ); 
                        activeVertexRequest.setDrawData( data );
                    activeVertexRequest.setToken( kDrawVertices );
                    activeVertexRequest.setColor( ACTIVE_VERTEX_COLOR,
                                                                                  M3dView::kActiveColors );

                    MObjectArray clist = surfaceShape()->activeComponents();
                    MObject vertexComponent = clist[0]; // Should filter list
                    activeVertexRequest.setComponent( vertexComponent );

                        queue.add( activeVertexRequest );
                }
        }
}

/* override */
void apiSimpleShapeUI::draw( const MDrawRequest & request, M3dView & view ) const
//
// Description:
//
//     Main (OpenGL) draw routine
//
// Arguments:
//
//     request - request to be drawn
//     view    - view to draw into
//
{ 
        // Get the token from the draw request.
        // The token specifies what needs to be drawn.
        //
        int token = request.token();
        switch( token )
        {
                case kDrawWireframe :
                case kDrawWireframeOnShaded :
                case kDrawVertices :
                        drawVertices( request, view );
                        break;

                case kDrawSmoothShaded :
                        break;                  // Not implemented, left as exercise

                case kDrawFlatShaded : // Not implemented, left as exercise
                        break;
        }
}

/* override */
bool apiSimpleShapeUI::select( MSelectInfo &selectInfo, MSelectionList &selectionList,
                                        MPointArray &worldSpaceSelectPts ) const
//
// Description:
//
//     Main selection routine
//
// Arguments:
//
//     selectInfo           - the selection state information
//     selectionList        - the list of selected items to add to
//     worldSpaceSelectPts  -
//
{
        bool selected = false;
        bool componentSelected = false;
        bool hilited = false;

        hilited = (selectInfo.displayStatus() == M3dView::kHilite);
        if ( hilited ) {
                componentSelected = selectVertices( selectInfo, selectionList, worldSpaceSelectPts );
                selected = selected || componentSelected;
        }

        if ( !selected ) 
        {
                // NOTE: If the geometry has an intersect routine it should
                // be called here with the selection ray to determine if the
                // the object was selected.

                selected = true;
                MSelectionMask priorityMask( MSelectionMask::kSelectNurbsSurfaces );
                MSelectionList item;
                item.add( selectInfo.selectPath() );
                MPoint xformedPt;
                if ( selectInfo.singleSelection() ) {
                        MPoint center = surfaceShape()->boundingBox().center();
                        xformedPt = center;
                        xformedPt *= selectInfo.selectPath().inclusiveMatrix();
                }

                selectInfo.addSelection( item, xformedPt, selectionList,
                                                                 worldSpaceSelectPts, priorityMask, false );
        }

        return selected;
}

//
// Helper routines
//


void apiSimpleShapeUI::drawVertices( const MDrawRequest & request,
                                                          M3dView & view ) const
//
// Description:
//
//     Component (vertex) drawing routine
//
// Arguments:
//
//     request - request to be drawn
//     view    - view to draw into
//
{
        MDrawData data = request.drawData();
        MVectorArray * geom = (MVectorArray*)data.geometry();

        view.beginGL(); 

        // Query current state so it can be restored
        //
        bool lightingWasOn = glIsEnabled( GL_LIGHTING ) ? true : false;
        if ( lightingWasOn ) {
                glDisable( GL_LIGHTING );
        }
        float lastPointSize;
        glGetFloatv( GL_POINT_SIZE, &lastPointSize );

        // Set the point size of the vertices
        //
        glPointSize( POINT_SIZE );

        // If there is a component specified by the draw request
        // then loop over comp (using an MFnComponent class) and draw the
        // active vertices, otherwise draw all vertices.
        //
        MObject comp = request.component();
        if ( ! comp.isNull() ) {
                MFnSingleIndexedComponent fnComponent( comp );
                for ( int i=0; i<fnComponent.elementCount(); i++ )
                {
                        int index = fnComponent.element( i );
                        glBegin( GL_POINTS );
                        MVector& point = (*geom)[index];
                        glVertex3f( (float)point[0], 
                                                (float)point[1], 
                                                (float)point[2] );
                        glEnd();

                        char annotation[32];
                        sprintf( annotation, "%d", index );
                        view.drawText( annotation, point );
                }
        }
        else {
                for ( unsigned int i=0; i<geom->length(); i++ )
                {
                        glBegin( GL_POINTS );
                        MVector point = (*geom)[ i ];
                        glVertex3f( (float)point[0], (float)point[1], (float)point[2] );
                        glEnd();
                }
        }

        // Restore the state
        //
        if ( lightingWasOn ) {
                glEnable( GL_LIGHTING );
        }
        glPointSize( lastPointSize );

        view.endGL(); 
}

bool apiSimpleShapeUI::selectVertices( MSelectInfo &selectInfo,
                                                         MSelectionList &selectionList,
                                                         MPointArray &worldSpaceSelectPts ) const
//
// Description:
//
//     Vertex selection.
//
// Arguments:
//
//     selectInfo           - the selection state information
//     selectionList        - the list of selected items to add to
//     worldSpaceSelectPts  -
//
{
        bool selected = false;
        M3dView view = selectInfo.view();

        MPoint          xformedPoint;
        MPoint          currentPoint;
        MPoint          selectionPoint;
        double          z,previousZ = 0.0;
        int                     closestPointVertexIndex = -1;

        const MDagPath & path = selectInfo.multiPath();

        // Create a component that will store the selected vertices
        //
        MFnSingleIndexedComponent fnComponent;
        MObject surfaceComponent = fnComponent.create( MFn::kMeshVertComponent );
        int vertexIndex;

        // if the user did a single mouse click and we find > 1 selection
        // we will use the alignmentMatrix to find out which is the closest
        //
        MMatrix alignmentMatrix;
        MPoint singlePoint; 
        bool singleSelection = selectInfo.singleSelection();
        if( singleSelection ) {
                alignmentMatrix = selectInfo.getAlignmentMatrix();
        }

        // Get the geometry information
        //
        apiSimpleShape* shape = (apiSimpleShape*) surfaceShape();
        MVectorArray* geomPtr = shape->getControlPoints();
        MVectorArray& geom = *geomPtr;


        // Loop through all vertices of the mesh and
        // see if they lie withing the selection area
        //
        int numVertices = geom.length();
        for ( vertexIndex=0; vertexIndex<numVertices; vertexIndex++ )
        {
                const MVector& point = geom[ vertexIndex ];

                // Sets OpenGL's render mode to select and stores
                // selected items in a pick buffer
                //
                view.beginSelect();

                glBegin( GL_POINTS );
                glVertex3f( (float)point[0], 
                                        (float)point[1], 
                                        (float)point[2] );
                glEnd();

                if ( view.endSelect() > 0 )     // Hit count > 0
                {
                        selected = true;

                        if ( singleSelection ) {
                                xformedPoint = currentPoint;
                                xformedPoint.homogenize();
                                xformedPoint*= alignmentMatrix;
                                z = xformedPoint.z;
                                if ( closestPointVertexIndex < 0 || z > previousZ ) {
                                        closestPointVertexIndex = vertexIndex;
                                        singlePoint = currentPoint;
                                        previousZ = z;
                                }
                        } else {
                                // multiple selection, store all elements
                                //
                                fnComponent.addElement( vertexIndex );
                        }
                }
        }

        // If single selection, insert the closest point into the array
        //
        if ( selected && selectInfo.singleSelection() ) {
                fnComponent.addElement(closestPointVertexIndex);

                // need to get world space position for this vertex
                //
                selectionPoint = singlePoint;
                selectionPoint *= path.inclusiveMatrix();
        }

        // Add the selected component to the selection list
        //
        if ( selected ) {
                MSelectionList selectionItem;
                selectionItem.add( path, surfaceComponent );

                MSelectionMask mask( MSelectionMask::kSelectComponentsMask );
                selectInfo.addSelection(
                        selectionItem, selectionPoint,
                        selectionList, worldSpaceSelectPts,
                        mask, true );
        }

        return selected;
}


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