Wednesday, September 5, 2012

Using Maya Api to Query Animation Keys

I was trying to animate a walk cycle and found that a script I wrote in MEL to try to block all the keys (put them in step / or smooth) was taking a way long time. So I began trying out some ideas with the api. I'm very new to using the api but I hope you find some of these code snippets helpful. The script isn't doing exactly what I want yet but it has a few stuff on keyframes.

Also check out Robert Bateman's amazing tips for the api.


Some things that might be helpful if used to MEL, or Python type Maya commands. Also I might have made some mistakes in this.

1. (mel) objectType, (api) like filtering selection list
2. (mel) objectExists, (api) like something.isNull()
3. (mel) for loop ++ counter, (api) like iterator .next()
4. (mel) array passed by reference (fn can edit param), (api) like &status error checking

(other stuff, api no dollar signs unlike MEL, and api mostly using different types than only having access to floats,ints,string...)

Also using the Maya docs was really helpful. Like for finding out info on keyframe stuff I looked in the Maya help docs and found an iterator for this kind of data. Bascially trying to find out what api worker can take care what I need it to do.

Here's the before and after

Here's the code, there still may be some bugs
/**@file keyframeQuery.cpp
@brief v1.0.0 Prints all keyframe values for all keys on all selected animation curves
@author Nathaniel O. Anozie (ogbonnawork at gmail dot com)
@bug all functions no assert checks
@note date created: Sep 05 2012
@note Inspired by Robert Bateman for learning about selection list,iterators and using a function set
@note this has some useful info for querying animation keyframe data

#include < maya/MSimple.h>
#include < maya/MGlobal.h>
//im guessing these are needed almost always
//printing stuff, selecting stuff
#include < maya/MItSelectionList.h>

//these are not always needed i needed these for keyframe stuff
//openMayaAnim library needed for animation stuff like these
#include < maya/MItKeyframe.h>             
#include < maya/MTime.h>
#include < maya/MFnAnimCurve.h>

//the name used here is the command that will be typed in Maya like keyQ;
DeclareSimpleCommand( keyQ, "Autodesk", "8.0");

/**the names here needs to match that used in DeclareSimpleCommand
@note notice no dollar signs, also we
@note need to do search manual to figure out the kind of thing that will help us find keyframes
@note the ampersand is alot different from MEL cause in MEL
@note i think only arrays are passed by reference
@note here a boolean type thing can be edited somewhere else and we can see what we got for error checking            
MStatus keyQ::doIt( const MArgList& )
    //i'm not sure if this is required in some cases
    MStatus stat = MS::kSuccess;
    MSelectionList selList;
    //unlike in MEL where we might say something like
    //if object is animation curve do this like objectType equal animCurvTA
    //In the api we can get with one line everything selected that
    //is an animation curve
    MItSelectionList curveIt(selList,MFn::kAnimCurve); //not in MGlobal
    while( !curveIt.isDone() )

        MObject myCurve;
        //not using getDagPath cause i'm guessing a backend animCurve node isn't in dag
        //because dealing with animation curves
        //i couldn't print name of animation curve
        //using MFnDependency node set 
        //MFnAnimCurve animCurveFn( myCurve, &status ); //no error checking if this is actually a compatible animation curve

        //different from mel instead of checking existing we need to check
        //null, like if objExists == 1 ...     
            //going from animator curve like animCurveTA to its keyframe
            MItKeyframe itKey(myCurve,&stat);
            //like saying in mel objectType was what we wanted
            if(stat == MS::kSuccess)
                while( !itKey.isDone() )
                    //print all the key times of this object
                    //its probably a good idea as using new tools
                    //then add header so header not forgotten
                    //the error would show up though when making
                    MTime frame = itKey.time();
                    //printing a number is a little tricky
                    //here i went into docs of MTime and found out
                    //how it could give back a double which MString can understand
                    //by using MString set double function
                    MString fr;
                    MGlobal::displayInfo( fr );
                    MGlobal::displayInfo( "\n" );
                    //increment key so dont get infinite loops
                //end is keyframe check  
        //increment selected;

 return MS::kSuccess;

Heres the make output command for mac, The parts that i'm familiar with is that we need more to actually run the thing in Maya than MEL where we can just use source. Like Maya's openMayaAnim need to be linked to to use the keyframe stuff of api.

//name for file

//where Maya is installed on computer

//name for the bundle this actually needs to then be put in mayas plugin path
//so it can find it

//-arch i386
//this was important for a macbook

//-lOpenMaya -lOpenMayaAnim
//these type of things were necessary to be able to use some of the headers

g++ -c keyframeQuery.cpp -arch i386 -DMAC_PLUGIN -DOSMac_MachO_ -DBits32_ -m32 -DUNIX -D_BOOL -DOSMac_ -DFUNCPROTO -D_GNU_SOURCE -fPIC -fno-strict-aliasing -DREQUIRE_IOSTREAM -Wno-deprecated -Wall -Wno-multichar -Wno-comment -Wno-sign-compare -funsigned-char -Wno-reorder -fno-gnu-keywords -ftemplate-depth-25 -pthread -Wno-deprecated -fno-gnu-keywords -g -I/Applications/Autodesk/maya2008/devkit/include -o keyframeQuery.o
g++ keyframeQuery.o -ldl -shared -L/Applications/ -lOpenMaya -lFoundation -Wl,-executable_path,/Applications/ -lFoundation -lOpenMaya -lOpenMayaAnim -framework OpenGL -o blockSelectedAnim.bundle

For more info on make file, building stuff check out Robert Pitts: Modules, Separate Compilation, Using Make Files (