/**@file naTangentTypeCmd.cpp

@brief v1.0.0 naTangentTypeCmd -step;   //make all the selected animation curves' keys stepped or smoothed  -smooth

@author Nathaniel O. Anozie (ogbonnawork at gmail dot com)

@bug no undo, limited error checking

@note modify at your own risk

@note goes over class declaration for maya command, initialize, unitialize,

@note I think studying the Maya docs is an excellent way to get familiar with the api

@note I looked at Maya's included api examples to understand parsing of user arguments,

initialize, unitialize, in        animInfoCmd.cpp

@note --fixed parameter bug, renamed file




// -step <string>: whether to use step tangent


// -smooth <string>: whether to use smooth tangent



//before using MSimple.h

//now to use external functions we'll use MPxCommand

//but we also need something else for the intialization stuff MFnPlugin

#include <maya/MPxCommand.h>

#include <maya/MFnPlugin.h>

#include <maya/MGlobal.h>

//for parameter stuff we need this one

#include <maya/MArgList.h>

#include <maya/MItSelectionList.h>

//look in docs what library needed to link to

#include <maya/MItKeyframe.h>                

//this is a little tricky this is kindof like a MEL global variable but not visible everywhere

//notice no equal is needed

//define replaces anywhere we see na_Cmd with this name

#define na_Cmd "naTangentTypeCmd"

#define na_Author "Nathaniel Anozie"

/**this is very different from MEL

before I used DeclareSimpleCommand( naTangentTypeCmd, "Autodesk", "8.0");

to take care of all the class stuff, now i'm writing the stuff out.

Check out Maya's included animInfoCmd.cpp for a great example


//public stuff




//do it



//private stuff

/*this slightly similar to MEL using proc, instead of global proc


//here i'm just making something to parse arguments we need for

//setting tangent of keys




class naTangentTypeCmd : public MPxCommand




        virtual            ~naTangentTypeCmd();

        virtual MStatus doIt ( const MArgList& args );

        static void* creator();


        //notice the stat isnt const so we can edit it in our function

        int getTangentTypeIndexFromArg(const MArgList& args, MStatus& stat );

//this semicolon is a little tricky because functions

//in MEL or if's etc don't have them after parenthesis




//after doing the class declaration need to make sure





//before with declareSimple command didn't need to worry about these


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

//pretty easy just write the command object twice kindof that

//tilde symbol

naTangentTypeCmd::~naTangentTypeCmd() {}

//if had some private variables -- coulbe be anything like doubles int whatever

//could set them to something in here

naTangentTypeCmd::naTangentTypeCmd() {}


//also need



MStatus initializePlugin( MObject obj )


        MFnPlugin plugin( obj, na_Author, "8.0", "Any");

        MStatus status = plugin.registerCommand(na_Cmd,

                                                                                    naTangentTypeCmd::creator );

    //heres another cool way to check error

    //like MEL's error( )

    //the MStatus class has this function perror

    if (!status) status.perror("registerCommand");

        return status;


MStatus uninitializePlugin( MObject obj )


        MFnPlugin plugin( obj );

        MStatus status = plugin.deregisterCommand(na_Cmd);

    if (!status) status.perror("deregisterCommand");

        return status;



//experimenting with a new function

//this i think is tricky because not using a variable but reference,

//i look at some of the example api files Maya came with to see how

//to parse argument list the animInfoCmd.cpp one


/**get the tangent type index to use given user arguments, basically I want rest of script

to know what the user selection was while keeping it separate from doIt

@param reference to user parameter (const MargList& arg)

@param reference to status code        (MStatus& stat)

@result 1 -- step, 2 -- smooth


int naTangentTypeCmd::getTangentTypeIndexFromArg( const MArgList& arg, MStatus& stat)



        int result = 1;

        stat = MS::kSuccess;


        //like MEL string

        MString parameterMessage = "Required single argument: -smooth ; - step; ";


        //like MEL's size using length

        if(arg.length() != 1){

            MGlobal::displayInfo( parameterMessage );


            stat = MS::kFailure; }


            //like MEL, param = array[0]


            MString param;

            param = arg.asString(0,&stat);

            MGlobal::displayInfo( param );

            //like MEL's strcmp but we'll use ==

            //dash needed

            if(param == "-smooth"){ result = 2;}

            else if(param == "-step"){ result = 1;  }


                //tell callee that something went wrong

                //by looking in docs for MStatus could find out these

                stat = MS::kFailure;






        //neat were returning something similar to MEL's usual


        return result;



before with declareSimpleCommand wasn't using argument so i didn't have

arg in parameter, i need it here so i can pass it as a parameter to another



MStatus naTangentTypeCmd::doIt( const MArgList& arg)



        MStatus stat = MS::kSuccess;


        //don't need anything before parseArg

        //because by writing out the class and putting this there

        //it can be found

        //neat how we can verify the function we wrote does what is needed

        //by checking

        int tangentTypeChoice = getTangentTypeIndexFromArg( arg, stat );





        MSelectionList selList;




        MItSelectionList curveIt(selList,MFn::kAnimCurve); //not in MGlobal


        while( !curveIt.isDone() )


            MObject myCurve;





                //going from animator curve like animCurveTA to its keyframe

                MItKeyframe itKey(myCurve,&stat);

                //i'm not surre 100 percent whether this will make sure

                //we have ability to work on keys



                if(stat == MS::kSuccess)


                    while( !itKey.isDone() )


                        //trying to use MItKeyframe's method to make

                        //key stepped, looked in manual for this and found

                        //one that changes tangent type.


                        //In a way similar to MEL's global variables

                        //we can use an public variables

                        //here using a public variable stored somewhere else

                        //in MItKeyframe, the kTangentStep enum (similar to mel int)

                        //I needed to look in manual though because sometimes

                        //like for the MSelectionList the filter variable wasnt in that

                        //header it was somewhere else in a MFn place



                        if( tangentTypeChoice == 1 ){

                            stat = itKey.setInTangentType(MItKeyframe::kTangentStep);

                            stat = itKey.setOutTangentType(MItKeyframe::kTangentStep);


                        else if( tangentTypeChoice == 2 ){


                            stat = itKey.setInTangentType(MItKeyframe::kTangentSmooth);

                            stat = itKey.setOutTangentType(MItKeyframe::kTangentSmooth);

                            stat = itKey.setTangentsLocked(false);












                    //end is keyframe check  




            //increment selected






    return MS::kSuccess;