// A large portion of this file has been pretty much directly copied
// from the lambertShader.cpp file included as an example plug-in with
// the Maya 6.5 devkit
//

#include "SingleScatterShader.h"

#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFloatVector.h>
#include <maya/MDagPath.h>
#include <maya/MGlobal.h>
#include <maya/MIOStream.h>
#include <maya/MPxNode.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MArrayDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnLightDataAttribute.h>
#include <maya/MMatrix.h>
#include <maya/MItDag.h>
#include <maya/MFnPointLight.h>
#include <maya/MFnMatrixData.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MColor.h>
#include <maya/MFloatMatrix.H>


#include <math.h>

#define E 2.718281828459f
#define PI 3.1415926535898f

// You MUST change this to a unique value!!!  The id is a 32bit value used
// to identify this type of node in the binary file format.  
//
MTypeId SingleScatterShader::id( 0x00002 );

TableReader SingleScatterShader::G0;
TableReader SingleScatterShader::G20;

MObject  SingleScatterShader::aMatrixEyeToWorld;
MObject  SingleScatterShader::aPointW;
MObject  SingleScatterShader::aPointC;
MObject  SingleScatterShader::aScatteringCoef;
MObject  SingleScatterShader::aShiny;

MObject  SingleScatterShader::aDiffuseReflectivity;

MObject  SingleScatterShader::aInTransparency;
MObject  SingleScatterShader::aInTransR;
MObject  SingleScatterShader::aInTransG;
MObject  SingleScatterShader::aInTransB;

MObject  SingleScatterShader::aColor;
MObject  SingleScatterShader::aColorR;
MObject  SingleScatterShader::aColorG;
MObject  SingleScatterShader::aColorB;

MObject  SingleScatterShader::aSpecularColor;
MObject  SingleScatterShader::aSpecularColorR;
MObject  SingleScatterShader::aSpecularColorG;
MObject  SingleScatterShader::aSpecularColorB;

MObject  SingleScatterShader::aIncandescence;
MObject  SingleScatterShader::aIncandescenceR;
MObject  SingleScatterShader::aIncandescenceG;
MObject  SingleScatterShader::aIncandescenceB;

MObject  SingleScatterShader::aOutColor;
MObject  SingleScatterShader::aOutColorR;
MObject  SingleScatterShader::aOutColorG;
MObject  SingleScatterShader::aOutColorB;

MObject  SingleScatterShader::aOutTransparency;
MObject  SingleScatterShader::aOutTransR;
MObject  SingleScatterShader::aOutTransG;
MObject  SingleScatterShader::aOutTransB;

MObject  SingleScatterShader::aNormalCamera;
MObject  SingleScatterShader::aNormalCameraX;
MObject  SingleScatterShader::aNormalCameraY;
MObject  SingleScatterShader::aNormalCameraZ;

SingleScatterShader::SingleScatterShader() { }
SingleScatterShader::~SingleScatterShader() { }

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


MStatus SingleScatterShader::initialize()
{
	MFnNumericAttribute nAttr; 
	MFnLightDataAttribute lAttr;
	MFnMatrixAttribute mAttr;

	MStatus status;
	
	// Input Attributes
	//
	aPointW = nAttr.createPoint("pointWorld", "pw" );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setStorable(false) );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setHidden(true) );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setReadable(true) );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setWritable(true) );

	aPointC = nAttr.createPoint("pointCamera", "pc" );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setStorable(false) );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setHidden(true) );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setReadable(true) );
    CHECK_MSTATUS_AND_RETURN_IT( nAttr.setWritable(true) );


	aMatrixEyeToWorld = mAttr.create( "matrixEyeToWorld", "mew",
									  MFnMatrixAttribute::kFloat, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setStorable(false) );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setHidden(true) );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setReadable(true) );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setWritable(true) );	

	aScatteringCoef = nAttr.create( "ScatteringCoef", "scac",
									MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );	
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setConnectable( true ) );
	CHECK_MSTATUS( nAttr.setWritable( true ) );
	CHECK_MSTATUS( nAttr.setReadable( false ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );

	aShiny = nAttr.create( "Shiny", "shin",
						   MFnNumericData::kBoolean, 0, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setStorable(true) );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setHidden(false) );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setReadable(true) );
    CHECK_MSTATUS_AND_RETURN_IT( mAttr.setWritable(true) );	


	aDiffuseReflectivity = nAttr.create( "diffuseReflectivity", "drfl",
										 MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.8f ) );
	
	aColorR = nAttr.create( "colorR", "cr",MFnNumericData::kFloat, 0,
							&status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.5f ) );
	
	aColorG = nAttr.create( "colorG", "cg", MFnNumericData::kFloat, 0,
							&status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.5f ) );

	aColorB = nAttr.create( "colorB", "cb",MFnNumericData::kFloat, 0,
							&status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.5f ) );
	
	aColor = nAttr.create( "color", "c", aColorR, aColorG, aColorB,
						   &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.5f, 0.5f, 0.5f ) );
	CHECK_MSTATUS( nAttr.setUsedAsColor( true ) );

	aSpecularColorR = nAttr.create( "specularColorR", "spcr", MFnNumericData::kFloat, 0,
									&status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );
	
	aSpecularColorG = nAttr.create( "specularColorG", "spcg", MFnNumericData::kFloat, 0,
									&status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );

	aSpecularColorB = nAttr.create( "specularColorB", "spcb", MFnNumericData::kFloat, 0,
									&status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );
	
	aSpecularColor = nAttr.create( "specularColor", "spc", aSpecularColorR,
								   aSpecularColorG, aSpecularColorB,
								   &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f, 1.0f, 1.0f ) );
	CHECK_MSTATUS( nAttr.setUsedAsColor( true ) );

	aIncandescenceR = nAttr.create( "incandescenceR", "ir",
									MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.0f ) );

	aIncandescenceG = nAttr.create( "incandescenceG", "ig",
									MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.0f ) );

	aIncandescenceB = nAttr.create( "incandescenceB", "ib",
									MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status);
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.0f ) );

	aIncandescence = nAttr.create( "incandescence", "ic", aIncandescenceR,
								   aIncandescenceG, aIncandescenceB, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.0f, 0.0f, 0.0f ) );
	CHECK_MSTATUS( nAttr.setUsedAsColor( true ) );

	aInTransR = nAttr.create( "transparencyR", "itr",
							  MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );

	aInTransG = nAttr.create( "transparencyG", "itg",
							  MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );

	aInTransB = nAttr.create( "transparencyB", "itb",
							  MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status);
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );

	aInTransparency = nAttr.create( "transparency", "it", aInTransR,
									aInTransG, aInTransB, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setKeyable( true ) );
	CHECK_MSTATUS( nAttr.setStorable( true ) );
	CHECK_MSTATUS( nAttr.setDefault( 0.0f, 0.0f, 0.0f ) );
	CHECK_MSTATUS( nAttr.setUsedAsColor( true ) );

	
	// Output Attributes
	//

	// Color Output
	//
	aOutColorR = nAttr.create( "outColorR", "ocr", MFnNumericData::kFloat,
							   0, &status );
	CHECK_MSTATUS( status );
	
	aOutColorG = nAttr.create( "outColorG", "ocg", MFnNumericData::kFloat,
							   0, &status );
	CHECK_MSTATUS( status );
	
	aOutColorB = nAttr.create( "outColorB", "ocb", MFnNumericData::kFloat,
							   0, &status );
	CHECK_MSTATUS( status );
	
	aOutColor = nAttr.create( "outColor", "oc", aOutColorR, aOutColorG,
							  aOutColorB, &status );
	CHECK_MSTATUS( status );
	
	CHECK_MSTATUS( nAttr.setHidden( false ) );
	CHECK_MSTATUS( nAttr.setReadable( true ) );
	CHECK_MSTATUS( nAttr.setWritable( false ) );

	
	// Transparency Output
	//
	aOutTransR = nAttr.create( "outTransparencyR", "otr",
							   MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );

	aOutTransG = nAttr.create( "outTransparencyG", "otg",
							   MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );

	aOutTransB = nAttr.create( "outTransparencyB", "otb",
							   MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );

	aOutTransparency = nAttr.create( "outTransparency", "ot",
									 aOutTransR,aOutTransG,aOutTransB, &status );
	CHECK_MSTATUS( status );

	CHECK_MSTATUS( nAttr.setHidden( false ) );
	CHECK_MSTATUS( nAttr.setReadable( true ) );
	CHECK_MSTATUS( nAttr.setWritable( false ) );


	// Camera Normals
	//
	aNormalCameraX = nAttr.create( "normalCameraX", "nx",
								   MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setStorable( false ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );

	aNormalCameraY = nAttr.create( "normalCameraY", "ny",
								   MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setStorable( false ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );

	aNormalCameraZ = nAttr.create( "normalCameraZ", "nz",
								   MFnNumericData::kFloat, 0, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setStorable( false ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f ) );

	aNormalCamera = nAttr.create( "normalCamera","n", aNormalCameraX,
								  aNormalCameraY, aNormalCameraZ, &status );
	CHECK_MSTATUS( status );
	CHECK_MSTATUS( nAttr.setStorable( false ) );
	CHECK_MSTATUS( nAttr.setDefault( 1.0f, 1.0f, 1.0f ) );
	CHECK_MSTATUS( nAttr.setHidden( true ) );



	// Next we will add the attributes we have defined to the node
	//
	CHECK_MSTATUS( addAttribute( aMatrixEyeToWorld ) );
	CHECK_MSTATUS( addAttribute( aPointW ) );
	CHECK_MSTATUS( addAttribute( aPointC ) );
	CHECK_MSTATUS( addAttribute( aScatteringCoef ) );
	CHECK_MSTATUS( addAttribute( aShiny ) );
	CHECK_MSTATUS( addAttribute( aDiffuseReflectivity ) );
	CHECK_MSTATUS( addAttribute( aColor ) );
	CHECK_MSTATUS( addAttribute( aSpecularColor ) );
	CHECK_MSTATUS( addAttribute( aIncandescence ) );
	CHECK_MSTATUS( addAttribute( aInTransparency ) );
	CHECK_MSTATUS( addAttribute( aOutColor ) );
	CHECK_MSTATUS( addAttribute( aOutTransparency ) );
	CHECK_MSTATUS( addAttribute( aNormalCamera ) );

	// Setup dependencies
	//
	CHECK_MSTATUS( attributeAffects( aPointW, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aPointC, aOutColor ) );
//	CHECK_MSTATUS( attributeAffects( aMatrixEyeToWorld, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aScatteringCoef, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aShiny, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aDiffuseReflectivity, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aColorR, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aColorG, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aColorB, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aColor, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aSpecularColorR, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aSpecularColorG, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aSpecularColorB, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aSpecularColor, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aInTransR, aOutTransparency ) );
	CHECK_MSTATUS( attributeAffects( aInTransG, aOutTransparency ) );
	CHECK_MSTATUS( attributeAffects( aInTransB, aOutTransparency ) );
	CHECK_MSTATUS( attributeAffects( aInTransparency, aOutTransparency ) );
	CHECK_MSTATUS( attributeAffects( aInTransparency, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aIncandescenceR, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aIncandescenceG, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aIncandescenceB, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aIncandescence, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aNormalCameraX, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aNormalCameraY, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aNormalCameraZ, aOutColor ) );
	CHECK_MSTATUS( attributeAffects( aNormalCamera, aOutColor ) );
	
	CHECK_MSTATUS_AND_RETURN_IT( G0.Load( "G0.csv" ) );
	CHECK_MSTATUS_AND_RETURN_IT( G20.Load( "G20.csv" ) );

	return( MS::kSuccess );
}


MStatus SingleScatterShader::compute( const MPlug& plug, MDataBlock& block ) 
{ 
	if( plug == aOutColor
		|| plug == aOutColorR
		|| plug == aOutColorG
		|| plug == aOutColorB
		|| plug == aOutTransparency
		|| plug == aOutTransR
		|| plug == aOutTransG
		|| plug == aOutTransB )
	{
		MStatus status;
		MFloatVector resultColor( 0.0, 0.0, 0.0 );

	
		// Get surface shading parameters from input block
		//
		MFloatVector& surfaceNormal = block.inputValue( aNormalCamera, &status ).asFloatVector();
		CHECK_MSTATUS( status );

		MFloatVector& surfaceColor = block.inputValue( aColor, &status ).asFloatVector();
		CHECK_MSTATUS( status );

		MFloatVector& specularColor = block.inputValue( aSpecularColor, &status ).asFloatVector();
		CHECK_MSTATUS( status );

		MFloatVector& incandescence = block.inputValue( aIncandescence, &status ).asFloatVector();
		CHECK_MSTATUS( status );

		float diffuseReflectivity = block.inputValue( aDiffuseReflectivity, &status ).asFloat();
		CHECK_MSTATUS( status );

		float& scatteringCoef = block.inputValue( aScatteringCoef, &status ).asFloat();
		CHECK_MSTATUS( status );

		bool& shiny = block.inputValue( aShiny, &status ).asBool();
		CHECK_MSTATUS( status );



		MFloatVector &pointWorld = block.inputValue( aPointW ).asFloatVector();
		MFloatVector &pointCamera = block.inputValue( aPointC ).asFloatVector();
		MFloatMatrix &matrixEyeToWorld = block.inputValue( aMatrixEyeToWorld ).asFloatMatrix();  

		MItDag dagNodes( MItDag::kBreadthFirst, MFn::kPointLight, &status );

		if(!status)
		{
			cerr << "dagNodes error\n";
			return status;
		}

		for(;!dagNodes.isDone();dagNodes.next())
		{
			MObject lightNode = dagNodes.item();
			MFnPointLight pointLight( lightNode, &status );

			if( !status )
			{
				cerr << "error getting point light\n";
				return status;
			}

			MDagPath lightPath;
			CHECK_MSTATUS_AND_RETURN_IT( pointLight.getPath( lightPath ) );

			MMatrix lightTransform = lightPath.inclusiveMatrix( &status );

			if( !status )
			{
				cerr << "error getting inclusive matrix\n";
				return status;
			}

			MFloatVector lightPos( (float)lightTransform( 3, 0 ),
								   (float)lightTransform( 3, 1 ),
								   (float)lightTransform( 3, 2 ) );

			MFloatVector normalWorld = surfaceNormal * matrixEyeToWorld;

			if( !status )
			{
				cerr << "error getting light direction\n";
				return status;
			}

			MFloatVector vecSP = lightPos - pointWorld;
			
			float Dsp = vecSP.length(),
				Tsp = scatteringCoef * Dsp;

			float theta = normalWorld.angle( vecSP );

//			cerr << theta << " " << pointWorld << endl;
			
			MColor lightColor = pointLight.color();
			MFloatVector lightColorVector( lightColor.r, lightColor.g, lightColor.b );
			
			if( theta > 0.0f )
			{
				float d1 = pow( E, -Tsp ) * cos(theta) * pointLight.intensity() / (Dsp * Dsp),
					d2 = ((pointLight.intensity() * scatteringCoef) / (2.0f*PI * Dsp)
						  * G0.LookUp( Tsp, theta ));

//				cerr << theta << " " << Tsp << " " << d1 << " " << d2 << " " << pointLight.color() << endl;
				
				// Put it all together
				//				
				resultColor += lightColorVector * diffuseReflectivity * (d1 + d2);
			}

			if( shiny )
			{
				MFloatVector cameraWorld( (float)matrixEyeToWorld( 3, 0 ),
										  (float)matrixEyeToWorld( 3, 1 ),
										  (float)matrixEyeToWorld( 3, 2 ) );

				MFloatVector V = pointWorld - cameraWorld;

				// Reflect the viewing vector over the surface normal
				//
				MFloatVector VRN = 2 * normalWorld * (V * normalWorld) - V;

				float theta_ = VRN.angle( -vecSP );

				float s1 = pow( E, -Tsp ) * pow( max( cos(theta_), 0 ), 20 ) * pointLight.intensity() / (Dsp * Dsp),
					s2 = ((pointLight.intensity() * scatteringCoef) / (2.0f*PI * Dsp)
						  * G20.LookUp( Tsp, theta_ ));

				MFloatVector specularResultColor = lightColorVector * (s1 + s2);
				specularResultColor.x *= specularColor.x;
				specularResultColor.y *= specularColor.y;
				specularResultColor.z *= specularColor.z;

				resultColor += specularResultColor;
			}
		}

		// Factor incident light with surface color and add incandescence
		//
		resultColor[0] = resultColor[0] * surfaceColor[0] + incandescence[0];
		resultColor[1] = resultColor[1] * surfaceColor[1] + incandescence[1];
		resultColor[2] = resultColor[2] * surfaceColor[2] + incandescence[2];


		// Set ouput color attribute
		//
		if ( plug == aOutColor || plug == aOutColorR || plug == aOutColorG
				|| plug == aOutColorB)
		{
			// Get the handle to the attribute
			//
			MDataHandle outColorHandle = block.outputValue( aOutColor,
					&status );
			CHECK_MSTATUS( status );
			MFloatVector& outColor = outColorHandle.asFloatVector();
		
			outColor = resultColor;		// Set the output value
			outColorHandle.setClean(); // Mark the output value as clean
		}


		// Set ouput transparency
		//
		if ( plug == aOutTransparency || plug == aOutTransR
				|| plug == aOutTransG || plug == aOutTransB )
		{
			MFloatVector& transparency = block.inputValue( aInTransparency, &status ).asFloatVector();
			CHECK_MSTATUS( status );


			// Get the handle to the attribute
			//
			MDataHandle outTransHandle = block.outputValue( aOutTransparency, &status );
			CHECK_MSTATUS( status );
			MFloatVector& outTrans = outTransHandle.asFloatVector();
			
			outTrans = transparency;   // Set the output value
			outTransHandle.setClean(); // Mark the output value as clean
		}
	} 
	else
	{
		return( MS::kUnknownParameter ); // We got an unexpected plug
	}

	return( MS::kSuccess );
}


