/**@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
*/
//Flags:
//
// -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
//
//constructor
//destructor
//do it
//creator
//
//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
//
//parseArg
//
class naTangentTypeCmd : public MPxCommand
{
public:
naTangentTypeCmd();
virtual ~naTangentTypeCmd();
virtual MStatus doIt ( const MArgList& args );
static void* creator();
private:
//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
//
//constructor
//destructor
//creator
//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
//initializePlugin
//uninitializePlugin
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)
{
CHECK_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.perror(parameterMessage);
stat = MS::kFailure; }
else{
//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; }
else{
//tell callee that something went wrong
//by looking in docs for MStatus could find out these
stat = MS::kFailure;
stat.perror(parameterMessage);
}
}
//neat were returning something similar to MEL's usual
//int
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
function
*/
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 );
CHECK_MSTATUS(stat);
MSelectionList selList;
MGlobal::getActiveSelectionList(selList);
MItSelectionList curveIt(selList,MFn::kAnimCurve); //not in MGlobal
while( !curveIt.isDone() )
{
MObject myCurve;
curveIt.getDependNode(myCurve);
if(!myCurve.isNull())
{
//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
CHECK_MSTATUS(stat);
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);
}
else
{
stat.perror("Skipping");
}
CHECK_MSTATUS(stat);
itKey.next();
}
//end is keyframe check
}
}
//increment selected
curveIt.next();
}
return MS::kSuccess;
}