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

//      Description:
//
//              Traces the position of an animated object
//              and create a curve showing the object's path.
//
//      Usage:
//
//              Animate an object.
//              Select the object.
//              Run 'motionTrace;' in the command window.
//              See the object's path drawn as a curve.
//
//      Options:
//
//              -s <frame>              The start frame.  Default to 1.
//              -e <frame>              The end frame.  Default to 60.
//              -b <frame>              The by frame.  Default to 1.
//
//      See also:
//
//              node_info.cc    for how to get object attributes
//              helix.cc                for how to create a curve

#include <maya/MIOStream.h>

#include <maya/MFnPlugin.h>
#include <maya/MString.h>
#include <maya/MArgList.h>

#include <maya/MPxCommand.h>

#include <maya/MGlobal.h>
#include <maya/MTime.h>
#include <maya/MDagPath.h>
#include <maya/MItSelectionList.h>
#include <maya/MSelectionList.h>

#include <maya/MFnDependencyNode.h>
#include <maya/MPlugArray.h>
#include <maya/MPlug.h>

#include <maya/MPoint.h>
#include <maya/MPointArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MObjectArray.h>
#include <maya/MFnNurbsCurve.h>

//
// Command class declaration
//
class motionTrace : public MPxCommand
{
public:
                                        motionTrace();
        virtual                 ~motionTrace();

        MStatus                 doIt( const MArgList& args );
        MStatus                 redoIt();

        static void*    creator();

private:
        void            printType( MObject node, MString & prefix );

        double                  start, end, by; // frame range
};



//
// Command class implementation
//

motionTrace::motionTrace() {}

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

motionTrace::~motionTrace()
{
}

MStatus motionTrace::doIt( const MArgList& args )
//
// Description
//     This method is called from MEL when this command is called.
//     It should set up any class data necessary for redo/undo,
//     parse any given arguments, and then call redoIt.
//
{
        start = 1.0;
        end = 60.0;
        by = 1.0;

        MStatus stat;
        double tmp;
        unsigned i;
    // Parse the arguments.
    for ( i = 0; i < args.length(); i++ )
        {
                if ( MString( "-s" ) == args.asString( i, &stat ) &&
                         MS::kSuccess == stat)
                {
                        tmp = args.asDouble( ++i, &stat );
                        if ( MS::kSuccess == stat )
                        start = tmp;
                }
                else if ( MString( "-e" ) == args.asString( i, &stat ) &&
                                  MS::kSuccess == stat)
                {
                        tmp = args.asDouble( ++i, &stat );
                        if ( MS::kSuccess == stat )
                        end = tmp;
                }
                else if ( MString( "-b" ) == args.asString( i, &stat ) &&
                                  MS::kSuccess == stat)
                {
                        tmp = args.asDouble( ++i, &stat );
                        if ( MS::kSuccess == stat )
                        by = tmp;
                }
        }

        stat = redoIt();

        return stat;
}

/*
-----------------------------------------

        Make a degree 1 curve from the given CVs.

-----------------------------------------
*/
static void jMakeCurve( MPointArray cvs )
{
        MStatus stat;
        unsigned int deg = 1;
        MDoubleArray knots;

        unsigned int i;
        for ( i = 0; i < cvs.length(); i++ )
                knots.append( (double) i );

    // Now create the curve
    //
    MFnNurbsCurve curveFn;

    curveFn.create( cvs,
                                    knots, deg,
                                    MFnNurbsCurve::kOpen,
                                    false, false,
                                    MObject::kNullObj,
                                    &stat );

    if ( MS::kSuccess != stat )
                cout<<"Error creating curve."<<endl;

}

MStatus motionTrace::redoIt()
//
// Description
//     This method performs the action of the command.
//
//     This method iterates over all selected items and
//     prints out connected plug and dependency node type
//     information.
//
{
        MStatus stat;                           // Status code

        MObjectArray picked;
        MObject         dependNode;             // Selected dependency node

        // Create a selection list iterator
        //
        MSelectionList slist;
        MGlobal::getActiveSelectionList( slist );
        MItSelectionList iter( slist, MFn::kInvalid,&stat );

        // Iterate over all selected dependency nodes
        // and save them in a list
        //
        for ( ; !iter.isDone(); iter.next() )
        {
                // Get the selected dependency node
                //
                if ( MS::kSuccess != iter.getDependNode( dependNode ) )
                {
                        cerr << "Error getting the dependency node" << endl;
                        continue;
                }
                picked.append( dependNode );
        }

        // array of arrays for object position

        MPointArray *pointArrays = new MPointArray [ picked.length() ];

        unsigned int i;
        double time;

        //      Sample the animation using start, end, by values

        for ( time = start; time <= end; time+=by )
        {
                MTime timeval(time);

                MGlobal::viewFrame( timeval );

                // Iterate over selected dependency nodes
                //

                for ( i = 0; i < picked.length(); i++ )
                {
                        // Get the selected dependency node
                        //
                        dependNode = picked[i];

                        // Create a function set for the dependency node
                        //
                        MFnDependencyNode fnDependNode( dependNode );

                        // Get the translation attribute values

                        MObject txAttr;
                        txAttr = fnDependNode.attribute( MString("translateX"), &stat );
                        MPlug txPlug( dependNode, txAttr );
                        double tx;
                        stat = txPlug.getValue( tx );

                        MObject tyAttr;
                        tyAttr = fnDependNode.attribute( MString("translateY"), &stat );
                        MPlug tyPlug( dependNode, tyAttr );
                        double ty;
                        stat = tyPlug.getValue( ty );

                        MObject tzAttr;
                        tzAttr = fnDependNode.attribute( MString("translateZ"), &stat );
                        MPlug tzPlug( dependNode, tzAttr );
                        double tz;
                        stat = tzPlug.getValue( tz );

#if 0
                        fprintf( stderr,
                                     "Time = %2.2lf, XYZ = ( %2.2lf, %2.2lf, %2.2lf )\n\n",
                                         time, tx, ty, tz );
#endif

                        pointArrays[i].append( MPoint( tx, ty, tz )) ;
                }
        }

        // make a path curve for each selected object

        for ( i = 0; i < picked.length(); i++ )
                jMakeCurve( pointArrays[i] );

        delete [] pointArrays;
        return MS::kSuccess;
}


//
// The following routines are used to register/unregister
// the command we are creating within Maya
//
MStatus initializePlugin( MObject obj )
{
        MStatus   status;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

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

        return status;
}

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

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

        return status;
}