#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MFloatMatrix.h>
#include <maya/MTime.h>
#include <maya/MArgList.h>
#include <maya/MPlug.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnCamera.h>
#include <maya/MDagPath.h>
#include <maya/MItDag.h>
#include <maya/MSelectionList.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MAnimControl.h>
#include <maya/MPxCommand.h>
#include <maya/MComputation.h>
#include <maya/MFnPlugin.h>
#define mCommandName "animInfo"             // Command name
#define INDENT_STEP  2                      // Indentation steps
#define MAX_NB_PLUGS 100                    // Max number of plugs
#define MAX_NB_CAM   32                     // Max number of camera
#define FILE_TYPE    "Maya per frame data"  // File type
#define VERSION_ID   0                      // Version number
static char * stIndentStr = "                                                ";
{
public:
                 animInfoCmd();
    virtual     ~animInfoCmd();
    static void* creator();
private:
    const char * indent() const {return stIndentStr+strlen(stIndentStr)-fIndent;}
    void readSceneStartEnd();
    MStatus writeFrameInfo( 
double frame );
 
    double      fStartFrame;
    double      fEndFrame;
    double      fByFrame;
    int         fIndent;
    FILE *      fOutput;
    int         fNbCameraPath;
    
    
    int         fNbPlugs;
    MPlug       fPlugs[MAX_NB_PLUGS];
 
};
animInfoCmd::animInfoCmd() :
    fStartFrame(-1),
    fEndFrame  (-2),
    fByFrame   ( 1),
    fIndent    (INDENT_STEP),
    fOutput    (stdout),
    fNbCameraPath(0),
    fNbPlugs   (0)
{}
animInfoCmd::~animInfoCmd() {}
{
    {
    }
}
#define MATCH(str, shortName, longName) \
        (((str)==(shortName))||((str)==(longName)))
static int stringArg(
const MArgList& args, 
unsigned int &indx, 
MString & res)
 
{
    {
        indx++;
            return 1;
    }
    return 0;
}
static int doubleArg(
const MArgList& args, 
unsigned int &indx, 
double & res)
 
{
    {
        indx++;
            return 1;
    }
    return 0;
}
{
    
    unsigned int i;
    for ( i = 0; i < args.
length(); i++ ) {
 
            continue;
        if (MATCH(arg, "-on", "-outputName") && stringArg(args, i, str))
        {
            FILE *f;
            if ( NULL != (f = fopen(str.
asChar(), 
"w")))
 
                fOutput = f;
            else 
            {
                fprintf(stderr, 
"cannot open '%s'\n", str.
asChar());
                fflush(stderr);
            }
        }
        else if (MATCH(arg, "-s", "-start"))
            doubleArg(args, i, fStartFrame);
        else if (MATCH(arg, "-e", "-end"))
            doubleArg(args, i, fEndFrame);
        else if (MATCH(arg, "-by", "-byFrame"))
            doubleArg(args, i, fByFrame);
        else if (MATCH(arg, "-cam", "-camera") && stringArg(args, i, str))
        {
            if (fNbCameraPath >= MAX_NB_CAM)
                break;
            nodeFromName(str, cameraNode);
            fCameraPath[fNbCameraPath].extendToShape();
            MFnCamera cam(fCameraPath[fNbCameraPath], &status);
 
                fNbCameraPath++;
            
        }
        else if (MATCH(arg, "-p", "-plug") && stringArg(args, i, str))
        {
            
            for (
unsigned int k = 0 ; k<plugList.
length() ; k++)
 
            {
                if (fNbPlugs >= MAX_NB_PLUGS)
                    break;
                    fNbPlugs++;
            }
        }
        else
        {
            fprintf(stderr, 
"Unknown argument '%s'\n", arg.
asChar());
            fflush(stderr);
        }
    }
    if (fByFrame<=0) fByFrame = 1;
    if (fNbCameraPath == 0)
    {
        
        for (; !dagIterator.isDone(); dagIterator.next())
        {
            if (fNbCameraPath >= MAX_NB_CAM)
                break;
            bool        renderable;
            if ( !dagIterator.getPath(fCameraPath[fNbCameraPath]) )
                continue;
    
            renderable = false;
            MFnCamera fnCameraNode( fCameraPath[fNbCameraPath] );
 
            fnCameraNode.findPlug( "renderable" ).getValue( renderable );
    
            if (renderable)
                fNbCameraPath++;
        }
    }
}
void animInfoCmd::readSceneStartEnd()
{
    
    
    int rangeIsSet = 0;
    if (nodeFromName(
"defaultRenderGlobals", renderGlobNode) == 
MS::kSuccess)
 
    {
        
        
        
        MPlug animPlug = fnRenderGlobals.findPlug( 
"animation" );
 
        short anim;
        if ( anim ) {
            float byFrame;
            fnRenderGlobals.findPlug( "startFrame"  ).getValue(startFrame);
            fnRenderGlobals.findPlug( "endFrame"    ).getValue(endFrame);
            fnRenderGlobals.findPlug( "byFrameStep" ).getValue(byFrame);
            fByFrame = (double) byFrame;
            rangeIsSet = 1;
        }
    }
    if (!rangeIsSet)    {
        
        fByFrame = 1;
    }
}
MStatus animInfoCmd::writeFrameInfo( 
double frame )
 
{
    int i;
    fprintf(fOutput, "%s<TIME VAL=%g>\n", indent(), frame);
    fIndent += INDENT_STEP;
    for (i = 0 ; i<fNbCameraPath ; i++)
    {
            writeCameraInfo(cam);
    }
    double val;
    for (i = 0 ; i<fNbPlugs ; i++)
    {
            fprintf(fOutput, "%s<PARAM NAME=\"%s\" VAL=%lg>\n", 
                    indent(), fPlugs[i].name().asChar(), val);
    }
    fIndent -= INDENT_STEP;
    fprintf(fOutput, "%s</TIME>\n", indent());
}
{
    fprintf(fOutput, "%s<CAMERA NAME=\"%s\">\n", 
    fIndent += INDENT_STEP;
    fprintf(fOutput, 
"%s<EYE X=%g Y=%g Z=%g>\n", indent(), pt.
x, pt.
y, pt.
z);
    fprintf(fOutput, 
"%s<DIR X=%g Y=%g Z=%g>\n", indent(), v.
x, v.
y, v.
z);
    fprintf(fOutput, 
"%s<UP X=%g Y=%g Z=%g>\n", indent(), v.
x, v.
y, v.
z);
    fprintf(fOutput, 
"%s<RIGHT X=%g Y=%g Z=%g>\n", indent(), v.
x, v.
y, v.
z);
        fprintf(fOutput, 
"%s<COI X=%g Y=%g Z=%g>\n", indent(), pt.
x,pt.
y,pt.
z);
    else
        fprintf(fOutput, "%s<COI NONE>\n", indent());
    fprintf(fOutput, 
"%s<ASPECTRATIO VAL=%g>\n", indent(), cam.
aspectRatio());
    fprintf(fOutput, 
"%s<FSTOP VAL=%g>\n", indent(), cam.
fStop());
    fprintf(fOutput, 
"%s<FOCALLENGTH VAL=%g>\n", indent(), cam.
focalLength());
    fprintf(fOutput, "%s<FOCUS VAL=%g NEAR=%g FAR=%g>\n", indent(),
    fprintf(fOutput, "%s<MAT A00=%g A01=%g A02=%g A03=%g\n", indent(),
            mat(0,0), mat(0,1), mat(0,2), mat(0,3));
    fprintf(fOutput, "%s     A10=%g A11=%g A12=%g A13=%g\n", indent(),
            mat(1,0), mat(1,1), mat(1,2), mat(1,3));
    fprintf(fOutput, "%s     A20=%g A21=%g A22=%g A23=%g\n", indent(),
            mat(2,0), mat(2,1), mat(2,2), mat(2,3));
    fprintf(fOutput, "%s     A30=%g A31=%g A32=%g A33=%g>\n", indent(),
            mat(3,0), mat(3,1), mat(3,2), mat(3,3));
    fIndent -= INDENT_STEP;
    fprintf(fOutput, "%s</CAMERA>\n", indent());
}
{
    
    
        if (fOutput != stdout) 
            fclose(fOutput);
        return stat;
    }
    if (fStartFrame > fEndFrame)
        readSceneStartEnd();
    
    fprintf(fOutput, "<FILE TYPE=\"%s\" VERSION=%d>\n", FILE_TYPE, VERSION_ID);
    fprintf(fOutput, "\n%s<SEQUENCE START=%g END=%g STEP=%g>\n", 
            indent(), fStartFrame, fEndFrame, fByFrame);
    fIndent += INDENT_STEP;
    const float kMaxProgressRange = 100.0;
    for (double frame = fStartFrame ; frame <= fEndFrame ; frame += fByFrame)
    {
        {
            fprintf(fOutput, "%s<INTERRUPTION>\n", indent());
            break ;
        }
        writeFrameInfo(frame);
        
        int amount = (int)(kMaxProgressRange * (frame - fStartFrame + 1) / (fEndFrame - fStartFrame + 1));
    }
    fIndent -= INDENT_STEP;
    fprintf(fOutput, "%s</SEQUENCE>\n", indent());
    fflush(fOutput);
    if (fOutput != stdout) 
        fclose(fOutput);
    
}
void * animInfoCmd::creator() { return new animInfoCmd(); }
{
    MFnPlugin plugin( obj, PLUGIN_COMPANY, 
"4.0", 
"Any");
 
    MStatus status = plugin.registerCommand(mCommandName,
 
                                            animInfoCmd::creator );
    if (!status) status.
perror(
"registerCommand");
 
    return status;
}
{
    MStatus status = plugin.deregisterCommand(mCommandName);
 
    if (!status) status.
perror(
"deregisterCommand");
 
    return status;
}