#include <geometrySurfaceConstraint.h>
MTypeId geometrySurfaceConstraint::id( 0x8103F );
MObject geometrySurfaceConstraint::compoundTarget;
MObject geometrySurfaceConstraint::targetGeometry;
MObject geometrySurfaceConstraint::targetWeight;
MObject geometrySurfaceConstraint::constraintParentInverseMatrix;
MObject geometrySurfaceConstraint::constraintGeometry;
geometrySurfaceConstraint::geometrySurfaceConstraint()
{
weightType = geometrySurfaceConstraintCommand::kLargestWeight;
}
geometrySurfaceConstraint::~geometrySurfaceConstraint()
{
}
void geometrySurfaceConstraint::postConstructor()
{
}
MStatus geometrySurfaceConstraint::compute( const MPlug& plug, MDataBlock& block )
{
MStatus returnStatus;
if ( plug == geometrySurfaceConstraint::constraintGeometry )
{
block.inputValue(constraintParentInverseMatrix);
MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget );
unsigned int targetArrayCount = targetArray.elementCount();
double weight,selectedWeight = 0;
if ( weightType == geometrySurfaceConstraintCommand::kSmallestWeight )
selectedWeight = FLT_MAX;
MObject selectedMesh;
unsigned int i;
for ( i = 0; i < targetArrayCount; i++ )
{
MDataHandle targetElement = targetArray.inputValue();
weight = targetElement.child(targetWeight).asDouble();
if ( !equivalent(weight,0.0))
{
if ( weightType == geometrySurfaceConstraintCommand::kLargestWeight )
{
if ( weight > selectedWeight )
{
MObject mesh = targetElement.child(targetGeometry).asMesh();
if ( !mesh.isNull() )
{
selectedMesh = mesh;
selectedWeight = weight;
}
}
}
else
{
if ( weight < selectedWeight )
{
MObject mesh = targetElement.child(targetGeometry).asMesh();
if ( !mesh.isNull() )
{
selectedMesh = mesh;
selectedWeight = weight;
}
}
}
}
targetArray.next();
}
if ( selectedMesh.isNull() )
{
block.setClean(plug);
}
else
{
MDataHandle outputConstraintGeometryHandle = block.outputValue(constraintGeometry);
outputConstraintGeometryHandle.setMObject(selectedMesh);
}
}
else
{
return MS::kUnknownParameter;
}
return MS::kSuccess;
}
const MObject geometrySurfaceConstraint::weightAttribute() const
{
return geometrySurfaceConstraint::targetWeight;
}
const MObject geometrySurfaceConstraint::targetAttribute() const
{
return geometrySurfaceConstraint::compoundTarget;
}
void geometrySurfaceConstraint::getOutputAttributes(MObjectArray& attributeArray)
{
attributeArray.clear();
attributeArray.append( geometrySurfaceConstraint::constraintGeometry );
}
void* geometrySurfaceConstraint::creator()
{
return new geometrySurfaceConstraint();
}
MStatus geometrySurfaceConstraint::initialize()
{
MFnNumericAttribute nAttr;
MStatus status;
{
MFnTypedAttribute typedAttrNotWritable;
geometrySurfaceConstraint::constraintGeometry =
typedAttrNotWritable.create( "constraintGeometry", "cg", MFnData::kMesh, &status );
if (!status) { status.perror("typedAttrNotWritable.create:cgeom"); return status;}
status = typedAttrNotWritable.setReadable(true);
if (!status) { status.perror("typedAttrNotWritable.setReadable:cgeom"); return status;}
status = typedAttrNotWritable.setWritable(false);
if (!status) { status.perror("typedAttrNotWritable.setWritable:cgeom"); return status;}
status = typedAttrNotWritable.setDisconnectBehavior(MFnAttribute::kDelete);
if (!status) { status.perror("typedAttrNotWritable.setDisconnectBehavior:cgeom"); return status;}
}
{
MFnTypedAttribute typedAttr;
geometrySurfaceConstraint::constraintParentInverseMatrix =
typedAttr.create( "constraintPim", "ci", MFnData::kMatrix, &status );
if (!status) { status.perror("typedAttr.create:matrix"); return status;}
status = typedAttr.setDisconnectBehavior(MFnAttribute::kDelete);
if (!status) { status.perror("typedAttr.setDisconnectBehavior:cgeom"); return status;}
geometrySurfaceConstraint::targetGeometry =
typedAttr.create( "targetGeometry", "tg", MFnData::kMesh, &status );
if (!status) { status.perror("typedAttr.create:tgeom"); return status;}
status = typedAttr.setDisconnectBehavior(MFnAttribute::kDelete);
if (!status) { status.perror("typedAttr.setDisconnectBehavior:cgeom"); return status;}
}
{
MFnNumericAttribute typedAttrKeyable;
geometrySurfaceConstraint::targetWeight
= typedAttrKeyable.create( "weight", "wt", MFnNumericData::kDouble, 1.0, &status );
if (!status) { status.perror("typedAttrKeyable.create:weight"); return status;}
status = typedAttrKeyable.setMin( (double) 0 );
if (!status) { status.perror("typedAttrKeyable.setMin"); return status;}
status = typedAttrKeyable.setKeyable( true );
if (!status) { status.perror("typedAttrKeyable.setKeyable"); return status;}
status = typedAttrKeyable.setDisconnectBehavior(MFnAttribute::kDelete);
if (!status) { status.perror("typedAttrKeyable.setDisconnectBehavior:cgeom"); return status;}
}
{
MFnCompoundAttribute compoundAttr;
geometrySurfaceConstraint::compoundTarget =
compoundAttr.create( "target", "tgt",&status );
if (!status) { status.perror("compoundAttr.create"); return status;}
status = compoundAttr.addChild( geometrySurfaceConstraint::targetGeometry );
if (!status) { status.perror("compoundAttr.addChild"); return status;}
status = compoundAttr.addChild( geometrySurfaceConstraint::targetWeight );
if (!status) { status.perror("compoundAttr.addChild"); return status;}
status = compoundAttr.setArray( true );
if (!status) { status.perror("compoundAttr.setArray"); return status;}
status = compoundAttr.setDisconnectBehavior(MFnAttribute::kDelete);
if (!status) { status.perror("typedAttrKeyable.setDisconnectBehavior:cgeom"); return status;}
}
status = addAttribute( geometrySurfaceConstraint::constraintParentInverseMatrix );
if (!status) { status.perror("addAttribute"); return status;}
status = addAttribute( geometrySurfaceConstraint::constraintGeometry );
if (!status) { status.perror("addAttribute"); return status;}
status = addAttribute( geometrySurfaceConstraint::compoundTarget );
if (!status) { status.perror("addAttribute"); return status;}
status = attributeAffects( compoundTarget, constraintGeometry );
if (!status) { status.perror("attributeAffects"); return status;}
status = attributeAffects( targetGeometry, constraintGeometry );
if (!status) { status.perror("attributeAffects"); return status;}
status = attributeAffects( targetWeight, constraintGeometry );
if (!status) { status.perror("attributeAffects"); return status;}
status = attributeAffects( constraintParentInverseMatrix, constraintGeometry );
if (!status) { status.perror("attributeAffects"); return status;}
return MS::kSuccess;
}
geometrySurfaceConstraintCommand::geometrySurfaceConstraintCommand() {}
geometrySurfaceConstraintCommand::~geometrySurfaceConstraintCommand() {}
void* geometrySurfaceConstraintCommand::creator()
{
return new geometrySurfaceConstraintCommand();
}
void geometrySurfaceConstraintCommand::createdConstraint(MPxConstraint *constraint)
{
if ( constraint )
{
geometrySurfaceConstraint *c = (geometrySurfaceConstraint*) constraint;
c->weightType = weightType;
}
else
{
MGlobal::displayError("Failed to get created constraint.");
}
}
MStatus geometrySurfaceConstraintCommand::parseArgs(const MArgList &argList)
{
MStatus ReturnStatus;
MArgDatabase argData(syntax(), argList, &ReturnStatus);
if ( ReturnStatus.error() )
return MS::kFailure;
ConstraintType typ;
if (argData.isFlagSet(kConstrainToLargestWeightFlag))
typ = geometrySurfaceConstraintCommand::kLargestWeight;
else if (argData.isFlagSet(kConstrainToSmallestWeightFlag))
typ = geometrySurfaceConstraintCommand::kSmallestWeight;
else
typ = geometrySurfaceConstraintCommand::kLargestWeight;
weightType = typ;
return MS::kUnknownParameter;
}
MStatus geometrySurfaceConstraintCommand::doIt(const MArgList &argList)
{
MStatus ReturnStatus;
if ( MS::kFailure == parseArgs(argList) )
return MS::kFailure;
return MS::kUnknownParameter;
}
MStatus geometrySurfaceConstraintCommand::connectTarget(void *opaqueTarget, int index)
{
MStatus status = connectTargetAttribute(
opaqueTarget, index, geometrySurfaceConstraint::targetGeometry );
if (!status) { status.perror("connectTargetGeometry"); return status;}
return MS::kSuccess;
}
MStatus geometrySurfaceConstraintCommand::connectObjectAndConstraint( MDGModifier& modifier )
{
MObject transform = transformObject();
if ( transform.isNull() )
{
MGlobal::displayError("Failed to get transformObject()");
return MS::kFailure;
}
MStatus status;
MFnTransform transformFn( transform );
MVector translate = transformFn.getTranslation(MSpace::kTransform,&status);
if (!status) { status.perror(" transformFn.getTranslation"); return status;}
MPlug translatePlug = transformFn.findPlug( "translate", &status );
if (!status) { status.perror(" transformFn.findPlug"); return status;}
if ( MPlug::kFreeToChange == translatePlug.isFreeToChange() )
{
MFnNumericData nd;
MObject translateData = nd.create( MFnNumericData::k3Double, &status );
status = nd.setData3Double( translate.x,translate.y,translate.z);
if (!status) { status.perror("nd.setData3Double"); return status;}
status = modifier.newPlugValue( translatePlug, translateData );
if (!status) { status.perror("modifier.newPlugValue"); return status;}
status = connectObjectAttribute(
MPxTransform::geometry,
geometrySurfaceConstraint::constraintGeometry, false );
if (!status) { status.perror("connectObjectAttribute"); return status;}
}
status = connectObjectAttribute(
MPxTransform::parentInverseMatrix,
geometrySurfaceConstraint::constraintParentInverseMatrix, true, true );
if (!status) { status.perror("connectObjectAttribute"); return status;}
return MS::kSuccess;
}
const MObject& geometrySurfaceConstraintCommand::constraintInstancedAttribute() const
{
return geometrySurfaceConstraint::constraintParentInverseMatrix;
}
const MObject& geometrySurfaceConstraintCommand::constraintOutputAttribute() const
{
return geometrySurfaceConstraint::constraintGeometry;
}
const MObject& geometrySurfaceConstraintCommand::constraintTargetInstancedAttribute() const
{
return geometrySurfaceConstraint::targetGeometry;
}
const MObject& geometrySurfaceConstraintCommand::constraintTargetAttribute() const
{
return geometrySurfaceConstraint::compoundTarget;
}
const MObject& geometrySurfaceConstraintCommand::constraintTargetWeightAttribute() const
{
return geometrySurfaceConstraint::targetWeight;
}
const MObject& geometrySurfaceConstraintCommand::objectAttribute() const
{
return MPxTransform::geometry;
}
MTypeId geometrySurfaceConstraintCommand::constraintTypeId() const
{
return geometrySurfaceConstraint::id;
}
MPxConstraintCommand::TargetType geometrySurfaceConstraintCommand::targetType() const
{
return MPxConstraintCommand::kGeometryShape;
}
MStatus geometrySurfaceConstraintCommand::appendSyntax()
{
MStatus ReturnStatus;
MSyntax theSyntax = syntax(&ReturnStatus);
if (MS::kSuccess != ReturnStatus) {
MGlobal::displayError("Could not get the parent's syntax");
return ReturnStatus;
}
theSyntax.addFlag( kConstrainToLargestWeightFlag, kConstrainToLargestWeightFlagLong );
theSyntax.addFlag( kConstrainToSmallestWeightFlag, kConstrainToSmallestWeightFlagLong );
return ReturnStatus;
}
MStatus initializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "9.0", "Any");
status = plugin.registerNode( "geometrySurfaceConstraint", geometrySurfaceConstraint::id, geometrySurfaceConstraint::creator,
geometrySurfaceConstraint::initialize, MPxNode::kConstraintNode );
if (!status) {
status.perror("registerNode");
return status;
}
status = plugin.registerConstraintCommand( "geometrySurfaceConstraint", geometrySurfaceConstraintCommand::creator );
if (!status) {
status.perror("registerConstraintCommand");
return status;
}
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
status = plugin.deregisterNode( geometrySurfaceConstraint::id );
if (!status) {
status.perror("deregisterNode");
return status;
}
status = plugin.deregisterConstraintCommand( "geometrySurfaceConstraint" );
if (!status) {
status.perror("deregisterNode");
return status;
}
return status;
}