- Main Page
- Related Pages
- Modules
- Classes
- Examples

# 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;
    }