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

//
// This example takes a curve and changes it into a helix.
//

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

#include <maya/MFnPlugin.h>
#include <maya/MFnNurbsCurve.h>
#include <maya/MPointArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MPoint.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <maya/MItCurveCV.h>
#include <maya/MGlobal.h>
#include <maya/MDagPath.h>
#include <maya/MString.h>
#include <maya/MPxCommand.h>
#include <maya/MArgList.h>

class helix2 : public MPxCommand
{

public:
                helix2();
    virtual     ~helix2();

    MStatus     doIt( const MArgList& );
    MStatus     redoIt();
    MStatus     undoIt();
    bool        isUndoable() const;

    static      void* creator();

private:
    MDagPath    fDagPath;
    MObject     fComponent;
    MPointArray fCVs;
    double      radius;
    double      pitch;
};

MStatus helix2::doIt( const MArgList& args )
{
    MStatus status;

    // Parse the arguments.
    for ( unsigned i = 0; i < args.length(); i++ ) {
        if ( MString( "-p" ) == args.asString( i, &status )
                && MS::kSuccess == status)
        {
            double tmp = args.asDouble( ++i, &status );
            if ( MS::kSuccess == status )
                pitch = tmp;
        }
        else if ( MString( "-r" ) == args.asString( i, &status )
                && MS::kSuccess == status)
        {
            double tmp = args.asDouble( ++i, &status );
            if ( MS::kSuccess == status )
                radius = tmp;
        } else {
            MString msg = "Invalid flag: ";
            msg += args.asString( i );
            displayError( msg );
            return MS::kFailure;
        }
    }

    // Get the first selected curve from the selection list.
    MSelectionList slist;
    MGlobal::getActiveSelectionList( slist );

    MItSelectionList    list( slist, MFn::kNurbsCurve, &status );
    if (MS::kSuccess != status) {
        cerr << "doIt: could not create selection list iterator\n";
        return status;
    }

    if (list.isDone()) {
        cerr << "doIt: no curve has been selected\n";
        return MS::kFailure;
    }

    list.getDagPath( fDagPath, fComponent );

    return redoIt();
}

MStatus helix2::redoIt()
{
    unsigned        i, numCVs;
    MStatus         status;
    MFnNurbsCurve   curveFn( fDagPath );

    numCVs = curveFn.numCVs();
    status = curveFn.getCVs( fCVs );
    if ( MS::kSuccess != status )
    {
        cerr << "redoIt: could not get cvs status: " << status << endl;
        return MS::kFailure;
    }

    MPointArray     points(fCVs);
    for (i = 0; i < numCVs; i++)
        points[i] = MPoint( radius * cos( (double)i ),
                            pitch * (double)i,
                            radius * sin( (double)i ) );
    status = curveFn.setCVs( points );
    if ( MS::kSuccess != status )
    {
        cerr << "redoIt: could not setCVs status: " << status << endl;
        fCVs.clear();
        return status;
    }

    status == curveFn.updateCurve();
    if ( MS::kSuccess != status )
    {
        cerr << "redoIt: updateCurve() failed status: " << status << endl;
        return status;
    }

    return MS::kSuccess;
}

MStatus helix2::undoIt()
{
    MStatus     status;

    MFnNurbsCurve   curveFn( fDagPath );
    status = curveFn.setCVs( fCVs );
    if ( MS::kSuccess != status)
    {
        cerr << "undoIt: array length is " << fCVs.length()
             << "bad status: " << status << endl;
        return status;
    }

    status = curveFn.updateCurve();
    if ( MS::kSuccess != status )
    {
        cerr << "undoIt: updateCurve() failed status: " << status << endl;
        return status;
    }

    fCVs.clear();
    return MS::kSuccess;
}

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

helix2::helix2()
    : radius( 4.0 ),
      pitch( 0.5 ),
      fComponent()
{}

helix2::~helix2()
{
    fCVs.clear();
    // Note that we do nothing with fComponent which is owned by Maya.
}

bool helix2::isUndoable() const
{
    return true;
}

MStatus initializePlugin( MObject obj )
{ 
    MStatus   status;
    MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

    status = plugin.registerCommand( "helix2", helix2::creator );
    if (!status) {
        status.perror("registerCommand");
        return status;
    }

    return status;
}

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

    status = plugin.deregisterCommand( "helix2" );
    if (!status) {
        status.perror("deregisterCommand");
        return status;
    }

    return status;
}