#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::doModifyPoly()
{
if( isCommandDataValid() )
{
collectNodeState();
if( !fHasHistory && !fHasRecordHistory )
{
MObject meshNode = fDagPath.node();
cacheMeshData();
cacheMeshTweaks();
status = directModifier( meshNode );
}
else
{
createModifierNode( modifierNode );
initModifierNode( modifierNode );
status = connectNodes( modifierNode );
}
}
return status;
}
MStatus polyModifierCmd::redoModifyPoly()
{
if( !fHasHistory && !fHasRecordHistory )
{
MObject meshNode = fDagPath.node();
status = directModifier( meshNode );
}
else
{
if( !fHasHistory )
{
fDagModifier.doIt();
}
status = fDGModifier.doIt();
}
return status;
}
MStatus polyModifierCmd::undoModifyPoly()
{
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()
{
fDagPath.extendToShape();
MObject meshNodeShape = fDagPath.node();
fHasTweaks = false;
{
"tweakPlug.isArray() -- tweakPlug is not an array plug" );
int i;
for( i = 0; i < numElements; i++ )
{
{
getFloat3PlugValue( tweak, tweakData );
{
fHasTweaks = true;
break;
}
}
}
}
int result;
fHasRecordHistory = (0 != result);
}
{
if( fModifierNodeTypeInitialized || fModifierNodeNameInitialized )
{
if( fModifierNodeTypeInitialized )
{
modifierNode = fDGModifier.createNode( fModifierNodeType, &status );
}
else if( fModifierNodeNameInitialized )
{
modifierNode = fDGModifier.createNode( fModifierNodeName, &status );
}
inMeshAttr = depNodeFn.
attribute(
"inMesh" );
outMeshAttr = depNodeFn.
attribute(
"outMesh" );
{
displayError( "Invalid Modifier Node: inMesh and outMesh attributes are required." );
}
}
return status;
}
MStatus polyModifierCmd::processMeshNode( modifyPolyData& data )
{
data.meshNodeShape = fDagPath.node();
"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 )
{
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
{
data.upstreamNodeTransform = dagNodeFn.
duplicate(
false,
false );
dagNodeFn.
setObject( data.upstreamNodeTransform );
"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 );
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;
}
modifyPolyData& data )
{
data.modifierNodeSrcAttr = depNodeFn.
attribute(
"outMesh" );
data.modifierNodeDestAttr = depNodeFn.
attribute(
"inMesh" );
return status;
}
MStatus polyModifierCmd::processTweaks( modifyPolyData& data )
{
fTweakIndexArray.clear();
fTweakVectorArray.clear();
if( fHasTweaks )
{
unsigned i;
unsigned j;
unsigned k;
data.tweakNode = fDGModifier.createNode( "polyTweak" );
data.tweakNodeSrcAttr = depNodeFn.
attribute(
"output" );
data.tweakNodeDestAttr = depNodeFn.
attribute(
"inputPolymesh" );
tweakNodeTweakAttr = depNodeFn.
attribute(
"tweak" );
meshTweakPlug = depNodeFn.
findPlug(
"pnts" );
MStatusAssert( (meshTweakPlug.
isArray()),
"meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
for( i = 0; i < numElements; i++ )
{
{
tweakDataArray.
append( tweakData );
getFloat3PlugValue( tweak, tweakVector );
fTweakIndexArray.append( logicalIndex );
fTweakVectorArray.append( tweakVector );
"tweak.isCompound() -- Element tweak plug is not compound" );
for( j = 0; j < numChildren; j++ )
{
tweakChild = tweak.
child(j);
{
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);
}
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.isCompound() -- Element plug, 'tweak', is not compound" );
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;
}
{
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()
{
MObject meshNode = fDagPath.node();
MPlug dupMeshNodeOutMeshPlug;
dupMeshNodeOutMeshPlug = depNodeFn.
findPlug(
"outMesh", &status );
MCheckStatus( status, "Could not retrieve outMesh" );
status = dupMeshNodeOutMeshPlug.
getValue( fMeshData );
MCheckStatus( status, "Could not retrieve meshData" );
return status;
}
MStatus polyModifierCmd::cacheMeshTweaks()
{
fTweakIndexArray.clear();
fTweakVectorArray.clear();
if( fHasTweaks )
{
MObject meshNode = fDagPath.node();
unsigned i;
meshTweakPlug = depNodeFn.
findPlug(
"pnts" );
MStatusAssert( (meshTweakPlug.
isArray()),
"meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
for( i = 0; i < numElements; i++ )
{
{
getFloat3PlugValue( tweak, tweakVector );
fTweakIndexArray.append( logicalIndex );
fTweakVectorArray.append( tweakVector );
}
}
}
return status;
}
MStatus polyModifierCmd::undoCachedMesh()
{
MStatusAssert( (fHasRecordHistory), "fHasRecordHistory == true" );
if( !fHasHistory )
{
MPlug meshNodeOutMeshPlug;
MPlug dupMeshNodeSrcPlug;
meshNodeShape = fDagPath.node();
dupMeshNodeShape = fDuplicateDagPath.node();
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" );
dupMeshNodeSrcPlug = depNodeFn.
findPlug(
"outMesh", &status );
MCheckStatus( status, "Could not retrieve outMesh" );
if( fHasTweaks )
{
dgModifier.
connect( dupMeshNodeSrcPlug, meshNodeDestPlug );
status = dgModifier.
doIt();
MCheckStatus( status, "Could not connect dupMeshNode -> meshNode" );
cmd += meshNodeName;
cmd += ".inMesh";
MCheckStatus( status, "Could not force DG eval" );
}
else
{
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()
{
if( fHasTweaks )
{
meshNodeShape = fDagPath.node();
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++ )
{
getFloat3asMObject( fTweakVectorArray[i], tweakData );
}
}
return status;
}
MStatus polyModifierCmd::undoDirectModifier()
{
MObject meshNode = fDagPath.node();
if( fHasTweaks )
{
MPlug meshNodeInMeshPlug = depNodeFn.
findPlug(
"inMesh", &status );
MCheckStatus( status, "Could not retrieve inMesh" );
MPlug dupMeshNodeOutMeshPlug = depNodeFn.
findPlug(
"outMesh", &status );
MCheckStatus( status, "Could not retrieve outMesh" );
status = dupMeshNodeOutMeshPlug.
setValue( fMeshData );
dgModifier.
connect( dupMeshNodeOutMeshPlug, meshNodeInMeshPlug );
status = dgModifier.
doIt();
MCheckStatus( status, "Could not connect dupMeshNode -> meshNode" );
cmd += meshNodeName;
cmd += ".inMesh";
MCheckStatus( status, "Could not force DG eval" );
status = undoTweakProcessing();
}
else
{
MPlug meshNodeOutMeshPlug = depNodeFn.
findPlug(
"outMesh", &status );
MCheckStatus( status, "Could not retrieve outMesh" );
status = meshNodeOutMeshPlug.
setValue( fMeshData );
MCheckStatus( status, "Could not set meshData" );
}
return status;
}
{
numDataFn.getData( value[0], value[1], value[2] );
}
{
numDataFn.
setData( value[0], value[1], value[2] );
}