- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Examples

# meshReorderTool.cpp

    //
    // Description: Get user selections for mesh vertex/edge reordering
    //
    // Author: Bruce Hickey
    //

    // This is added to prevent multiple definitions of the MApiVersion string.
    #define _MApiVersion

    #include <maya/MCursor.h>
    #include <maya/MGlobal.h>
    #include <maya/MFnDependencyNode.h>
    #include <maya/MIOStream.h>
    #include <maya/MItMeshVertex.h>
    #include <maya/MPlug.h>

    #include <meshReorderTool.h>
    #include <meshMapUtils.h>

    // The user Context

    meshReorderTool::meshReorderTool()
    {
        setTitleString ( "Mesh Reorder Tool" );
        setCursor( MCursor::editCursor );
        reset();
    }

    meshReorderTool::~meshReorderTool() {}

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

    void meshReorderTool::toolOnSetup ( MEvent & )
    {
        reset();
    }

    void meshReorderTool::reset()
    {
        MEvent e;

        fNumSelectedPoints = 0;

        fSelectedPathSrc.clear();
        fSelectedComponentSrc.clear();
        fSelectVtxSrc.clear();
        fSelectedFaceSrc = -1;

        fCurrentHelpString = "Select 1st point on mesh.";

        helpStateHasChanged( e );
    }

    //
    // Selects objects within the user defined area, then process them
    //
    MStatus meshReorderTool::doRelease( MEvent & event )
    {
        char buf[1024];

        // Perform the base actions
        MStatus stat = MPxSelectionContext::doRelease(event);

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

        //
        //  If there's nothing selected, don't worry about it, just return
        //
        if( fSelectionList.length() != 1 )
        {
            MGlobal::displayWarning( "Components must be selected one at a time" );
            return MS::kSuccess;
        }

        //
        //  Get the selection's details, we must have exactly one component selected
        //
        MObject component;
        MDagPath path;

        MItSelectionList selectionIt (fSelectionList, MFn::kComponent);

        MStringArray    selections;
        selectionIt.getStrings( selections );

        if( selections.length() != 1 )
        {
            MGlobal::displayError( "Must select exactly one vertex" );
            return MS::kSuccess;
        }

        if (selectionIt.isDone ())
        {
            MGlobal::displayError( "Selected item not a vertex" );
            return MS::kSuccess;
        }

        if( selectionIt.getDagPath (path, component) != MStatus::kSuccess )
        {
            MGlobal::displayError( "Must select a mesh or its vertex");
            return MS::kSuccess;
        }

        if (!path.node().hasFn(MFn::kMesh) && !(path.node().hasFn(MFn::kTransform) && path.hasFn(MFn::kMesh)))
        {
            MGlobal::displayError( "Must select a mesh or its transform" );
            return MS::kSuccess;
        }

        MFnMesh meshFn(path);
        MPlug   historyPlug = meshFn.findPlug("inMesh", true);
        if (historyPlug.isDestination())
        {
            MGlobal::displayError( "Mesh has history. Its geometry cannot be modified" );
            return MS::kSuccess;
        }

        MItMeshVertex fIt ( path, component, &stat );
        if( stat != MStatus::kSuccess )
        {
            MGlobal::displayError( "MItMeshVertex failed");
            return MStatus::kFailure;
        }

        if (fIt.count() != 1 )
        {
            sprintf(buf, " Invalid selection '%s'. Vertices must be picked one at a time.", selections[0].asChar() );
            MGlobal::displayError( buf );
            return MS::kSuccess;
        }
        else
        {
            sprintf(buf, "Accepting vertex '%s'", selections[0].asChar() );
            MGlobal::displayInfo(  buf );
        }

        //
        // Now that we know it's valid, process the selection
        //

        fSelectedPathSrc.append( path );
        fSelectedComponentSrc.append( component );

        //
        //  When each of the mesh defined, process it. An error/invalid selection will restart the selection for
        //  that particular mesh.
        //
        if( fNumSelectedPoints == 2 )
        {
            if( ( stat = meshMapUtils::validateFaceSelection( fSelectedPathSrc, fSelectedComponentSrc, &fSelectedFaceSrc, &fSelectVtxSrc ) ) != MStatus::kSuccess )
            {
                MGlobal::displayError("Must select vertices from the same face of a mesh");
                reset();
                return stat;
            }

            char cmdString[200];
            sprintf(cmdString, "meshReorder %s.vtx[%d] %s.vtx[%d] %s.vtx[%d]",
                                fSelectedPathSrc[0].partialPathName().asChar(), fSelectVtxSrc[0],
                                fSelectedPathSrc[1].partialPathName().asChar(), fSelectVtxSrc[1],
                                fSelectedPathSrc[2].partialPathName().asChar(), fSelectVtxSrc[2]);

            stat = MGlobal::executeCommand(cmdString, true, true);
            if (stat)
            {
                MGlobal::displayInfo( "Mesh reordering complete" );
            }

            //
            // Empty the selection list since the reodering may move the user's current selection on screen
            //
            MSelectionList empty;
            MGlobal::setActiveSelectionList( empty );

            //
            // Start again, get new meshes
            //
            reset();
        }
        else
        {
            //
            // We don't have all the details yet, just move to the next item
            //
            fNumSelectedPoints++;
        }

        helpStateHasChanged( event );

        return stat;
    }

    MStatus meshReorderTool::helpStateHasChanged( MEvent &)
    //
    // Description:
    //              Set up the correct information in the help window based
    //              on the current state.
    //
    {
        switch (fNumSelectedPoints)
        {
            case 0:
             fCurrentHelpString = "Select 1st vertex on mesh";
             break;
            case 1:
             fCurrentHelpString = "Select 2nd vertex, connected to 1st vertex and on the same face";
             break;
            case 2:
             fCurrentHelpString = "Select 3rd vertex, connected to 2nd vertex and on the same face";
             break;
            default:
             // nothing, shouldn't be here
             break;
         }

        setHelpString( fCurrentHelpString );

        return MS::kSuccess;
    }

    MPxContext* meshReorderContextCmd::makeObj()
    {
        return new meshReorderTool;
    }

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

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