MetadataSample/tweakMetadataNode.cpp
 
 
 
MetadataSample/tweakMetadataNode.cpp
#include <tweakMetadataNode.h>
#include <string.h>
#include <maya/MIOStream.h>
#include <math.h>

#include <maya/MPxNode.h>
#include <maya/MFnMesh.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MArrayDataHandle.h>
#include <maya/adskDataAssociations.h>
#include <maya/adskDataChannel.h>
#include <maya/adskDataStream.h>
#include <maya/adskDataHandle.h>
#include <maya/adskDataMember.h>

#define MCheckErr(stat,msg)             \
        if ( MS::kSuccess != stat ) {   \
                cerr << msg;            \
                return MS::kFailure;    \
        }

MTypeId tweakMetadataNode::id( 0x8104F );

// local attributes
//
MObject tweakMetadataNode::aInMesh;
MObject tweakMetadataNode::aOutMesh;
MObject tweakMetadataNode::aOperation;

tweakMetadataNode::tweakMetadataNode    () {}
tweakMetadataNode::~tweakMetadataNode   () {}

void* tweakMetadataNode::creator()
{
        return new tweakMetadataNode();
}

const char* tweakMetadataNode::nodeName()
{
        return "tweakMetadata";
}

MStatus tweakMetadataNode::initialize()
{
        MStatus status;

        //----------------------------------------
        MFnEnumAttribute eAttr;
        aOperation = eAttr.create( "operation", "op", kOpNone );
                eAttr.addField( "none",   kOpNone );
                eAttr.addField( "random", kOpRandomize );
                eAttr.addField( "fill",   kOpFill );
                eAttr.addField( "double", kOpDouble );
        MCheckErr( status, "failed to create operation attribute" );
        addAttribute( aOperation );

        //----------------------------------------
        MFnTypedAttribute tAttr;
        aInMesh = tAttr.create( "inMesh", "im", MFnData::kMesh, MObject::kNullObj, &status );
        MCheckErr( status, "failed to create inMesh attribute" );
        addAttribute( aInMesh );

        //----------------------------------------
        aOutMesh = tAttr.create( "outMesh", "om", MFnData::kMesh, MObject::kNullObj, &status );
        MCheckErr( status, "failed to create outMesh attribute" );
        tAttr.setWritable( false );
        tAttr.setStorable( false );
        addAttribute( aOutMesh );

        //----------------------------------------
        attributeAffects(aInMesh, aOutMesh);
        attributeAffects(aOperation, aOutMesh);

        return MStatus::kSuccess;
}

MStatus tweakMetadataNode::compute( const MPlug& plug, MDataBlock& block)
{
        MStatus status = MS::kSuccess;

        MObject thisNode = thisMObject();
        MPlug opPlug(thisNode, aOperation);

        short opType = block.inputValue( opPlug, & status ).asShort();
        if( status != MS::kSuccess )
        {
                return status;
        }

        MPlug inMeshPlug(thisNode, aInMesh);
        MDataHandle inMeshHandle = block.inputValue(inMeshPlug, &status);
        MCheckErr(status,"ERROR getting inMesh"); 

        MPlug outMeshPlug(thisNode, aOutMesh);
        MDataHandle outMeshHandle = block.outputValue(outMeshPlug, &status);
        MCheckErr(status,"ERROR getting outMesh"); 

        // Create a copy of the mesh object. Rely on the underlying geometry
        // object to minimize the amount of duplication that will happen.
        outMeshHandle.set( inMeshHandle.asMesh() );
        MObject outMeshObj = outMeshHandle.asMesh();
        MFnMesh outputMesh( outMeshObj );

        const adsk::Data::Associations* oldAssociations = outputMesh.metadata();
        //associations.makeUnique();    // Create a copy for modification

        // Search through all streams in all channels for matching data types.
        if( oldAssociations )
        {
                adsk::Data::Associations associations( *oldAssociations );
                for( unsigned int c=0; c<associations.channelCount(); ++c )
                {
                        adsk::Data::Channel channel = associations.channelAt( c );
                        //channel.makeUnique(); // Create a copy for modification
                        for( unsigned int s=0; s<channel.dataStreamCount(); ++s )
                        {
                                adsk::Data::Stream* chStream = channel.dataStream( s );
                                if( ! chStream ) continue;
                                //chStream->makeUnique();       // Create a copy for modification
                                for( unsigned int el=0; el<chStream->elementCount(); ++el )
                                {
                                        adsk::Data::Handle sHandle = chStream->element( el );
                                        if( ! sHandle.hasData() ) continue;
                                        if( sHandle.dataType() != adsk::Data::Member::kInt32 ) continue;
        
                                        int* hValue = sHandle.asInt32();
                                        if( ! hValue ) continue;
        
                                        for( unsigned int l=0; l<sHandle.dataLength(); ++l )
                                        {
                                                switch( opType )
                                                {
                                                        case kOpRandomize:
                                                                // Fill all of the int32 metadata types with a random number
                                                                // between -1000 and +1000
                                                                hValue[l] = int(rand() % 2001) - 1000;
                                                                break;
        
                                                        //----------------------------------------
                                                        case kOpFill:
                                                                // Fill all of the int32 metadata types with a constant
                                                                // Since it doesn't really matter what the constant is pick the
                                                                // last eight bits of the pointer to the stream so that each
                                                                // stream will potentially get a different value.
                                                                hValue[l] = (size_t)(chStream) % 0xff;
                                                                break;
        
                                                        //----------------------------------------
                                                        case kOpDouble:
                                                                // Find all int32 metadata types and double their values
                                                                hValue[l] *= 2;
                                                                break;
        
                                                        //----------------------------------------
                                                        case kOpNone:
                                                        default:
                                                                // No-op moves the mesh through unchanged
                                                                break;
                                                }
                                        }
                                }
                        }
                        associations.setChannel( channel );
                }
                outMeshHandle.setClean();
        }

        return status;
}

//-
// ==================================================================
// Copyright 2012 Autodesk, Inc.  All rights reserved.
//
// This computer source code  and related  instructions and comments are
// the unpublished confidential and proprietary information of Autodesk,
// Inc. and are  protected  under applicable  copyright and trade secret
// law. They may not  be disclosed to, copied or used by any third party
// without the prior written consent of Autodesk, Inc.
// ==================================================================
//+