meshOpCmd/meshOpNode.cpp

meshOpCmd/meshOpNode.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.
// ==========================================================================
//+
#include "meshOpNode.h"
// Function Sets
//
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnMeshData.h>
#include <maya/MFnComponentListData.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MFnEnumAttribute.h>
// General Includes
//
#include <maya/MGlobal.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MIOStream.h>
// Macros
//
#define MCheckStatus(status,message) \
if( MStatus::kSuccess != status ) { \
cerr << message << "\n"; \
return status; \
}
// Unique Node TypeId
MTypeId meshOpNode::id( 0x00085000 );
// Node attributes
// (in addition to inMesh and outMesh defined by polyModifierNode)
//
MObject meshOpNode::cpList;
MObject meshOpNode::opType;
meshOpNode::meshOpNode()
{}
meshOpNode::~meshOpNode()
{}
MStatus meshOpNode::compute( const MPlug& plug, MDataBlock& data )
//
// Description:
// This method computes the value of the given output plug based
// on the values of the input attributes.
//
// Arguments:
// plug - the plug to compute
// data - object that provides access to the attributes for this node
//
{
MStatus status = MS::kSuccess;
MDataHandle stateData = data.outputValue( state, &status );
MCheckStatus( status, "ERROR getting state" );
// Check for the HasNoEffect/PassThrough flag on the node.
//
// (stateData is an enumeration standard in all depend nodes)
//
// (0 = Normal)
// (1 = HasNoEffect/PassThrough)
// (2 = Blocking)
// ...
//
if( stateData.asShort() == 1 )
{
MDataHandle inputData = data.inputValue( inMesh, &status );
MCheckStatus(status,"ERROR getting inMesh");
MDataHandle outputData = data.outputValue( outMesh, &status );
MCheckStatus(status,"ERROR getting outMesh");
// Simply redirect the inMesh to the outMesh for the PassThrough effect
//
outputData.set(inputData.asMesh());
}
else
{
// Check which output attribute we have been asked to
// compute. If this node doesn't know how to compute it,
// we must return MS::kUnknownParameter
//
if (plug == outMesh)
{
MDataHandle inputData = data.inputValue( inMesh, &status );
MCheckStatus(status,"ERROR getting inMesh");
MDataHandle outputData = data.outputValue( outMesh, &status );
MCheckStatus(status,"ERROR getting outMesh");
// Now, we get the value of the component list and the operation
// type and use it to perform the mesh operation on this mesh
//
MDataHandle inputIDs = data.inputValue( cpList, &status);
MCheckStatus(status,"ERROR getting componentList");
MDataHandle opTypeData = data.inputValue( opType, &status);
MCheckStatus(status,"ERROR getting opType");
// Copy the inMesh to the outMesh, so you can
// perform operations directly on outMesh
//
outputData.set(inputData.asMesh());
MObject mesh = outputData.asMesh();
// Retrieve the ID list from the component list.
//
// Note, we use a component list to store the components
// because it is more compact memory wise. (ie. comp[81:85]
// is smaller than comp[81], comp[82],...,comp[85])
//
MObject compList = inputIDs.data();
MFnComponentListData compListFn( compList );
// Get what operation is requested and
// what type of component is expected for this operation.
MeshOperation operationType = (MeshOperation) opTypeData.asShort();
MFn::Type componentType =
meshOpFty::getExpectedComponentType(operationType);
unsigned i;
int j;
MIntArray cpIds;
for( i = 0; i < compListFn.length(); i++ )
{
MObject comp = compListFn[i];
if( comp.apiType() == componentType )
{
MFnSingleIndexedComponent siComp( comp );
for( j = 0; j < siComp.elementCount(); j++ )
cpIds.append( siComp.element(j) );
}
}
// Set the mesh object and component List on the factory
//
fmeshOpFactory.setMesh( mesh );
fmeshOpFactory.setComponentList( compList );
fmeshOpFactory.setComponentIDs( cpIds );
fmeshOpFactory.setMeshOperation( operationType );
// Now, perform the meshOp
//
status = fmeshOpFactory.doIt();
// Mark the output mesh as clean
//
outputData.setClean();
}
else
{
status = MS::kUnknownParameter;
}
}
return status;
}
void* meshOpNode::creator()
//
// Description:
// this method exists to give Maya a way to create new objects
// of this type.
//
// Return Value:
// a new object of this type
//
{
return new meshOpNode();
}
MStatus meshOpNode::initialize()
//
// Description:
// This method is called to create and initialize all of the attributes
// and attribute dependencies for this node type. This is only called
// once when the node type is registered with Maya.
//
// Return Values:
// MS::kSuccess
// MS::kFailure
//
{
MStatus status;
cpList = attrFn.create("inputComponents", "ics",
attrFn.setStorable(true); // To be stored during file-save
opType = enumFn.create("operationType", "oprt", 0, &status);
enumFn.addField("subd_edges", 0);
enumFn.addField("subd_faces", 1);
enumFn.setHidden(false);
enumFn.setKeyable(true);
enumFn.setStorable(true); // To be stored during file-save
inMesh = attrFn.create("inMesh", "im", MFnMeshData::kMesh);
attrFn.setStorable(true); // To be stored during file-save
// Attribute is read-only because it is an output attribute
//
outMesh = attrFn.create("outMesh", "om", MFnMeshData::kMesh);
attrFn.setStorable(false);
attrFn.setWritable(false);
// Add the attributes we have created to the node
//
status = addAttribute( cpList );
if (!status)
{
status.perror("addAttribute");
return status;
}
status = addAttribute( opType );
if (!status)
{
status.perror("addAttribute");
return status;
}
status = addAttribute( inMesh );
if (!status)
{
status.perror("addAttribute");
return status;
}
status = addAttribute( outMesh);
if (!status)
{
status.perror("addAttribute");
return status;
}
// Set up a dependency between the input and the output. This will cause
// the output to be marked dirty when the input changes. The output will
// then be recomputed the next time the value of the output is requested.
//
status = attributeAffects( inMesh, outMesh );
if (!status)
{
status.perror("attributeAffects");
return status;
}
status = attributeAffects( cpList, outMesh );
if (!status)
{
status.perror("attributeAffects");
return status;
}
status = attributeAffects( opType, outMesh );
if (!status)
{
status.perror("attributeAffects");
return status;
}
return MS::kSuccess;
}