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

#include <maya/MIOStream.h>
#include <maya/MSimple.h>
#include <maya/MSelectionList.h>
#include <maya/M3dView.h>
#include <maya/MGlobal.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnMesh.h>
#include <maya/MDagPath.h>
#include <math.h>

DeclareSimpleCommand( listPolyHoles, PLUGIN_COMPANY, "4.5");

MStatus listPolyHoles::doIt( const MArgList& args )
//
//  Description:
//      Implements the MEL listPolyHoles command.  This command outputs a list
//      of all the holes in each selected polymesh.
//      
//  Arguments:
//      args - the argument list that was passes to the command from MEL.  This
//             command takes no arguments.
//
//  Return Value:
//      MS::kSuccess - command succeeded
//      MS::kFailure - command failed (returning this value will cause the 
//                     MEL script that is being run to terminate unless the
//                     error is caught using a "catch" statement.
//
{
    MStatus stat = MS::kSuccess;

    MSelectionList curSel;
    MGlobal::getActiveSelectionList( curSel );

    cout<<endl;
    cout<<"*****************"<<endl;
    cout<<"* listPolyHoles *"<<endl;
    cout<<"*****************"<<endl;

    // iterate through the selection list, and find holes in any selected
    // polygons.
    //
    int numSelected = curSel.length();
    for( int s = 0; s < numSelected; s++ )
    {
        MDagPath dagPath;
        MObject node;

        // get the selected item, figure out if it's a polymesh or not
        //
        curSel.getDagPath( s, dagPath );
        if( dagPath.extendToShape() != MS::kSuccess )
        {
            // selection does not correspond to a DAG shape
            //
            cout<<" Error - object is not a polymesh"<<endl;
            stat = MS::kFailure;
            return stat;
        }

        node = dagPath.node();
        MFnDependencyNode fnNode( node );
        cout<<endl<<"Looking for holes in "<<fnNode.name().asChar()<<endl;
        
        MStatus polyStatus;
        MFnMesh fnMesh( node, &polyStatus );

        if( polyStatus == MS::kSuccess )
        {
            // Retrieve the list of holes in the polymesh.
            // 'holeInfo' array stores 3 integers for each hole:
            // 
            //  [ face, numVertices, startIndex ]
            //
            // where 'face' is the index of the face in which the 
            // hole is found, 'numVertices' is the number of vertices
            // that define the hole, and 'startIndex' is the starting
            // index of the list of hole vertices in the 'holeVertices'
            // array.
            //
            MIntArray holeInfo;

            // 'holeVertices' array contains a linear listing of the
            // vertices comprising all the holes in the selected polymesh.
            // information from the 'holeInfo' array is used to index into
            // this list to extract the list of vertices for each hole.
            //
            MIntArray holeVertices;
            MStatus holeStatus;

            holeInfo.clear();
            holeVertices.clear();
            
            // get the holes
            //
            int numHoles = fnMesh.getHoles( holeInfo, holeVertices, &holeStatus );
            if( holeStatus == MS::kSuccess )
            {
                cout<<"    Poly has "<<numHoles<<" holes"<<endl;

                for( int h = 0; h < numHoles; h++ )
                {
                    // retrieve the hole face index, number of hole vertices, and
                    // hole vertex list start index for the current hole.
                    //
                    int holeFace = holeInfo[3*h];
                    int holeNumVertices = holeInfo[3*h+1];
                    int holeStartIndex = holeInfo[3*h+2];

                    cout<<"    Hole "<<h<<":"<<endl;
                    cout<<"        Face "<<holeFace<<endl;
                    cout<<"        Start index "<<holeStartIndex<<endl;
                    cout<<"        "<<holeNumVertices<<" vertices: ";

                    // retrieve the hole vertex indices from the 'holeVertices'
                    // array.  The indices are a list of 'holeNumVertices' entries,
                    // starting at index 'holeStartIndex'.
                    //
                    for( int v = 0; v < holeNumVertices; v++ )
                    {
                        int index = holeStartIndex + v;
                        cout<<holeVertices[index];
                    }

                    cout<<endl;
                }
                
            }
            else
            {
                // something went wrong trying to retrieve the poly holes
                //
                cout<<"    Error retrieving polygon holes"<<endl;
                stat = MS::kFailure;
            }
        }
        else
        {
            // the current selection item was not a polymesh, so we can't retrieve
            // holes for it.
            //
            cout<<" Error - object is not a polymesh"<<endl;
            stat = MS::kFailure;
        }
    }
    
    setResult( "listPolyHoles completed." );
    return stat;
}