weightListNode/weightListNode.cpp
 
 
 
weightListNode/weightListNode.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.
// ==========================================================================
//+
//


//
//  File: weightListNode.cpp
//
//  Description:
//              Example implementation of a node which read and write a 
//              multi of multi of float attibute in the compute() method. The
//              definition of this multi of multi of float attibute is 
//              the same as the weightList attribute for deformer. 
//        
//              To test the node, use the following MEL commands
/*
                                loadPlugin weightListNode;
                                createNode weightList;
                                setAttr weightList1.bias 1;
                                getAttr -type weightList1.weightsList;
*/

#include <string.h>
#include <maya/MIOStream.h>
#include <math.h>

#include <maya/MPxNode.h> 
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFnPlugin.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>

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

class weightList : public MPxNode
{
public:
                                weightList();
        virtual                 ~weightList();

        static  void*           creator();
        static  MStatus         initialize();

        // deformation function
        //
        virtual MStatus         compute( const MPlug&, MDataBlock&);

public:
        // local node attributes

        static  MObject         aWeightsList;
        static  MObject         aWeights;
        static  MObject         aBias;
        static  MTypeId         id;

private:
};

MTypeId weightList::id( 0x81035 );

// local attributes
//
MObject weightList::aWeightsList;
MObject weightList::aWeights;
MObject weightList::aBias;

weightList::weightList() {}
weightList::~weightList() {}

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

MStatus weightList::initialize()
{
        MStatus status;
        MFnNumericAttribute numAtt; 

        aBias = numAtt.create( "bias", "b", MFnNumericData::kFloat);
        addAttribute(aBias);

        aWeights = numAtt.create("weights", "w", MFnNumericData::kFloat, -1000.0, &status); 
        numAtt.setKeyable(true); 
        numAtt.setArray(true); 
        numAtt.setReadable(true); 
        numAtt.setUsesArrayDataBuilder(true); 
        // setIndexMatters() will only affect array attributes with setReadable set to false, 
        // i.e. destination attributes. We have set the default value to an unlikely value 
        // to guarantee an entry is created regardless of its value. 
        // numAtt.setIndexMatters(true);
        addAttribute(aWeights); 
        
        MFnCompoundAttribute cmpAttr; 
        aWeightsList = cmpAttr.create("weightsList", "wl", &status); 
        cmpAttr.setArray(true); 
        cmpAttr.addChild(aWeights); 
        cmpAttr.setReadable(true); 
        cmpAttr.setUsesArrayDataBuilder(true); 
        // cmpAttr.setIndexMatters(true);
        addAttribute(aWeightsList); 

        attributeAffects(aBias, aWeightsList);
        
        return MStatus::kSuccess;
}

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

        unsigned i, j;
        MObject thisNode = thisMObject();
        MPlug wPlug(thisNode, aWeights); 

        // Write into aWeightList
        for( i = 0; i < 3; i++) {
            status = wPlug.selectAncestorLogicalIndex( i, aWeightsList );
            MDataHandle wHandle = wPlug.constructHandle(block);
            MArrayDataHandle arrayHandle(wHandle, &status);
            McheckErr(status, "arrayHandle construction failed\n");
            MArrayDataBuilder arrayBuilder = arrayHandle.builder(&status);
            McheckErr(status, "arrayBuilder accessing/construction failed\n");
            for( j = 0; j < i+2; j++) {
                MDataHandle handle = arrayBuilder.addElement(j,&status);
                McheckErr(status, "addElement to arrayBuilder failed\n");
                float val = 1.0f*(i+j); 
                handle.set(val);
            }
            status = arrayHandle.set(arrayBuilder);
            McheckErr(status, "set arrayBuilder failed\n");
            wPlug.setValue(wHandle);
            wPlug.destructHandle(wHandle);
        }

        // Read from aWeightList and print out result
        MArrayDataHandle arrayHandle = block.inputArrayValue(aWeightsList, &status);
        McheckErr(status, "arrayHandle construction for aWeightsList failed\n");
        unsigned count = arrayHandle.elementCount();
        for( i = 0; i < count; i++) {
            arrayHandle.jumpToElement(i);
            MDataHandle eHandle = arrayHandle.inputValue(&status).child(aWeights);
            McheckErr(status, "handle evaluation failed\n");
            MArrayDataHandle eArrayHandle(eHandle, &status);
            McheckErr(status, "arrayHandle construction for aWeights failed\n");
            unsigned eCount = eArrayHandle.elementCount();
            for( j = 0; j < eCount; j++) {
                eArrayHandle.jumpToElement(j);
                float weight = eArrayHandle.inputValue(&status).asFloat();
                McheckErr(status, "weight evaluation error\n");
                fprintf(stderr, "weightList[%u][%u] = %g\n",i,j,weight);
            }
        }

        // Read from aWeightList and print out result using the more
        // efficient jumpToArrayElement() call
        arrayHandle = block.inputArrayValue(aWeightsList, &status);
        McheckErr(status, "arrayHandle construction for aWeightsList failed\n");
        count = arrayHandle.elementCount();
        for( i = 0; i < count; i++) {
            arrayHandle.jumpToArrayElement(i);
            MDataHandle eHandle = arrayHandle.inputValue(&status).child(aWeights);
            McheckErr(status, "handle evaluation failed\n");
            MArrayDataHandle eArrayHandle(eHandle, &status);
            McheckErr(status, "arrayHandle construction for aWeights failed\n");
            unsigned eCount = eArrayHandle.elementCount();
            for( j = 0; j < eCount; j++) {
                eArrayHandle.jumpToArrayElement(j);
                float weight = eArrayHandle.inputValue(&status).asFloat();
                McheckErr(status, "weight evaluation error\n");
                fprintf(stderr, "weightList[%d][%d] = %g\n",i,j,weight);
            }
        }

        return status;
}

// standard initialization procedures
//

MStatus initializePlugin( MObject obj )
{
        MStatus result;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");
        result = plugin.registerNode( "weightList", 
                                      weightList::id, 
                                      weightList::creator, 
                                      weightList::initialize);

        return result;
}

MStatus uninitializePlugin( MObject obj)
{
        MStatus result;
        MFnPlugin plugin( obj );
        result = plugin.deregisterNode( weightList::id );
        return result;
}