particleAttrNode.cpp
#include <particleAttrNode.h>
#include <maya/MStatus.h>
#include <maya/MObject.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MPlug.h>
#include <maya/MVector.h>
#include <maya/MDoubleArray.h>
#include <maya/MVectorArray.h>
#include <maya/MPlugArray.h>
#include <maya/MPointArray.h>
#include <maya/MFnDoubleArrayData.h>
#include <maya/MFnVectorArrayData.h>
#include <maya/MFnMesh.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MDynamicsUtil.h>
MTypeId particleAttrNode::id = 0x81036;
MObject particleAttrNode::outPositionPP;
MObject particleAttrNode::particleCount;
particleAttrNode::particleAttrNode()
{}
particleAttrNode::~particleAttrNode()
{}
void* particleAttrNode::creator()
{
return new particleAttrNode();
}
MStatus particleAttrNode::initialize()
{
MStatus status = MS::kSuccess;
MFnTypedAttribute typedAttrFn;
MVectorArray defaultVectArray;
MFnVectorArrayData vectArrayDataFn;
vectArrayDataFn.create( defaultVectArray );
typedAttrFn.create( "outPosition",
"opos",
MFnData::kVectorArray,
vectArrayDataFn.object(),
&status );
typedAttrFn.setWritable(false);
typedAttrFn.setStorable(false);
outPositionPP = typedAttrFn.object();
addAttribute( outPositionPP );
MFnNumericAttribute numAttrFn;
numAttrFn.create( "particleCount", "pc", MFnNumericData::kInt );
particleCount = numAttrFn.object();
addAttribute( particleCount );
attributeAffects( computeNode, outPositionPP );
attributeAffects( particleCount, outPositionPP );
return status;
}
MStatus particleAttrNode::compute( const MPlug& plug, MDataBlock& block )
{
MStatus status = MS::kUnknownParameter;
if( (plug.attribute() == outColorPP) || (plug.attribute() == outValuePP) )
{
status = compute2DTexture( plug, block );
}
else if( plug.attribute() == outPositionPP )
{
status = computeMesh( plug, block );
}
return status;
}
MStatus particleAttrNode::compute2DTexture( const MPlug& plug, MDataBlock& block )
{
MStatus status = MS::kSuccess;
block.inputValue( computeNodeColor );
block.inputValue( computeNodeColorR );
block.inputValue( computeNodeColorG );
block.inputValue( computeNodeColorB );
bool doUcoord = false;
bool doVcoord = false;
bool doOutColor = ( plug.attribute() == outColorPP );
bool doOutValue = ( plug.attribute() == outValuePP );
MFnDoubleArrayData dataDoubleArrayFn;
MObject uCoordD = block.inputValue( uCoordPP ).data();
status = dataDoubleArrayFn.setObject( uCoordD );
MDoubleArray uAry;
if( status == MS::kSuccess )
{
uAry = dataDoubleArrayFn.array();
if (uAry.length())
{
doUcoord = true;
}
}
status = MS::kSuccess;
MObject vCoordD = block.inputValue( vCoordPP ).data();
status = dataDoubleArrayFn.setObject( vCoordD );
MDoubleArray vAry;
if( status == MS::kSuccess )
{
vAry = dataDoubleArrayFn.array();
if (vAry.length())
{
doVcoord = true;
}
}
status = MS::kSuccess;
MFnVectorArrayData dataVectorArrayFn;
MVectorArray outColorAry;
if( doOutColor )
{
MObject colorD = block.outputValue( outColorPP ).data();
status = dataVectorArrayFn.setObject( colorD );
if( status == MS::kSuccess )
{
outColorAry = dataVectorArrayFn.array();
}
}
status = MS::kSuccess;
MDoubleArray outValueAry;
if( doOutValue )
{
MObject valueD = block.outputValue( outValuePP ).data();
status = dataDoubleArrayFn.setObject( valueD );
if( status == MS::kSuccess )
{
outValueAry = dataDoubleArrayFn.array();
}
}
unsigned int uCount = ( doUcoord ? uAry.length() : 0 );
unsigned int vCount = ( doVcoord ? vAry.length() : 0 );
unsigned int count = ( (uCount) > (vCount) ? (uCount) : (vCount) );
if( doOutColor ) outColorAry.setLength( count );
if( doOutValue ) outValueAry.setLength( count );
bool hasTextureNode =
MDynamicsUtil::hasValidDynamics2dTexture( thisMObject(),
computeNode );
if( hasTextureNode )
{
MDynamicsUtil::evalDynamics2dTexture( thisMObject(),
computeNode,
uAry,
vAry,
&outColorAry,
&outValueAry );
const double& minValue = block.inputValue( outMinValue ).asDouble();
const double& maxValue = block.inputValue( outMaxValue ).asDouble();
if( (minValue != 0.0) || (maxValue != 1.0) )
{
double r = maxValue - minValue;
if( doOutValue )
{
for( unsigned int i = 0; i < count; i++ )
{
outValueAry[i] = (r * outValueAry[i]) + minValue;
}
}
if( doOutColor )
{
MVector minVector( minValue, minValue, minValue );
for( unsigned int i = 0; i < count; i++ )
{
outColorAry[i] = (r * outColorAry[i]) + minVector;
}
}
}
}
else
{
for( unsigned int i = 0; i < count; i++ )
{
MVector clr( 0.0, 0.0, 0.0 );
if( doOutColor )
{
outColorAry[i] = clr;
}
if( doOutValue )
{
outValueAry[i] = clr.x;
}
}
}
dataVectorArrayFn.set( outColorAry );
dataDoubleArrayFn.set( outValueAry );
return MS::kSuccess;
}
MStatus particleAttrNode::computeMesh( const MPlug& plug, MDataBlock& block )
{
MStatus status = MS::kSuccess;
MPlug compPlug( thisMObject(), computeNode );
MPlugArray conns;
compPlug.connectedTo( conns, true, false, &status );
if( conns.length() <= 0 )
{
return MS::kFailure;
}
MPlug conn = conns[0];
MObject compNode = conn.node();
MFnMesh meshFn( compNode, &status );
if( status != MS::kSuccess )
{
return MS::kFailure;
}
MPointArray points;
meshFn.getPoints( points );
unsigned int nPoints = points.length();
unsigned int nParticles = 0;
int nSignedPart = block.inputValue( particleCount ).asInt();
if( nSignedPart > 0 )
{
nParticles = nSignedPart;
}
MFnVectorArrayData dataVectorArrayFn;
MVectorArray outPosArray;
MObject posD = block.outputValue( outPositionPP ).data();
status = dataVectorArrayFn.setObject( posD );
if( status == MS::kSuccess )
{
outPosArray = dataVectorArrayFn.array();
}
outPosArray.setLength( nParticles );
for( unsigned int i = 0; i < nParticles; i++ )
{
unsigned int index = i;
if( nParticles > nPoints )
{
index = i % nPoints;
}
MPoint point = points[index];
MVector pos( point.x, point.y, point.z );
outPosArray[i] = pos;
}
dataVectorArrayFn.set( outPosArray );
return MS::kSuccess;
}