#include "polyModifierCmd.h"
#include <maya/MGlobal.h>
#include <maya/MFloatVector.h>
#include <maya/MObjectArray.h>
#include <maya/MPlugArray.h>
#include <maya/MIOStream.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnNumericData.h>
#ifdef _DEBUG
#       define MCheckStatus(status,message)                     \
                if( MS::kSuccess != status ) {                  \
                        MString error("Status failed: ");       \
                        error += message;                                       \
                        MGlobal::displayError(error);           \
                        return status;                                          \
                }
#else
#       define MCheckStatus(status,message)
#endif
#ifdef _DEBUG
#       define MAssert(state,message)                                   \
                if( !state ) {                                                          \
                        MString error("Assertion failed: ");    \
                        error += message;                                               \
                        MGlobal::displayError(error);                   \
                        return;                                                                 \
                }
#else
#       define MAssert(state,message)
#endif
#ifdef _DEBUG
#       define MStatusAssert(state,message)                             \
                if( !state ) {                                                          \
                        MString error("Assertion failed: ");    \
                        error += message;                                               \
                        MGlobal::displayError(error);                   \
                        return MS::kFailure;                                    \
                }
#else
#       define MStatusAssert(state,message)
#endif
polyModifierCmd::polyModifierCmd()
{
        fDagPathInitialized = false;
        fModifierNodeTypeInitialized = false;
        fModifierNodeNameInitialized = false;
}
polyModifierCmd::~polyModifierCmd()
{}
MStatus polyModifierCmd::initModifierNode( MObject  )
{
        return MS::kSuccess;
}
MStatus polyModifierCmd::directModifier( MObject  )
{
        return MS::kSuccess;
}
MStatus polyModifierCmd::doModifyPoly()
{
        MStatus status = MS::kFailure;
        if( isCommandDataValid() )
        {
                
                
                collectNodeState();
                if( !fHasHistory && !fHasRecordHistory )
                {
                        MObject meshNode = fDagPath.node();
                        
                        
                        cacheMeshData();
                        cacheMeshTweaks();
                        
                        
                        status = directModifier( meshNode );
                }
                else
                {
                        MObject modifierNode;
                        createModifierNode( modifierNode );
                        initModifierNode( modifierNode );
                        status = connectNodes( modifierNode );
                }
        }
        return status;
}
MStatus polyModifierCmd::redoModifyPoly()
{
        MStatus status = MS::kSuccess;
        if( !fHasHistory && !fHasRecordHistory )
        {
                MObject meshNode = fDagPath.node();
                
                
                
                status = directModifier( meshNode );
        }
        else
        {
                
                
                if( !fHasHistory )
                {
                        fDagModifier.doIt();
                }
                status = fDGModifier.doIt();
        }
        return status;
}
MStatus polyModifierCmd::undoModifyPoly()
{
        MStatus status = MS::kSuccess;
        if( !fHasHistory && !fHasRecordHistory )
        {
                status = undoDirectModifier();
        }
        else
        {
                fDGModifier.undoIt();
                
                
                
                
                if( !fHasHistory )
                {
                        status = undoCachedMesh();
                        MCheckStatus( status, "undoCachedMesh" );
                        fDagModifier.undoIt();
                }
                status = undoTweakProcessing();
                MCheckStatus( status, "undoTweakProcessing" );
        }
        return status;
}
bool polyModifierCmd::isCommandDataValid()
{
        bool valid = true;
        
        
        if( fDagPathInitialized )
        {
                fDagPath.extendToShape();
                if( !fDagPath.isValid() || fDagPath.apiType() != MFn::kMesh )
                {
                        valid = false;
                }
        }
        else
        {
                valid = false;
        }
        
        
        if( !fModifierNodeTypeInitialized && !fModifierNodeNameInitialized )
        {
                valid = false;
        }
        return valid;
}
void polyModifierCmd::collectNodeState()
{
        MStatus status;
        
        
        
        
        
        
        fDagPath.extendToShape();
        MObject meshNodeShape = fDagPath.node();
        MFnDependencyNode depNodeFn;
        depNodeFn.setObject( meshNodeShape );
        MPlug inMeshPlug = depNodeFn.findPlug( "inMesh" );
        fHasHistory = inMeshPlug.isConnected();
        
        
        
        
        fHasTweaks = false;
        MPlug tweakPlug = depNodeFn.findPlug( "pnts" );
        if( !tweakPlug.isNull() )
        {
                
                
                MAssert( (tweakPlug.isArray()),
                                 "tweakPlug.isArray() -- tweakPlug is not an array plug" );
                MPlug tweak;
                MFloatVector tweakData;
                int i;
                int numElements = tweakPlug.numElements();
                for( i = 0; i < numElements; i++ )
                {
                        tweak = tweakPlug.elementByPhysicalIndex( i, &status );
                        if( status == MS::kSuccess && !tweak.isNull() )
                        {
                                getFloat3PlugValue( tweak, tweakData );
                                if( 0 != tweakData.x ||
                                        0 != tweakData.y ||
                                        0 != tweakData.z )
                                {
                                        fHasTweaks = true;
                                        break;
                                }
                        }
                }
        }
        int result;
        MGlobal::executeCommand( "constructionHistory -q -tgl", result );
        fHasRecordHistory = (0 != result);
}
MStatus polyModifierCmd::createModifierNode( MObject& modifierNode )
{
        MStatus status = MS::kFailure;
        if( fModifierNodeTypeInitialized || fModifierNodeNameInitialized )
        {
                if( fModifierNodeTypeInitialized )
                {
                        modifierNode = fDGModifier.createNode( fModifierNodeType, &status );
                }
                else if( fModifierNodeNameInitialized )
                {
                        modifierNode = fDGModifier.createNode( fModifierNodeName, &status );
                }
                
                
                
                MFnDependencyNode depNodeFn( modifierNode );
                MObject inMeshAttr;
                MObject outMeshAttr;
                inMeshAttr = depNodeFn.attribute( "inMesh" );
                outMeshAttr = depNodeFn.attribute( "outMesh" );
                if( inMeshAttr.isNull() || outMeshAttr.isNull() )
                {
                        displayError( "Invalid Modifier Node: inMesh and outMesh attributes are required." );
                        status = MS::kFailure;
                }
        }
        
        return status;
}
MStatus polyModifierCmd::processMeshNode( modifyPolyData& data )
{
        MStatus status = MS::kSuccess;
        
        
        
        MFnDagNode dagNodeFn;
        
        
        data.meshNodeShape = fDagPath.node();
        dagNodeFn.setObject( data.meshNodeShape );
        
        
        MStatusAssert( (0 < dagNodeFn.parentCount()),
                                   "0 < dagNodeFn.parentCount() -- meshNodeshape has no parent transform" );
        data.meshNodeTransform = dagNodeFn.parent(0);
        
        data.meshNodeDestPlug = dagNodeFn.findPlug( "inMesh" );
        data.meshNodeDestAttr = data.meshNodeDestPlug.attribute();
        return status;
}
MStatus polyModifierCmd::processUpstreamNode( modifyPolyData& data )
{
        MStatus status = MS::kSuccess;
        
        
        
        
        
        MFnDependencyNode       depNodeFn;
        MFnDagNode                      dagNodeFn;
        
        
        
        
        
        
        
        
        
        MPlugArray tempPlugArray;
        if( fHasHistory )
        {
                
                
                
                
                data.meshNodeDestPlug.connectedTo( tempPlugArray, true, false);
                
                
                MStatusAssert( (tempPlugArray.length() == 1),
                                           "tempPlugArray.length() == 1 -- 0 or >1 connections on meshNodeShape.inMesh" );
                data.upstreamNodeSrcPlug = tempPlugArray[0];
                
                
                
                data.upstreamNodeShape = data.upstreamNodeSrcPlug.node();
                depNodeFn.setObject( data.upstreamNodeShape );
                data.upstreamNodeSrcAttr = data.upstreamNodeSrcPlug.attribute();
                
                
                
                fDGModifier.disconnect( data.upstreamNodeSrcPlug,
                                                                data.meshNodeDestPlug );
        }
        else    
        {
                
                
                
                
                
                
                dagNodeFn.setObject( data.meshNodeShape );
                data.upstreamNodeTransform = dagNodeFn.duplicate( false, false );
                dagNodeFn.setObject( data.upstreamNodeTransform );
                
                
                MStatusAssert( (0 < dagNodeFn.childCount()),
                                           "0 < dagNodeFn.childCount() -- Duplicate meshNode transform has no shape." );
                data.upstreamNodeShape = dagNodeFn.child(0);
                
                
                status = fDagModifier.reparentNode( data.upstreamNodeShape, data.meshNodeTransform );
                MCheckStatus( status, "reparentNode" );
                
                
                
                
                
                status = fDagModifier.doIt();
                MCheckStatus( status, "fDagModifier.doIt()" );
                
                
                
                dagNodeFn.setObject( data.upstreamNodeShape );
                dagNodeFn.setIntermediateObject( true );
                
                
                data.upstreamNodeSrcAttr = dagNodeFn.attribute( "outMesh" );
                data.upstreamNodeSrcPlug = dagNodeFn.findPlug( "outMesh", &status );
                
                
                status = fDagModifier.deleteNode( data.upstreamNodeTransform );
                MCheckStatus( status, "deleteNode" );
                
                
                
                
                
                
                status = fDagModifier.doIt();
                MCheckStatus( status, "fDagModifier.doIt()" );
                
                
                dagNodeFn.getPath( fDuplicateDagPath );
        }
        return status;
}
MStatus polyModifierCmd::processModifierNode( MObject modifierNode,
                                                                                          modifyPolyData& data )
{
        MStatus status = MS::kSuccess;
        MFnDependencyNode depNodeFn ( modifierNode );
        data.modifierNodeSrcAttr = depNodeFn.attribute( "outMesh" );
        data.modifierNodeDestAttr = depNodeFn.attribute( "inMesh" );
        return status;
}
MStatus polyModifierCmd::processTweaks( modifyPolyData& data )
{
        MStatus status = MS::kSuccess;
        
        
        fTweakIndexArray.clear();
        fTweakVectorArray.clear();
        
        
        
        
        
        
        
        
        if( fHasTweaks )
        {
                
                
                MFnDependencyNode depNodeFn;
                
                
                MPlug   meshTweakPlug;
                MPlug   upstreamTweakPlug;
                MObject tweakNodeTweakAttr;
                
                
                MPlug                           tweak;
                MPlug                           tweakChild;
                MObject                         tweakData;
                MObjectArray            tweakDataArray;
                MFloatVector            tweakVector;
                MIntArray                       tweakSrcConnectionCountArray;
                MPlugArray                      tweakSrcConnectionPlugArray;
                MIntArray                       tweakDstConnectionCountArray;
                MPlugArray                      tweakDstConnectionPlugArray;
                MPlugArray                      tempPlugArray;
                unsigned i;
                unsigned j;
                unsigned k;
                
                
                data.tweakNode = fDGModifier.createNode( "polyTweak" );
                depNodeFn.setObject( data.tweakNode );
                data.tweakNodeSrcAttr = depNodeFn.attribute( "output" );
                data.tweakNodeDestAttr = depNodeFn.attribute( "inputPolymesh" );
                tweakNodeTweakAttr = depNodeFn.attribute( "tweak" );
                depNodeFn.setObject( data.meshNodeShape );
                meshTweakPlug = depNodeFn.findPlug( "pnts" );
                
                
                MStatusAssert( (meshTweakPlug.isArray()),
                                           "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
                unsigned numElements = meshTweakPlug.numElements();
                
                
                for( i = 0; i < numElements; i++ )
                {
                        
                        
                        
                        
                        tweak = meshTweakPlug.elementByPhysicalIndex(i);
                        
                        
                        
                        if( !tweak.isNull() )
                        {
                                
                                
                                unsigned logicalIndex = tweak.logicalIndex();
                                
                                
                                tweak.getValue( tweakData );
                                tweakDataArray.append( tweakData );
                                getFloat3PlugValue( tweak, tweakVector );
                                fTweakIndexArray.append( logicalIndex );
                                fTweakVectorArray.append( tweakVector );
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                MStatusAssert( (tweak.isCompound()),
                                                           "tweak.isCompound() -- Element tweak plug is not compound" );
                                unsigned numChildren = tweak.numChildren();
                                for( j = 0; j < numChildren; j++ )
                                {
                                        tweakChild = tweak.child(j);
                                        if( tweakChild.isConnected() )
                                        {
                                                
                                                
                                                tempPlugArray.clear();
                                                if( tweakChild.connectedTo( tempPlugArray, false, true ) )
                                                {
                                                        unsigned numSrcConnections = tempPlugArray.length();
                                                        tweakSrcConnectionCountArray.append( numSrcConnections );
                                                        for( k = 0; k < numSrcConnections; k++ )
                                                        {
                                                                tweakSrcConnectionPlugArray.append( tempPlugArray[k] );
                                                                fDGModifier.disconnect( tweakChild, tempPlugArray[k] );
                                                        }
                                                }
                                                else
                                                {
                                                        tweakSrcConnectionCountArray.append(0);
                                                }
                                                
                                                
                                                tempPlugArray.clear();
                                                if( tweakChild.connectedTo( tempPlugArray, true, false ) )
                                                {
                                                        
                                                        
                                                        MStatusAssert( (tempPlugArray.length() == 1),
                                                                                   "tempPlugArray.length() == 1 -- 0 or >1 connections on tweakChild" );
                                                        tweakDstConnectionCountArray.append(1);
                                                        tweakDstConnectionPlugArray.append( tempPlugArray[0] );
                                                        fDGModifier.disconnect( tempPlugArray[0], tweakChild );
                                                }
                                                else
                                                {
                                                        tweakDstConnectionCountArray.append(0);
                                                }
                                        }
                                        else
                                        {
                                                tweakSrcConnectionCountArray.append(0);
                                                tweakDstConnectionCountArray.append(0);
                                        }
                                }
                        }
                }
                
                
                MPlug polyTweakPlug( data.tweakNode, tweakNodeTweakAttr );
                unsigned numTweaks = fTweakIndexArray.length();
                int srcOffset = 0;
                int dstOffset = 0;
                for( i = 0; i < numTweaks; i++ )
                {
                        
                        
                        tweak = polyTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
                        tweak.setValue( tweakDataArray[i] );
                        
                        
                        MStatusAssert( (tweak.isCompound()),
                                                   "tweak.isCompound() -- Element plug, 'tweak', is not compound" );
                        unsigned numChildren = tweak.numChildren();
                        for( j = 0; j < numChildren; j++ )
                        {
                                tweakChild = tweak.child(j);
                                
                                
                                if( 0 < tweakSrcConnectionCountArray[i*numChildren + j] )
                                {
                                        for( k = 0;
                                                 k < (unsigned) tweakSrcConnectionCountArray[i*numChildren + j];
                                                 k++ )
                                        {
                                                fDGModifier.connect( tweakChild,
                                                                                         tweakSrcConnectionPlugArray[srcOffset] );
                                                srcOffset++;
                                        }
                                }
                                                
                                
                                
                                if( 0 < tweakDstConnectionCountArray[i*numChildren + j] )
                                {
                                        fDGModifier.connect( tweakDstConnectionPlugArray[dstOffset],
                                                                                 tweakChild );
                                        dstOffset++;
                                }
                        }
                }
      }
        return status;
}
MStatus polyModifierCmd::connectNodes( MObject modifierNode )
{
        MStatus status;
        
        
        modifyPolyData data;
        
        
        status = processMeshNode( data );
        MCheckStatus( status, "processMeshNode" );
        
        
        status = processUpstreamNode( data );
        MCheckStatus( status, "processUpstreamNode" );
        
        
        status = processModifierNode( modifierNode,
                                                 data );
        MCheckStatus( status, "processModifierNode" );
        
        
        status = processTweaks( data );
        MCheckStatus( status, "processTweaks" );
        
        
        if( fHasTweaks )
        {
                MPlug tweakDestPlug( data.tweakNode, data.tweakNodeDestAttr );
                status = fDGModifier.connect( data.upstreamNodeSrcPlug, tweakDestPlug );
                MCheckStatus( status, "upstream-tweak connect failed" );
                MPlug tweakSrcPlug( data.tweakNode, data.tweakNodeSrcAttr );
                MPlug modifierDestPlug( modifierNode, data.modifierNodeDestAttr );
                status = fDGModifier.connect( tweakSrcPlug, modifierDestPlug );
                MCheckStatus( status, "tweak-modifier connect failed" );
        }
        else
        {
                MPlug modifierDestPlug( modifierNode, data.modifierNodeDestAttr );
                status = fDGModifier.connect( data.upstreamNodeSrcPlug, modifierDestPlug );
                MCheckStatus( status, "upstream-modifier connect failed" );
        }
        MPlug modifierSrcPlug( modifierNode, data.modifierNodeSrcAttr );
        MPlug meshDestAttr( data.meshNodeShape, data.meshNodeDestAttr );
        status = fDGModifier.connect( modifierSrcPlug, meshDestAttr );
        MCheckStatus( status, "modifier-mesh connect failed" );
        
        status = fDGModifier.doIt();
        return status;
}
MStatus polyModifierCmd::cacheMeshData()
{
        MStatus status = MS::kSuccess;
        MFnDependencyNode depNodeFn;
        MFnDagNode dagNodeFn;
        MObject meshNode = fDagPath.node();
        MObject dupMeshNode;
        MPlug dupMeshNodeOutMeshPlug;
        
        
        dagNodeFn.setObject( meshNode );
        dupMeshNode = dagNodeFn.duplicate();
        MDagPath dupMeshDagPath;
        MDagPath::getAPathTo( dupMeshNode, dupMeshDagPath );
        dupMeshDagPath.extendToShape();
        depNodeFn.setObject( dupMeshDagPath.node() );
        dupMeshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
        MCheckStatus( status, "Could not retrieve outMesh" );
        
        
        status = dupMeshNodeOutMeshPlug.getValue( fMeshData );
        MCheckStatus( status, "Could not retrieve meshData" );
        
        
        MGlobal::deleteNode( dupMeshNode );
        return status;
}
MStatus polyModifierCmd::cacheMeshTweaks()
{
        MStatus status = MS::kSuccess;
        
        
        fTweakIndexArray.clear();
        fTweakVectorArray.clear();
        
        
        if( fHasTweaks )
        {
                
                
                MFnDependencyNode depNodeFn;
                MObject meshNode = fDagPath.node();
                MPlug   meshTweakPlug;
                
                
                MPlug                           tweak;
                MPlug                           tweakChild;
                MObject                         tweakData;
                MObjectArray            tweakDataArray;
                MFloatVector            tweakVector;
                MPlugArray                      tempPlugArray;
                unsigned i;
                depNodeFn.setObject( meshNode );
                meshTweakPlug = depNodeFn.findPlug( "pnts" );
                
                
                MStatusAssert( (meshTweakPlug.isArray()),
                                           "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
                unsigned numElements = meshTweakPlug.numElements();
                
                
                for( i = 0; i < numElements; i++ )
                {
                        
                        
                        
                        
                        tweak = meshTweakPlug.elementByPhysicalIndex(i);
                        
                        
                        
                        if( !tweak.isNull() )
                        {
                                
                                
                                unsigned logicalIndex = tweak.logicalIndex();
                                
                                
                                getFloat3PlugValue( tweak, tweakVector );
                                fTweakIndexArray.append( logicalIndex );
                                fTweakVectorArray.append( tweakVector );
                        }
                }
        }
        return status;
}
MStatus polyModifierCmd::undoCachedMesh()
{
        MStatus status;
        
        
        
        MStatusAssert( (fHasRecordHistory), "fHasRecordHistory == true" );
        if( !fHasHistory )
        {
                MFnDependencyNode depNodeFn;
                MString meshNodeName;
                MObject meshNodeShape;
                MPlug   meshNodeDestPlug;
                MPlug   meshNodeOutMeshPlug;
                MObject dupMeshNodeShape;
                MPlug   dupMeshNodeSrcPlug;
                meshNodeShape = fDagPath.node();
                dupMeshNodeShape = fDuplicateDagPath.node();
                depNodeFn.setObject( meshNodeShape );
                meshNodeName = depNodeFn.name();
                meshNodeDestPlug = depNodeFn.findPlug( "inMesh", &status );
                MCheckStatus( status, "Could not retrieve inMesh" );
                meshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
                MCheckStatus( status, "Could not retrieve outMesh" );
                depNodeFn.setObject( dupMeshNodeShape );
                dupMeshNodeSrcPlug = depNodeFn.findPlug( "outMesh", &status );
                MCheckStatus( status, "Could not retrieve outMesh" );
                
                
                
                
                
                
                
                
                if( fHasTweaks )
                {
                        MDGModifier dgModifier;
                        dgModifier.connect( dupMeshNodeSrcPlug, meshNodeDestPlug );
                        status = dgModifier.doIt();
                        MCheckStatus( status, "Could not connect dupMeshNode -> meshNode" );
                        
                        
                        MString cmd( "dgeval -src " );
                        cmd += meshNodeName;
                        cmd += ".inMesh";
                        status = MGlobal::executeCommand( cmd, false, false );
                        MCheckStatus( status, "Could not force DG eval" );
                        
                        
                        dgModifier.undoIt();
                }
                else
                {
                        MObject meshData;
                        status = dupMeshNodeSrcPlug.getValue( meshData );
                        MCheckStatus( status, "Could not retrieve meshData" );
                        status = meshNodeOutMeshPlug.setValue( meshData );
                        MCheckStatus( status, "Could not set outMesh" );
                }
        }
        return status;
}
MStatus polyModifierCmd::undoTweakProcessing()
{
        MStatus status = MS::kSuccess;
        if( fHasTweaks )
        {
                MFnDependencyNode depNodeFn;
                MObject meshNodeShape;
                MPlug   meshTweakPlug;
                MPlug   tweak;
                MObject tweakData;
                meshNodeShape = fDagPath.node();
                depNodeFn.setObject( meshNodeShape );
                meshTweakPlug = depNodeFn.findPlug( "pnts" );
                MStatusAssert( (meshTweakPlug.isArray()),
                                           "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
                unsigned i;
                unsigned numElements = fTweakIndexArray.length();
                for( i = 0; i < numElements; i++ )
                {
                        tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
                        getFloat3asMObject( fTweakVectorArray[i], tweakData );
                        tweak.setValue( tweakData );
                }
                
                
                
        }
        return status;
}
MStatus polyModifierCmd::undoDirectModifier()
{
        MStatus status;
        MFnDependencyNode depNodeFn;
        MFnDagNode dagNodeFn;
        MObject meshNode = fDagPath.node();
        depNodeFn.setObject( meshNode );
        
        
        
        
        
        
        
        
        
        
        if( fHasTweaks )
        {
                
                
                depNodeFn.setObject( meshNode );
                MPlug meshNodeInMeshPlug = depNodeFn.findPlug( "inMesh", &status );
                MCheckStatus( status, "Could not retrieve inMesh" );
                MString meshNodeName = depNodeFn.name();
                
                
                dagNodeFn.setObject( meshNode );
                MObject dupMeshNode = dagNodeFn.duplicate();
                
                
                
                MDagPath dupMeshDagPath;
                MDagPath::getAPathTo( dupMeshNode, dupMeshDagPath );
                dupMeshDagPath.extendToShape();
                
                
                
                depNodeFn.setObject( dupMeshDagPath.node() );
                MPlug dupMeshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
                MCheckStatus( status, "Could not retrieve outMesh" );
                status = dupMeshNodeOutMeshPlug.setValue( fMeshData );
                
                
                MDGModifier dgModifier;
                dgModifier.connect( dupMeshNodeOutMeshPlug, meshNodeInMeshPlug );
                status = dgModifier.doIt();
                MCheckStatus( status, "Could not connect dupMeshNode -> meshNode" );
                
                
                MString cmd("dgeval -src ");
                cmd += meshNodeName;
                cmd += ".inMesh";
                status = MGlobal::executeCommand( cmd, false, false );
                MCheckStatus( status, "Could not force DG eval" );
                
                
                dgModifier.undoIt();
                MGlobal::deleteNode( dupMeshNode );
                
                
                status = undoTweakProcessing();
        }
        else
        {
                
                
                
                depNodeFn.setObject( meshNode );
                MPlug meshNodeOutMeshPlug = depNodeFn.findPlug( "outMesh", &status );
                MCheckStatus( status, "Could not retrieve outMesh" );
                status = meshNodeOutMeshPlug.setValue( fMeshData );
                MCheckStatus( status, "Could not set meshData" );
        }
        return status;
}
MStatus polyModifierCmd::getFloat3PlugValue( MPlug plug, MFloatVector & value )
{
        
        
        MObject object;
        plug.getValue( object );
        
        
        MFnNumericData numDataFn( object );
        numDataFn.getData( value[0], value[1], value[2] );
        return MS::kSuccess;
}
MStatus polyModifierCmd::getFloat3asMObject( MFloatVector value, MObject& object )
{
        
        
        MFnNumericData numDataFn;
        numDataFn.create( MFnNumericData::k3Float );
        numDataFn.setData( value[0], value[1], value[2] );
        object = numDataFn.object();
        return MS::kSuccess;
}