- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Examples

# genericAttributeNode.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 <string.h>
    #include <maya/MIOStream.h>
    #include <math.h>

    #include <maya/MPxNode.h>

    #include <maya/MFnNumericAttribute.h>
    #include <maya/MFnGenericAttribute.h>
    #include <maya/MFnPlugin.h>

    #include <maya/MTypeId.h>
    #include <maya/MPlug.h>
    #include <maya/MDataBlock.h>
    #include <maya/MDataHandle.h>
    #include <maya/MGlobal.h>

    //
    // Node definition
    //
    class genericAttributeNode : public MPxNode
    {
    public:
                            genericAttributeNode();
        virtual             ~genericAttributeNode();

        virtual MStatus     compute( const MPlug& plug, MDataBlock& data );

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

        static MStatus  addComplexFloatGenericAttribute( MObject& attrObject, const char *longName, const char *shortName );

    public:
        // Numeric attribute
        static MObject      gInputInt;
        // Generic attribute that can be a float, 2float, 3float
        static MObject      gOutputFloat_2Float_3Float;
        // Type id
        static  MTypeId     id;
    };

    // Static initialization
    MTypeId genericAttributeNode::id( 0x81031 );
    MObject genericAttributeNode::gInputInt;
    MObject genericAttributeNode::gOutputFloat_2Float_3Float;

    // No-op constructor and destructor
    genericAttributeNode::genericAttributeNode() {}
    genericAttributeNode::~genericAttributeNode() {}

    //
    // Compute that will update the generic attribute
    // when requested.
    //
    MStatus genericAttributeNode::compute( const MPlug& plug, MDataBlock& data )
    {
        MStatus returnStatus;

        if ( plug == gOutputFloat_2Float_3Float )
        {
            // attribute affecting generic attribute case.  Based on the
            // input attribute, we modify the output generic attribute
            MDataHandle inputDataInt = data.inputValue( gInputInt );
            int inputInt = inputDataInt.asInt();

            // Get the output handle
            MDataHandle outputData = data.outputValue( plug );
            bool isGenericNumeric = false;
            bool isGenericNull = false;

            // Is the output handle generic data
            if ( outputData.isGeneric( isGenericNumeric, isGenericNull ) )
            {
                // Based on the inputHandle, update the generic
                // output handle
                if ( inputInt == 1 )
                    outputData.setGenericBool( false, true );
                else if ( inputInt == 2 )
                    outputData.setGenericBool( true, true );
                else if ( inputInt == 3 )
                    outputData.setGenericChar( 127, true );
                else if ( inputInt == 4 )
                    outputData.setGenericDouble( 3.145, true );
                else if ( inputInt == 5 )
                    outputData.setGenericFloat( (float)9.98, true );
                else if ( inputInt == 6 )
                    outputData.setGenericShort( 3245, true );
                else if ( inputInt == 7 )
                    outputData.setGenericInt( 32768, true );
                else if ( inputInt == 8 )
                {
                    MFnNumericData numericData;
                    MObject obj = numericData.create( MFnNumericData::k2Float, &returnStatus );
                    CHECK_MSTATUS( returnStatus );

                    returnStatus = numericData.setData( (float)1.5, (float)6.7 );
                    CHECK_MSTATUS( returnStatus );

                    outputData.set( obj );
                }
                else if ( inputInt == 9 )
                {
                    MFnNumericData numericData;
                    MObject obj = numericData.create( MFnNumericData::k3Float, &returnStatus );
                    CHECK_MSTATUS( returnStatus );

                    returnStatus = numericData.setData( (float)2.5, (float)8.7, (float)2.3345 );
                    CHECK_MSTATUS( returnStatus );

                    outputData.set( obj );
                }
                else if ( inputInt == 10 )
                {
                    outputData.setGenericInt( 909, true );
                }

                // Mark the data clean
                outputData.setClean();
                data.setClean( gOutputFloat_2Float_3Float );
            }
        }
        else
        {
            return MS::kUnknownParameter;
        }

        return MS::kSuccess;
    }

    // Creator
    void* genericAttributeNode::creator()
    {
        return new genericAttributeNode();
    }

    // Adds a generic attribute that accepts a float, float2, float3
    MStatus genericAttributeNode::addComplexFloatGenericAttribute(
        MObject& attrObject,
        const char *longName, const char *shortName )
    {
        // Create the generic attribute and set the 3 accepts types
        MFnGenericAttribute gAttr;
        attrObject = gAttr.create( longName, shortName );
        MStatus status = gAttr.addAccept(MFnNumericData::kFloat);
        CHECK_MSTATUS( status );

        status = gAttr.addAccept(MFnNumericData::k2Float);
        CHECK_MSTATUS( status );

        status = gAttr.addAccept(MFnNumericData::k3Float);
        CHECK_MSTATUS( status );

        gAttr.setWritable(false);
        gAttr.setStorable( false );

        // Add the attribute to the node
        status = addAttribute( attrObject );
        CHECK_MSTATUS( status );

        return MS::kSuccess;
    }

    // Create and add attributes
    MStatus genericAttributeNode::initialize()
    {
        MFnNumericAttribute nAttr;
        MStatus status;

        // single float attribute affecting a generic attribute
        gInputInt = nAttr.create( "gInputInt", "gii",
                       MFnNumericData::kInt, 0, &status );
        nAttr.setStorable(true);
        nAttr.setKeyable(true);
        CHECK_MSTATUS( status );

        status = addAttribute( gInputInt );
        CHECK_MSTATUS( status );

        if ( !addComplexFloatGenericAttribute( gOutputFloat_2Float_3Float,
                         "gOutputFloat_2Float_3Float", "gof2f3f" ) )
            return MS::kFailure;

        status = attributeAffects( gInputInt, gOutputFloat_2Float_3Float );
        CHECK_MSTATUS( status );

        return MS::kSuccess;
    }

    MStatus initializePlugin( MObject obj )
    {
        MStatus   status;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "7.0", "Any");

        status = plugin.registerNode( "genericAttributeNode",
                                        genericAttributeNode::id, genericAttributeNode::creator,
                                        genericAttributeNode::initialize );
        if (!status) {
            status.perror("registerNode");
            return status;
        }

        return status;
    }

    MStatus uninitializePlugin( MObject obj)
    {
        MStatus   status;
        MFnPlugin plugin( obj );

        status = plugin.deregisterNode( genericAttributeNode::id );
        if (!status) {
            status.perror("deregisterNode");
            return status;
        }

        return status;
    }