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

//
// particleSystemInfoCmd
//
// Demonstrates the use of the new MFnParticleSystem class for retrieving
// particle information.  The number of particle positions followed by
// the positions are printed to the script editor.
//
//  Syntax:
//      particleSystemInfo $particleNodeName;
//
//  Example:
//  particleSystemInfo particleShape2;
//

#include <assert.h>

#include <maya/MIOStream.h>
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MPointArray.h>
#include <maya/MVectorArray.h>
#include <maya/MFloatMatrix.h>
#include <maya/MArgList.h>
#include <maya/MPlug.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MDagPath.h>
#include <maya/MItDag.h>
#include <maya/MSelectionList.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MPxCommand.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnParticleSystem.h>
#include <maya/MFnPlugin.h>
#include <maya/MObjectArray.h>

#define mCommandName "particleSystemInfo"   // Command name

#define CHECKRESULT(stat,msg)     \
        if ( MS::kSuccess != stat ) { \
                cerr << msg << endl;      \
        }

class particleSystemInfoCmd : public MPxCommand
{
public:
                 particleSystemInfoCmd();
    virtual     ~particleSystemInfoCmd();

    virtual MStatus doIt ( const MArgList& args );

    static void* creator();

private:

    static MStatus nodeFromName(MString name, MObject & obj);

    MStatus parseArgs ( const MArgList& args );

    MObject particleNode;
};

particleSystemInfoCmd::particleSystemInfoCmd()
{
}

particleSystemInfoCmd::~particleSystemInfoCmd() 
{
}


//
//

MStatus particleSystemInfoCmd::nodeFromName(MString name, MObject & obj)
{
    MSelectionList tempList;
    tempList.add( name );
    if ( tempList.length() > 0 ) 
    {
        tempList.getDependNode( 0, obj );
        return MS::kSuccess;
    }
    return MS::kFailure;
}




MStatus particleSystemInfoCmd::parseArgs( const MArgList& args )
{
    // Parse the arguments.
    MStatus stat = MS::kSuccess;

    if( args.length() > 1 )
    {
        MGlobal::displayError( "Too many arguments." );
        return MS::kFailure;
    }

    if( args.length() == 1 )
    {
            MString particleName = args.asString( 0, &stat );
        CHECKRESULT(stat, "Failed to parse particle node name argument." );

        nodeFromName( particleName, particleNode );
        
        if( !particleNode.isNull() && !particleNode.hasFn( MFn::kParticle ) )
        {
                MGlobal::displayError( "The named node is not a particle system." );
            return MS::kFailure;
        }
    } 
    return MS::kSuccess;
}


//
// Main routine
MStatus particleSystemInfoCmd::doIt( const MArgList& args )
{
    MStatus stat = parseArgs( args );
    if( stat != MS::kSuccess ) return stat;

    if( particleNode.isNull() ) {
            MObject parent;
        MFnParticleSystem dummy;
        particleNode = dummy.create(&stat);
        CHECKRESULT(stat,"MFnParticleSystem::create(status) failed!");

        MFnParticleSystem ps( particleNode, &stat );
        CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!");

        MPointArray posArray;
        posArray.append(MPoint(-5,  5, 0));
        posArray.append(MPoint(-5, 10, 0));

        MVectorArray velArray;
        velArray.append(MPoint(1, 1, 0));
        velArray.append(MPoint(1, 1, 0));
        stat = ps.emit(posArray, velArray);
        CHECKRESULT(stat,"MFnParticleSystem::emit(posArray,velArray) failed!");

        stat = ps.emit(MPoint(5,  5, 0));
        CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!");
        stat = ps.emit(MPoint(5, 10, 0));
        CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!");

        stat = ps.saveInitialState();
        CHECKRESULT(stat,"MFnParticleSystem::saveInitialState() failed!");

        MVectorArray accArray;
        accArray.setLength(4);
        for( unsigned int i=0; i<accArray.length(); i++ )
        {
                MVector& acc = accArray[i];
            acc.x = acc.y = acc.z = 3.0;
        }
        MString accName("acceleration");
        ps.setPerParticleAttribute( accName, accArray, &stat );
        CHECKRESULT(stat,"MFnParticleSystem::setPerParticleAttribute(vectorArray) failed!");
    } 

    MFnParticleSystem ps( particleNode, &stat );
    CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!");

    if( ! ps.isValid() )
    {
        MGlobal::displayError( "The function set is invalid!" );
        return MS::kFailure;
    }

    const MString name = ps.particleName();
    const MFnParticleSystem::RenderType psType = ps.renderType();
    const unsigned int count = ps.count();

    const char* typeString = NULL;
    switch( psType )
    {
    case MFnParticleSystem::kCloud:
        typeString = "Cloud";
        break;
    case MFnParticleSystem::kTube:
        typeString = "Tube system";
        break;
    case MFnParticleSystem::kBlobby:
        typeString = "Blobby";
        break;
    case MFnParticleSystem::kMultiPoint:
        typeString = "MultiPoint";
        break;
    case MFnParticleSystem::kMultiStreak:
        typeString = "MultiStreak";
        break;
    case MFnParticleSystem::kNumeric:
        typeString = "Numeric";
        break;
    case MFnParticleSystem::kPoints:
        typeString = "Points";
        break;
    case MFnParticleSystem::kSpheres:
        typeString = "Spheres";
        break;
    case MFnParticleSystem::kSprites:
        typeString = "Sprites";
        break;
    case MFnParticleSystem::kStreak:
        typeString = "Streak";
        break;
    default:
        typeString = "Particle system";
        assert( false );
        break;
    }

    char buffer[256];

    sprintf( buffer, "%s \"%s\" has %u primitives.", typeString, name.asChar(), count );
    MGlobal::displayInfo( buffer );

    unsigned i;

    MIntArray ids;
    ps.particleIds( ids );

    sprintf( buffer, "count : %u ", count );
    MGlobal::displayInfo( buffer );
    sprintf( buffer, "%u ids.", ids.length() );
    MGlobal::displayInfo( buffer );

    assert( ids.length() == count );
    for( i=0; i<ids.length(); i++ )
    {
        sprintf( buffer, "id %d  ", ids[i] );
        MGlobal::displayInfo( buffer );
    }

    MVectorArray positions;
    ps.position( positions );
    assert( positions.length() == count );
    for( i=0; i<positions.length(); i++ )
    {
        MVector& p = positions[i];
        sprintf( buffer, "pos %f %f %f  ", p[0], p[1], p[2] );
        MGlobal::displayInfo( buffer );
    }

    MVectorArray vels;
    ps.velocity( vels );
    assert( vels.length() == count );
    for( i=0; i<vels.length(); i++ )
    {
        const MVector& v = vels[i];
        sprintf( buffer, "vel %f %f %f  ", v[0], v[1], v[2] );
        MGlobal::displayInfo( buffer );
    }

    MVectorArray accs;
    ps.acceleration( accs );
    assert( accs.length() == count );
    for( i=0; i<accs.length(); i++ )
    {
        const MVector& a = accs[i];
        sprintf( buffer, "acc %f %f %f  ", a[0], a[1], a[2] );
        MGlobal::displayInfo( buffer );
    }

    bool flag = ps.isDeformedParticleShape(&stat);
    CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!");
    if( flag ) {
            MObject obj = ps.originalParticleShape(&stat);
        CHECKRESULT(stat,"MFnParticleSystem::originalParticleShape() failed!");
        if( obj != MObject::kNullObj ) {
                MFnParticleSystem ps( obj );
            sprintf( buffer, "original particle shape : %s ", ps.particleName().asChar() );
            MGlobal::displayInfo( buffer );
        }
    }

    flag = ps.isDeformedParticleShape(&stat);
    CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!");
    if( !flag ) {
            MObject obj = ps.deformedParticleShape(&stat);
        CHECKRESULT(stat,"MFnParticleSystem::deformedParticleShape() failed!");
        if( obj != MObject::kNullObj ) {
                MFnParticleSystem ps( obj );
            sprintf( buffer, "deformed particle shape : %s ", ps.particleName().asChar() );
            MGlobal::displayInfo( buffer );
        }
    }

    if( ids.length() == positions.length() &&
        ids.length() == vels.length()      &&
        ids.length() == accs.length()       ) { 
            setResult( int(ids.length()) );
    } else {
            setResult( int(-1) );
    }

    return MS::kSuccess;
}


//
//

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


MStatus initializePlugin( MObject obj )
{
    MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");

    MStatus status = plugin.registerCommand(mCommandName,
                                            particleSystemInfoCmd::creator );
    if (!status) 
        status.perror("registerCommand");

    return status;
}


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

    MStatus status = plugin.deregisterCommand(mCommandName);
    if (!status) 
        status.perror("deregisterCommand");

    return status;
}