#include "cgfxShaderCommon.h"
#include <float.h>                     
#include <limits.h>                    
#include <string.h>
#include <maya/MIOStream.h>
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MStringArray.h>
#include <maya/MFnStringData.h>
#include <maya/MFnStringArrayData.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MDGModifier.h>
#include <maya/MFnMatrixData.h>
#include <maya/MPlugArray.h>
#include <maya/MItDependencyGraph.h>
#include <maya/MSelectionList.h>
#include "cgfxAttrDef.h"
#include "cgfxShaderNode.h"
#include "cgfxFindImage.h"
#include "cgfxTextureCache.h"
#define N_MAX_STRING_LENGTH 1024
#ifdef _WIN32
#else
#   define stricmp  strcasecmp
#   define strnicmp strncasecmp
#endif
const char cgfxAttrDef::fSymbol = '_';
cgfxAttrDef::cgfxAttrDef(CGparameter cgParameter)
: fType( kAttrTypeUnknown )
, fSize( 0 )
, fHint( kVectorHintNone )
, fNumericMin( NULL )
, fNumericMax( NULL )
, fNumericSoftMin( NULL )
, fNumericSoftMax( NULL )
, fNumericDef( NULL )
, fTextureMonitor(kNullCallback)
, fParameterHandle(0)
, fInvertMatrix( false )
, fTransposeMatrix( false )
, fTweaked( false )
, fInitOnUndo( false )
, fIsConvertedToInternal( false )
{
    fName = cgGetParameterName(cgParameter);
    fType = cgfxAttrDef::kAttrTypeOther;
    fSize = cgGetParameterRows(cgParameter) * cgGetParameterColumns(cgParameter);
    fParameterHandle = cgParameter;
    fSemantic = cgGetParameterSemantic(cgParameter);
    CGtype cgParameterType = cgGetParameterType(cgParameter);
    switch (cgParameterType)
    {
        case CG_BOOL    : 
            if (stricmp(fSemantic.asChar() , "HardwareFogEnabled") == 0)
                fType = cgfxAttrDef::kAttrTypeHardwareFogEnabled;
            else 
                fType = cgfxAttrDef::kAttrTypeBool; 
            break ;
        case CG_INT     : 
            if (stricmp(fSemantic.asChar() , "HardwareFogMode") == 0)
                fType = cgfxAttrDef::kAttrTypeHardwareFogMode;
            else 
                fType = cgfxAttrDef::kAttrTypeInt; 
            break ;
        case CG_HALF    :
        case CG_FLOAT :
            if (stricmp(fSemantic.asChar() , "HardwareFogStart") == 0)
                fType = cgfxAttrDef::kAttrTypeHardwareFogStart;
            else if (stricmp(fSemantic.asChar() , "HardwareFogEnd") == 0)
                fType = cgfxAttrDef::kAttrTypeHardwareFogEnd;
            else if (stricmp(fSemantic.asChar() , "HardwareFogDensity") == 0)
                fType = cgfxAttrDef::kAttrTypeHardwareFogDensity;
#ifdef _WIN32
            else if (stricmp(fSemantic.asChar() , "Time")==0)
                fType = cgfxAttrDef::kAttrTypeTime;
#endif
            else 
                fType = cgfxAttrDef::kAttrTypeFloat;
            break;
        case CG_HALF2               :
        case CG_FLOAT2          : 
            fType = cgfxAttrDef::kAttrTypeVector2; 
            break ;
        case CG_HALF3               :
        case CG_FLOAT3          : 
               fType = cgfxAttrDef::kAttrTypeVector3; 
            break ;
        case CG_HALF4               :
        case CG_FLOAT4          : 
            if (stricmp(fSemantic.asChar() , "HardwareFogColor") == 0)
                fType = cgfxAttrDef::kAttrTypeHardwareFogColor;
            else
                fType = cgfxAttrDef::kAttrTypeVector4; 
            break ;
        case CG_HALF4x4         :
        case CG_FLOAT4x4        : 
            setMatrixType(cgParameter); 
            break ;
        case CG_STRING          : 
            fType = cgfxAttrDef::kAttrTypeString; 
            break ;
        case CG_TEXTURE         :
            
            break ;
        case CG_SAMPLER1D       : 
        case CG_SAMPLER2D       :
        case CG_SAMPLER3D       :
        case CG_SAMPLERRECT :
        case CG_SAMPLERCUBE :
            setSamplerType(cgParameter);
            break ;
        case CG_ARRAY               :
        case CG_STRUCT          :
            break ;
        default                         : 
            MString msg = cgGetTypeString(cgParameterType);
 
            msg += " not yet supported";
            M_CHECK( false );
    }
    if (fType == cgfxAttrDef::kAttrTypeVector3 ||
        fType == cgfxAttrDef::kAttrTypeVector4)
    {
        
        
        setVectorType(cgParameter);
    }
    
    
    
    
        
    CGannotation cgAnnotation = cgGetFirstParameterAnnotation(cgParameter);
    while (cgAnnotation)
    {
        const char* annotationName      = cgGetAnnotationName(cgAnnotation);
        const char* annotationValue     = cgGetStringAnnotationValue(cgAnnotation);
        CGtype          cgAnnotationType    = cgGetAnnotationType(cgAnnotation);
        if (stricmp(annotationName, "uihelp") == 0)
        {
            fDescription = 
MString(annotationValue);
        }
        else if (stricmp(annotationName, "uiname" ) == 0 )
        {
            sUIName = 
MString(annotationValue);
        }
        else if( stricmp( annotationName, "units") == 0)
        {
            
            
            if ( fSymbol == annotationValue[0] ) 
            {
                fIsConvertedToInternal = true;
                annotationValue++;
            }
            else
            {
                fIsConvertedToInternal = false;
            }
            if( stricmp( annotationValue, "inches") == 0)
            {
            }
            else if( stricmp( annotationValue, "millimetres") == 0 || stricmp( annotationValue, "millimeters") == 0 || stricmp( annotationValue, "mm") == 0)
            {
            }
            else if( stricmp( annotationValue, "centimetres") == 0 || stricmp( annotationValue, "centimeters") == 0 || stricmp( annotationValue, "cm") == 0)
            {
            }
            else if( stricmp( annotationValue, "metres") == 0 || stricmp( annotationValue, "meters") == 0 || stricmp( annotationValue, "m") == 0)
            {
            }
            else if( stricmp( annotationValue, "kilometres") == 0 || stricmp( annotationValue, "kilometers") == 0 || stricmp( annotationValue, "km") == 0)
            {
            }
            else if( stricmp( annotationValue, "feet") == 0)
            {
            }
        }
        else if ((fType >= cgfxAttrDef::kAttrTypeFirstTexture &&
                  fType <= cgfxAttrDef::kAttrTypeLastTexture))
        {
            if (stricmp(annotationName, "resourcetype") == 0)
            {
                if (stricmp(annotationValue, "1d") == 0)
                {
                    fType = cgfxAttrDef::kAttrTypeColor1DTexture;
                }
                else if (stricmp(annotationValue, "2d") == 0)
                {
                    fType = cgfxAttrDef::kAttrTypeColor2DTexture;
                }
                else if (stricmp(annotationValue, "3d") == 0)
                {
                    fType = cgfxAttrDef::kAttrTypeColor3DTexture;
                }
                else if (stricmp(annotationValue, "cube") == 0)
                {
                    fType = cgfxAttrDef::kAttrTypeCubeTexture;
                }
                else if (stricmp(annotationValue, "rect") == 0)
                {
                    fType = cgfxAttrDef::kAttrTypeColor2DRectTexture;
                }
            }
            else if (stricmp(annotationName, "resourcename") == 0)
            {
                
                
                
                
                
                
                fStringDef = annotationValue;
            }
        }
        else if (cgAnnotationType == CG_BOOL )
        {}                     
        else if (stricmp(annotationName, "min") == 0 ||
                 stricmp(annotationName, "max") == 0 ||
                 stricmp(annotationName, "uimin") == 0 ||
                 stricmp(annotationName, "uimax") == 0 )
        {
            double * tmp = new double [fSize];
            switch (cgAnnotationType)
            {
                case CG_INT:
                    {
                        
                        
                        
                        
                        
                        
                        int nValues;
                        const int* annotationValues = cgGetIntAnnotationValues(cgAnnotation, &nValues);
                        
                        for (int iValue = 0; iValue < nValues; ++iValue)
                            tmp[iValue] = static_cast<double>(annotationValues[iValue]);
                    }   
                    break;
                case CG_FLOAT:
                    {
                        
                        
                        
                        
                        
                        int nValues;
                        const float* annotationValues = cgGetFloatAnnotationValues(cgAnnotation, &nValues);
                        for (int iValue = 0; iValue < nValues; ++iValue)
                            tmp[iValue] = static_cast<double>(annotationValues[iValue]);
                    }
                    break;
                default:
                    
                    delete [] tmp;
                    tmp = 0;
                    break;
            }
            if (stricmp(annotationName, "min") == 0)
            {
                fNumericMin = tmp;
            }
            else if (stricmp(annotationName, "max") == 0)
            {
                fNumericMax = tmp;
            }
            else if (stricmp(annotationName, "uimin") == 0)
            {
                fNumericSoftMin = tmp;
            }
            else 
            {
                fNumericSoftMax = tmp;
            }
        } 
        cgAnnotation = cgGetNextAnnotation(cgAnnotation);
    }
    
    if ( fType == cgfxAttrDef::kAttrTypeColor3 ||
         fType == cgfxAttrDef::kAttrTypeColor4 )
    {
        if ( !fNumericMin )
        {
            fNumericMin = new double[4];
            fNumericMin[0] = 0.0;
            fNumericMin[1] = 0.0;
            fNumericMin[2] = 0.0;
            fNumericMin[3] = 0.0;
        }
        if ( !fNumericMax )
        {
            fNumericMax = new double[4];
            fNumericMax[0] = 1.0;
            fNumericMax[1] = 1.0;
            fNumericMax[2] = 1.0;
            fNumericMax[3] = 1.0;
        }
    }
    
    if ( !fDescription.length() )
        fDescription = sUIName;
    
    
    double* tmp = new double [fSize];
    CGtype cgParameterBaseType = cgGetParameterBaseType(cgParameter);
    switch (cgParameterBaseType)
    {
        case CG_BOOL:
            {
                int val;
                if (cgGetParameterValueic(cgParameter, 1, &val) != 1)
                {
                    delete [] tmp;
                    tmp = 0;
                    break;
                }
                for (int k = 0; k < fSize; ++k)
                {
                    tmp[k] = val ? 1 : 0;
                }
            }
            break;
        case CG_INT:
            {
                int val;
                if (cgGetParameterValueic(cgParameter, 1, &val) != 1)
                {
                    delete [] tmp;
                    tmp = 0;
                    break;
                }
                for (int k = 0; k < fSize; ++k)
                {
                    tmp[k] = val;
                }
            }
            break;
        case CG_FLOAT:
            {
                if (fSize == 1)
                {
                    float val;
                    if (cgGetParameterValuefc(cgParameter, 1, &val) != 1)
                    {
                        delete [] tmp;
                        tmp = 0;
                        break;
                    }
                    
                    if( fIsConvertedToInternal)
                    {
                    }
                    tmp[0] = val;
                }
                else if (fSize <= 4 || fType == cgfxAttrDef::kAttrTypeMatrix)
                {
                    float val[16];
                    if (fType == kAttrTypeMatrix)
                    {
                        cgGetMatrixParameterfc(cgParameter, val);
                    }
                    else
                    {
                        unsigned int vecSize = fSize;
                        cgGetParameterValuefc(cgParameter, vecSize, val);
                    }
                    
                     for (int k = 0; k < fSize; ++k)
                    {
                        
                        if( fIsConvertedToInternal)
                        {
                        }
                        tmp[k] = val[k];
                    }
                    
                }
            }
            break;
        case CG_STRING:
            {
#ifdef _WIN32
                LPCSTR val;
#else
                const char* val = NULL;
#endif
                val = cgGetStringParameterValue(cgParameter);
                fStringDef = val;
            }
            
            
            
        default:
            
            
            
            delete [] tmp;
            tmp = 0;
    }
    
    if ( tmp )
    {
        int k;
        if ( fSize == 16 )
        {
            for ( k = 0; k < fSize; ++k )
                if ( tmp[ k ] != d[ k ] )
                    break;
        }
        else
        {
            for ( k = 0; k < fSize; ++k )
                if ( tmp[ k ] != 0.0 )
                    break;
        }
        if ( k == fSize )
        {
            delete [] tmp;
            tmp = 0;
        }
    }
    fNumericDef = tmp;
};
cgfxAttrDef::cgfxAttrDef(
    const cgfxAttrType      eAttrType,
)
: fType( kAttrTypeUnknown )
, fSize( 0 )
, fHint( kVectorHintNone )
, fNumericMin( NULL )
, fNumericMax( NULL )
, fNumericSoftMin( NULL )
, fNumericSoftMax( NULL )
, fNumericDef( NULL )
, fTextureMonitor(kNullCallback)
, fParameterHandle(0)
, fInvertMatrix( false )
, fTransposeMatrix( false )
, fTweaked( false )
, fInitOnUndo( false )
, fIsConvertedToInternal(false)
{
    
    fName = sAttrName;
    fType = eAttrType;
    fDescription = sDescription;
    fSemantic = sSemantic;
    fAttr = obAttr;
    MPlug   plug( obNode, obAttr );
 
    double  numericMin[4];
    double  numericMax[4];
    double  numericValue[4];
    bool    hasMin    = false;
    bool    hasMax    = false; 
    bool    isNumeric = false;
    
    {
        hasMin = true;
        hasMax = true;
        isNumeric = true;
        int iChild;
        M_CHECK( nChild >= 2 && nChild <= 3 );
        for ( iChild = 0; iChild < nChild; ++iChild )
        {
            
            if ( iChild < 3 )
            {
                obChild = fnCompound.
child( iChild, &status );
                M_CHECK( status );
            }
            M_CHECK( status );
            
                fnNumeric.
getMin( numericMin[ iChild ] );
            else
                hasMin = false; 
            
                fnNumeric.
getMax( numericMax[ iChild ] );
            else
                hasMax = false; 
            
            MPlug plChild( obNode, obChild );
 
            status = plChild.getValue( numericValue[ iChild ] );
            M_CHECK( status );
            
            if ( iChild == 2 )
            {
                const char* suffix = NULL;
                if ( saChild[0] == sAttrName + "X" &&
                     saChild[1] == sAttrName + "Y" &&
                     saChild[2] == sAttrName + "Z" ) 
                    suffix = "W";
                else if ( saChild[0] == sAttrName + "R" &&
                          saChild[1] == sAttrName + "G" &&
                          saChild[2] == sAttrName + "B" ) 
                    suffix = "Alpha";
                if ( suffix )
                {
                    MString sName2 = sAttrName + suffix;
 
                    obChild = fnNode.attribute( sName2, &status );
                    if ( status &&
                    {
                        fAttr2 = obChild;
                        nChild = 4;     
                    }
                }
            }
        }                          
        fSize = nChild;
    }                              
    
    {
        M_CHECK( status );
    
        fSize = 1;
        isNumeric = true;
        
        {
            fnNumeric.
getMin( numericMin[0] );
            hasMin = true;
        }
        {
            fnNumeric.
getMax( numericMax[0] );
            hasMax = true;
        }
        
        {
            fNumericSoftMin = new double[1];
        }
        {
            fNumericSoftMax = new double[1];
        }
        
        status = plug.getValue( numericValue[0] );
        M_CHECK( status );
    }                              
    
    {
        fSize = 1;
        status = plug.getValue( fStringDef );
        M_CHECK( status );
    }                           
    
    {
        status = plug.getValue( obData );
        M_CHECK( status );
        M_CHECK( status );
        M_CHECK( status );
        fSize = 16;
        fNumericDef = new double[ fSize ];
        const double* p = &(mat.
matrix[0][0]);
 
        for ( int i = 0; i < 16; ++i )
            fNumericDef[ i ] = p[ i ];
        M_CHECK( status );
    }                           
    
    else
        M_CHECK( false );
    
    
    if ( isNumeric )
    {
        fNumericDef = new double[ fSize ];
        memcpy( fNumericDef, numericValue, fSize * sizeof( numericValue[0] ) );
        if ( hasMin )
        {
            fNumericMin = new double[ fSize ];
            memcpy( fNumericMin, numericMin, fSize * sizeof( numericMin[0] ) );
        }
        if ( hasMax )
        {
            fNumericMax = new double[ fSize ];
            memcpy( fNumericMax, numericMax, fSize * sizeof( numericMax[0] ) );
        }
    }
    
    setAttributeFlags();
}
cgfxAttrDef::~cgfxAttrDef()
{
    release();
    delete [] fNumericMin;
    delete [] fNumericMax;
    delete [] fNumericSoftMin;
    delete [] fNumericSoftMax;
    delete [] fNumericDef;
};
void cgfxAttrDef::release()
{
    releaseTexture();
    releaseCallback();
}
void cgfxAttrDef::releaseTexture()
{
    fTexture = cgfxRCPtr<cgfxTextureCacheEntry>();
}
void cgfxAttrDef::releaseCallback()
{
    if( fTextureMonitor != kNullCallback)
    {
        fTextureMonitor = kNullCallback;
    }
}
void cgfxAttrDef::setTextureType(CGparameter cgParameter)
{
    fType = kAttrTypeColor2DTexture;
    const char* semantic = cgGetParameterSemantic(cgParameter);
    if (!semantic) return;
    
    if (semantic)
    {
        if (stricmp(semantic, "normal") == 0)
        {
            fType = kAttrTypeNormalTexture;
        }
        else if (stricmp(semantic, "height") == 0)
        {
            fType = kAttrTypeBumpTexture;
        }
        else if (stricmp(semantic, "environment") == 0)
        {
            fType = kAttrTypeEnvTexture;
        }
        else if (stricmp(semantic, "environmentnormal") == 0)
        {
            fType = kAttrTypeNormalizationTexture;
        }
    }
    
    
    CGannotation cgAnnotation = cgGetFirstParameterAnnotation(cgParameter);
    while (cgAnnotation)
    {
        const char* annotationName  = cgGetAnnotationName(cgAnnotation);
        const char* annotationValue = cgGetStringAnnotationValue(cgAnnotation);
        
        if (stricmp(annotationName, "resourcetype") == 0)
        {
            if (stricmp(annotationValue, "1d") == 0)
            {
                fType = kAttrTypeColor1DTexture;
            }
            else if (stricmp(annotationValue, "2d") == 0)
            {
                fType = kAttrTypeColor2DTexture;
            }
            else if (stricmp(annotationValue, "rect") == 0)
            {
                fType = kAttrTypeColor2DRectTexture;
            }
            else if (stricmp(annotationValue, "3d") == 0)
            {
                fType = kAttrTypeColor3DTexture;
            }
            else if (stricmp(annotationValue, "cube") == 0)
            {
                fType = kAttrTypeCubeTexture;
            }
        }
        else if (stricmp(annotationName, "resourcename") == 0)
        {
            
            
            
            
            
            
            fStringDef = annotationValue;
        }
        else if (stricmp(annotationName, "uvlink") == 0)
        {
            
            
            fTextureUVLink = annotationValue;
        }
        cgAnnotation = cgGetNextAnnotation(cgAnnotation);
    }
}
void cgfxAttrDef::setSamplerType(CGparameter cgParameter)
{
    CGstateassignment cgStateAssignment = cgGetNamedSamplerStateAssignment(cgParameter, "texture");
    setTextureType(cgGetTextureStateAssignmentValue(cgStateAssignment));
}
void cgfxAttrDef::setMatrixType(CGparameter cgParameter)
{
    fType = kAttrTypeMatrix;
    const char* semantic = cgGetParameterSemantic(cgParameter);
    if (!semantic)
        return;
    if (stricmp(semantic, "world") == 0)
    {
        fType = kAttrTypeWorldMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "worldinverse") == 0)
    {
        fType = kAttrTypeWorldMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "worldtranspose") == 0)
    {
        fType = kAttrTypeWorldMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "worldinversetranspose") == 0)
    {
        fType = kAttrTypeWorldMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "worldview") == 0)
    {
        fType = kAttrTypeWorldViewMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "worldviewtranspose") == 0)
    {
        fType = kAttrTypeWorldViewMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "worldviewinverse") == 0)
    {
        fType = kAttrTypeWorldViewMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "worldviewinversetranspose") == 0)
    {
        fType = kAttrTypeWorldViewMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "worldviewprojection") == 0)
    {
        fType = kAttrTypeWorldViewProjectionMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "worldviewprojectiontranspose") == 0)
    {
        fType = kAttrTypeWorldViewProjectionMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "worldviewprojectioninverse") == 0)
    {
        fType = kAttrTypeWorldViewProjectionMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "worldviewprojectioninversetranspose") == 0)
    {
        fType = kAttrTypeWorldViewProjectionMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "view") == 0)
    {
        fType = kAttrTypeViewMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "viewinverse") == 0)
    {
        fType = kAttrTypeViewMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "viewtranspose") == 0)
    {
        fType = kAttrTypeViewMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "viewinversetranspose") == 0)
    {
        fType = kAttrTypeViewMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "projection") == 0)
    {
        fType = kAttrTypeProjectionMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "projectioninverse") == 0)
    {
        fType = kAttrTypeProjectionMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = false;
    }
    else if (stricmp(semantic, "projectiontranspose") == 0)
    {
        fType = kAttrTypeProjectionMatrix;
        fInvertMatrix = false;
        fTransposeMatrix = true;
    }
    else if (stricmp(semantic, "projectioninversetranspose") == 0)
    {
        fType = kAttrTypeProjectionMatrix;
        fInvertMatrix = true;
        fTransposeMatrix = true;
    }
}
void cgfxAttrDef::setVectorType(CGparameter cgParameter)
{
#if 0
    
    static char* colorList[] = 
    {
        "diffuse",
        "specular",
        "ambient",
        "emissive",
    };
#endif
    const char* semantic = cgGetParameterSemantic(cgParameter);
    if ((semantic == NULL || strcmp(semantic,"") == 0) == false)
    {
        
        
        if (stricmp(semantic, "diffuse") == 0 ||
            stricmp(semantic, "specular") == 0 ||
            stricmp(semantic, "ambient") == 0 ||
            stricmp(semantic, "emissive") == 0)
        {
            fType = (fSize == 3) ? kAttrTypeColor3 : kAttrTypeColor4;
        }
        else if (stricmp(semantic, "direction") == 0)
        {
            fType = kAttrTypeFirstDir;
        }
        else if (stricmp(semantic, "position") == 0)
        {
            fType = kAttrTypeFirstPos;
        }
    }
    CGannotation cgAnnotation = cgGetFirstParameterAnnotation(cgParameter);
    while (cgAnnotation)
    {
        const char* annotationName  = cgGetAnnotationName(cgAnnotation);
        const char* annotationValue = cgGetStringAnnotationValue(cgAnnotation);
        
        if (stricmp(annotationName, "type") == 0)
        {
            if (strlen(annotationValue) != 0)
            {
                if (stricmp(annotationValue, "color") == 0)
                {
                    fType = (fSize == 3) ? kAttrTypeColor3 : kAttrTypeColor4;
                }
            }
        }
        else if (stricmp(annotationName, "space") == 0)
        {
            
            
            if(fType != kAttrTypeFirstDir && fType != kAttrTypeFirstPos)
            {
                const MString warnMsg = fName + 
" has space annotation but doesn't have semantic to determine if it is a direction or position! Assuming it to be a direction. You'd better add a semantic for it!";
 
                fType = kAttrTypeFirstDir;
            }
                
            if (stricmp(annotationValue, "world") == 0)
            {
                fType = (cgfxAttrType)(fType + kAttrTypeWorldDir - kAttrTypeFirstDir);
            }
            else if (stricmp(annotationValue, "view") == 0 ||
                stricmp(annotationValue, "devicelightspace") == 0)
            {
                fType = (cgfxAttrType)(fType + kAttrTypeViewDir - kAttrTypeFirstDir);
            }
            else if (stricmp(annotationValue, "projection") == 0)
            {
                fType = (cgfxAttrType)(fType + kAttrTypeProjectionDir - kAttrTypeFirstDir);
            }
            else if (stricmp(annotationValue, "screen") == 0)
            {
                fType = (cgfxAttrType)(fType + kAttrTypeScreenDir - kAttrTypeFirstDir);
            }
        }
        else if (stricmp(annotationName, "object") == 0)
        {
            fHint = kVectorHintNone;
            if (stricmp(annotationValue, "dirlight") == 0)
            {
                fHint = kVectorHintDirLight;
            }
            else if (stricmp(annotationValue, "spotlight") == 0)
            {
                fHint = kVectorHintSpotLight;
            }
            else if (stricmp(annotationValue, "pointlight") == 0)
            {
                fHint = kVectorHintPointLight;
            }
            else if (stricmp(annotationValue, "camera") == 0 || stricmp(annotationValue, "eye") == 0)
            {
                fHint = kVectorHintEye;
            }
        }
        cgAnnotation = cgGetNextAnnotation(cgAnnotation);
    }
    return;
}
cgfxRCPtr<cgfxAttrDefList> cgfxAttrDef::attrsFromNode(
MObject& oNode)
{
    M_CHECK( status );
    M_CHECK( fnNode.typeId() == cgfxShaderNode::sId );
    cgfxShaderNode* pNode = (cgfxShaderNode *) fnNode.userNode();
    M_CHECK( pNode );
    cgfxRCPtr<cgfxAttrDefList> list = pNode->attrDefList();
    
    
    if (list.isNull())
    {
        buildAttrDefList(oNode);
        list = pNode->attrDefList();
    }
    return list;
}
void cgfxAttrDef::buildAttrDefList(
MObject& oNode)
 
{
    M_CHECK( status &&
             fnNode.typeId() == cgfxShaderNode::sId );
    cgfxShaderNode* pNode = (cgfxShaderNode *) fnNode.userNode();
    M_CHECK( pNode && pNode->attrDefList().isNull() );
    cgfxRCPtr<cgfxAttrDefList> list(new cgfxAttrDefList);
    pNode->getAttributeList(saList);
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    unsigned int i;
    for (i = 0; i < saList.
length(); ++i)
 
    {
        item.
split(
'\t', splitItem);
        cgfxAttrDef* attrDef = attrFromNode( fnNode,
                                             splitItem[0], 
                                             (cgfxAttrType)(splitItem[1].asInt()),
                                             splitItem[2],
                                             splitItem[3]);
        if ( attrDef )
        {
            list->add( attrDef );
        }
    }
    pNode->setAttrDefList(list);
}
cgfxAttrDef*
                           const cgfxAttrType       eAttrType,
{
    cgfxAttrDef* attrDef = NULL;
    try
    {
        if ( !status )                 
            return NULL;               
        attrDef = new cgfxAttrDef(
            sAttrName, eAttrType, sDescription, sSemantic,
            obNode, obAttr
        );
    }
    catch ( cgfxShaderCommon::InternalError* e )   
    {
        size_t ee = (size_t)e;
        sMsg += (int)ee;
        sMsg += ") cgfxShader node \"";
        sMsg += "\" has invalid attribute \"";
        sMsg += sAttrName;
        sMsg += "\" - ignored";
        delete attrDef;
        attrDef = NULL; 
    }
    catch (...)
    {
        delete attrDef;
        M_CHECK( false );
    }
    return attrDef;
}                                      
bool
cgfxAttrDef::createAttribute( 
const MObject& oNode, 
MDGModifier* mod, cgfxShaderNode* pNode)
{
    
    
    if ( !obExistingAttr.
isNull() )
 
    {
        return false;
    }
    try
    {
        bool doConnection = false;
        switch (fType)
        {
        case kAttrTypeBool:
                0.0, &status );
            M_CHECK( status );
            break;
        case kAttrTypeInt:
                0.0, &status );
            M_CHECK( status );
            break;
        case kAttrTypeFloat:
                0.0, &status );
            M_CHECK( status );
            break;
        case kAttrTypeString:
            M_CHECK( status );
            break;
        case kAttrTypeVector2:
        case kAttrTypeVector3:
        case kAttrTypeVector4:
        case kAttrTypeColor3:
        case kAttrTypeColor4:
        case kAttrTypeObjectDir:
        case kAttrTypeWorldDir:
        case kAttrTypeViewDir:
        case kAttrTypeProjectionDir:
        case kAttrTypeScreenDir:
        case kAttrTypeObjectPos:
        case kAttrTypeWorldPos:
        case kAttrTypeViewPos:
        case kAttrTypeProjectionPos:
        case kAttrTypeScreenPos:
            {
                const char** suffixes = compoundAttrSuffixes( fType );
                M_CHECK( fSize <= 4 );
                for ( int iChild = 0; iChild < fSize; ++iChild )
                {
                    const char* suffix = suffixes[ iChild ];
                    sChild = fName + suffix;
                    oaChildren[ iChild ] = nAttr.
create( sChild,
                        sChild,
                        0.0,
                        &status );
                    M_CHECK( status );
                }
                if ( fSize == 4 )
                {
                    oAttr2 = oaChildren[3];
                    if ( fType == kAttrTypeColor3 ||
                        fType == kAttrTypeColor4 ||
                        fDescription.length() > 0 )
                }
                    fName,
                    oaChildren[0],
                    oaChildren[1],
                    oaChildren[2], 
                    &status );
                M_CHECK( status );
                if ( fType == kAttrTypeColor3 ||
                    fType == kAttrTypeColor4 )
                {
                }
                else if ( fDescription.length() > 0 )
                break;
            }
        case kAttrTypeMatrix:
            
            
            oAttr = mAttr.
create(fName, fName,
            M_CHECK( status );
            break;
        case kAttrTypeWorldMatrix:
        case kAttrTypeViewMatrix:
        case kAttrTypeProjectionMatrix:
        case kAttrTypeWorldViewMatrix:
        case kAttrTypeWorldViewProjectionMatrix:
            
            
            break;
        case kAttrTypeColor1DTexture:
        case kAttrTypeColor2DTexture:
        case kAttrTypeColor3DTexture:
        case kAttrTypeColor2DRectTexture:
        case kAttrTypeNormalTexture:
        case kAttrTypeBumpTexture:
        case kAttrTypeCubeTexture:
        case kAttrTypeEnvTexture:
        case kAttrTypeNormalizationTexture:
            if( pNode->getTexturesByName())
            {
                M_CHECK( status );
            }
            else
            {
                const char* suffix1 = "R";
                const char* suffix2 = "G";
                const char* suffix3 = "B";
                    fName + suffix1,
                    0.0, &status);
                    fName + suffix2,
                    0.0, &status);
                    fName + suffix3,
                    0.0, &status);
                    fName,
                    oChild1,
                    oChild2,
                    oChild3, 
                    &status );
                M_CHECK( status );
                
                
                
                
            }
            break;
#ifdef _WIN32
        case kAttrTypeTime:
#endif
        case kAttrTypeHardwareFogEnabled:
        case kAttrTypeHardwareFogMode:
        case kAttrTypeHardwareFogStart:
        case kAttrTypeHardwareFogEnd:
        case kAttrTypeHardwareFogDensity:
        case kAttrTypeHardwareFogColor:
        case kAttrTypeOther:
            break;
        default:
            M_CHECK( false );
        }
        {
            
            
            return false;
        }
        
        
        M_CHECK( status );
        {
            M_CHECK( status );
        }
        
        fAttr  = oAttr;
        fAttr2 = oAttr2;
        
        
        if (doConnection)
        {
            status = mod->
connect(oSrcNode, oSrcAttr, oDstNode, oDstAttr);
            M_CHECK( status );
        }
        return true;                   
    }
    catch ( cgfxShaderCommon::InternalError* e )   
    {
        size_t ee = (size_t)e;
        fType = kAttrTypeUnknown;
        sMsg += (int)ee;
        sMsg += ") cgfxShader node \"";
        sMsg += "\": unable to add attribute \"";
        sMsg += fName;
        sMsg += "\"";
        return false;                  
    }
    catch (...)
    {
        M_CHECK( false );
    }
    return true;
}                                      
bool
{
    
    
    if( fType >= kAttrTypeFirstTexture && fType <= kAttrTypeLastTexture)
        setTexture( oNode, "", dgMod);
    
    
    if ( !fAttr2.isNull() )
    
}                                      
void
cgfxAttrDef::updateNode(
    const cgfxRCPtr<const cgfxEffect>&  effect,         
    cgfxShaderNode*                     pNode,          
    cgfxRCPtr<cgfxAttrDefList>&         effectList,     
{
    effectList = cgfxRCPtr<cgfxAttrDefList>();
    try
    {
        MObject           oNode = pNode->thisMObject();
 
        effectList = effect->attrsFromEffect();  
        cgfxRCPtr<cgfxAttrDefList> nodeList = attrsFromNode( oNode ); 
        cgfxAttrDefList::iterator emIt;
        cgfxAttrDefList::iterator nmIt;
        cgfxAttrDef* adef;
        
        
        
        for (nmIt = nodeList->begin(); nmIt; ++nmIt)
        {                              
            adef = (*nmIt);
            
            if ( adef->fAttr.isNull() )
                continue;
            
            emIt = effectList->find( adef->fName );
            
            
            
            if ( !emIt ||
                (*emIt)->fType != adef->fType )
            {
                adef->destroyAttribute( oNode, dgMod);
            }
            
            
            
            else if( emIt && 
                (*emIt)->fType >= kAttrTypeFirstTexture &&
                (*emIt)->fType <= kAttrTypeLastTexture)
            {
                
                
                
                pNode->setTexturesByName( usesName);
                
                
                
                
                
                
                
                
                
                
                
                
                if( !usesName)
                    (*emIt)->fTweaked = true;
            }
        }                              
        
        
        
        
        
        
        
        for (emIt = effectList->begin(); emIt; ++emIt)
        {                              
            adef = (*emIt);
            
            
            
            nmIt = nodeList->find( adef->fName );
            
            cgfxAttrDef* cdef = NULL;
            if ( nmIt &&
                !(*nmIt)->fAttr.isNull() )
                cdef = attrFromNode( fnNode,
                (*nmIt)->fName, 
                (*nmIt)->fType,
                (*nmIt)->fDescription,
                (*nmIt)->fSemantic);
            
            if ( !cdef )
                adef->createAttribute( oNode, dgMod, pNode );
            
            else
            {                          
                
                adef->fAttr  = (*nmIt)->fAttr;
                adef->fAttr2 = (*nmIt)->fAttr2;
                
                if ( (*nmIt)->fTweaked )
                    adef->fTweaked = true;
                
                
                
                else if ( pNode->effect().isNull() )
                {
                    if ( !adef->isInitialValueEqual( *cdef ) )
                        adef->fTweaked = true;
                }
                
                
                
                else if ( !(*nmIt)->isInitialValueEqual( *cdef ) )
                    adef->fTweaked = true;
                
                
                
                
                
                
                else
                    (*nmIt)->fInitOnUndo = true;
                delete cdef;
            }                          
        }                              
        
        
        
        cgfxAttrDefList::iterator it(effectList);
        while (it)
        {
            cgfxAttrDef* aDef = *it;
            tmpStr = aDef->fName;
            tmpStr += "\t";
            tmpStr += (int)aDef->fType;
            tmpStr += "\t";
            tmpStr += aDef->fDescription;
            tmpStr += "\t";
            tmpStr += aDef->fSemantic;
            
            const char* bp = tmpStr.
asChar();
 
            const char* ep;
            for ( ep = bp + tmpStr.
length(); bp < ep; --ep )
 
                if ( ep[-1] != '\t' )
                    break;
            ++it;
        }
    }
    catch ( cgfxShaderCommon::InternalError* )   
    {
        throw;
    }
    catch (...)
    {
        M_CHECK( false );
    }
}                                      
bool
cgfxAttrDef::isInitialValueEqual( const cgfxAttrDef& that ) const
{
    if ( fStringDef != that.fStringDef )
        return false;
    const double* thisNumericDef = fNumericDef;
    const double* thatNumericDef = that.fNumericDef;
    if ( thisNumericDef == thatNumericDef ) 
        return true;
    
    
    
    if( fType == that.fType && fType >= kAttrTypeFirstTexture && fType <= kAttrTypeLastTexture)
        return true;
    if ( !thisNumericDef )
    {
        thisNumericDef = thatNumericDef;
        thatNumericDef = fNumericDef;
    }
    if ( !thatNumericDef )
    {
        if ( fType == kAttrTypeMatrix )
        {
            M_CHECK( fSize == 16 && that.fSize == 16 );
        }
        else
        {
            static const double d0[4] = {0.0, 0.0, 0.0, 0.0};
            thatNumericDef = d0;
            M_CHECK( fSize <= sizeof(d0)/sizeof(d0[0]) );
            if ( fSize != that.fSize )
        }
    }
    double eps = 0.0001;
    int i;
    for ( i = 0; i < fSize; ++i )
        if ( thisNumericDef[ i ] + eps < thatNumericDef[ i ] ||
            thatNumericDef[ i ] + eps < thisNumericDef[ i ] )
            return false;
    return true;
}                                      
void
cgfxAttrDef::setInitialValue( const cgfxAttrDef& from )
{
    if ( from.fNumericDef )
    {
        M_CHECK( fSize == from.fSize );
        if ( !fNumericDef )
            fNumericDef = new double[ fSize ];
        memcpy( fNumericDef, from.fNumericDef, fSize * sizeof( *fNumericDef ) );
    }
    else
    {
        delete fNumericDef;
        fStringDef = from.fStringDef;
    }
}                                      
void cgfxAttrDef::setAttributeFlags()
{
        return ;
    switch (fType)
    {
    case kAttrTypeColor3:
    case kAttrTypeColor4:
        break;
    case kAttrTypeBool:
    case kAttrTypeInt:
    case kAttrTypeFloat:
        break;
    
    case kAttrTypeVector2:
    case kAttrTypeVector3:
    case kAttrTypeVector4:
    case kAttrTypeObjectDir:
    case kAttrTypeWorldDir:
    case kAttrTypeViewDir:
    case kAttrTypeProjectionDir:
    case kAttrTypeScreenDir:
    case kAttrTypeObjectPos:
    case kAttrTypeWorldPos:
    case kAttrTypeViewPos:
    case kAttrTypeProjectionPos:
    case kAttrTypeScreenPos:
        if( fDescription.length() > 0)
        break;
    case kAttrTypeString:
    case kAttrTypeMatrix: 
        break;
    case kAttrTypeWorldMatrix:
    case kAttrTypeViewMatrix:
    case kAttrTypeProjectionMatrix:
    case kAttrTypeWorldViewMatrix:
    case kAttrTypeWorldViewProjectionMatrix:
        
        
        break;
    case kAttrTypeColor1DTexture:
    case kAttrTypeColor2DTexture:
    case kAttrTypeColor3DTexture:
    case kAttrTypeColor2DRectTexture:
    case kAttrTypeNormalTexture:
    case kAttrTypeBumpTexture:
    case kAttrTypeCubeTexture:
    case kAttrTypeEnvTexture:
    case kAttrTypeNormalizationTexture:
        
        break;
#ifdef _WIN32
    case kAttrTypeTime:
#endif
    case kAttrTypeHardwareFogEnabled:
    case kAttrTypeHardwareFogMode:
    case kAttrTypeHardwareFogStart:
    case kAttrTypeHardwareFogEnd:
    case kAttrTypeHardwareFogDensity:
    case kAttrTypeHardwareFogColor:
    case kAttrTypeOther:
        break;
    default:
        M_CHECK( false );
    }
}
void
cgfxAttrDef::initializeAttributes(
    const cgfxRCPtr<cgfxAttrDefList>&   list,
    bool                                bUndoing,
{
    for ( cgfxAttrDefList::iterator it( list ); it; ++it )
    {                                  
        cgfxAttrDef* aDef = (*it);
        if ( aDef->fAttr.isNull() )    
            continue;                  
        bool bSetValue = bUndoing ? aDef->fInitOnUndo
            : !aDef->fTweaked;
        try
        {
            
            if ( aDef->fType == kAttrTypeBool )
            {
                if ( bSetValue )
                    aDef->setValue( oNode, aDef->fNumericDef && aDef->fNumericDef[0] );
            }
            
            
            
            else if( aDef->fType >= kAttrTypeFirstTexture && 
                aDef->fType <= kAttrTypeLastTexture)
            {
                if ( bSetValue )
                    aDef->setTexture( oNode, aDef->fStringDef, dgMod);
            }
            
            else if ( fnNumeric.
setObject( aDef->fAttr ) ) 
 
            {                          
                
                double vMin = -FLT_MAX;
                double vMax = FLT_MAX;
                if ( aDef->fType == kAttrTypeInt )
                {
                    vMin = INT_MIN;
                    vMax = INT_MAX;
                }
                
                switch ( aDef->fSize )
                {                      
                case 1:
                    if ( aDef->fNumericMin )
                        fnNumeric.
setMin( aDef->fNumericMin[0] );
                    else if ( fnNumeric.
hasMin() )
 
                    if ( aDef->fNumericMax )
                        fnNumeric.
setMax( aDef->fNumericMax[0] );
                    else if ( fnNumeric.
hasMax() )
 
                    if ( aDef->fNumericSoftMin )
                    if ( aDef->fNumericSoftMax )
                    break;
                case 2:
                    if ( aDef->fNumericMin )
                        fnNumeric.
setMin( aDef->fNumericMin[0], 
                        aDef->fNumericMin[1] );
                    else if ( fnNumeric.
hasMin() )
 
                        fnNumeric.
setMin( vMin, vMin );
                    if ( aDef->fNumericMax )
                        fnNumeric.
setMax( aDef->fNumericMax[0], 
                        aDef->fNumericMax[1] );
                    else if ( fnNumeric.
hasMax() )
 
                        fnNumeric.
setMax( vMax, vMax );
                    break;
                case 3:
                case 4:
                    if ( aDef->fNumericMin )
                        fnNumeric.
setMin( aDef->fNumericMin[0], 
                        aDef->fNumericMin[1],
                        aDef->fNumericMin[2] );
                    else if ( fnNumeric.
hasMin() )
 
                        fnNumeric.
setMin( vMin, vMin, vMin );
                    if ( aDef->fNumericMax )
                        fnNumeric.
setMax( aDef->fNumericMax[0], 
                        aDef->fNumericMax[1],
                        aDef->fNumericMax[2] );
                    else if ( fnNumeric.
hasMax() )
 
                        fnNumeric.
setMax( vMax, vMax, vMax );
                    break;
                default:
                    M_CHECK( false );
                }                      
                
                
                if ( bSetValue )
                {                      
                    static const double d0[4] = {0.0, 0.0, 0.0, 0.0};
                    const double* pNumericDef = aDef->fNumericDef ? aDef->fNumericDef
                        : d0;
                    switch ( aDef->fSize )
                    {                  
                    case 1:
                        if ( aDef->fType == kAttrTypeInt )
                            aDef->setValue( oNode, (int)pNumericDef[0] );
                        else
                            aDef->setValue( oNode, (float)pNumericDef[0] );
                        break;
                    case 2:
                        aDef->setValue( oNode,
                            (float)pNumericDef[0],
                            (float)pNumericDef[1] );
                        break;
                    case 3:
                        aDef->setValue( oNode,
                            (float)pNumericDef[0],
                            (float)pNumericDef[1],
                            (float)pNumericDef[2] );
                        break;
                    case 4:
                        status = fnNumeric.
setObject( aDef->fAttr2 );
                        M_CHECK( status );
                        if ( aDef->fNumericMin )
                            fnNumeric.
setMin( aDef->fNumericMin[3] );
                        else if ( fnNumeric.
hasMin() )
 
                        if ( aDef->fNumericMax )
                            fnNumeric.
setMax( aDef->fNumericMax[3] );
                        else if ( fnNumeric.
hasMax() )
 
                        aDef->setValue( oNode,
                            (float)pNumericDef[0],
                            (float)pNumericDef[1],
                            (float)pNumericDef[2],
                            (float)pNumericDef[3] );
                        break;
                    default:
                        M_CHECK( false );
                    }                  
                }                      
            }                          
            
            else if ( fnTyped.
setObject( aDef->fAttr ) &&
 
            {
                if ( bSetValue )
                    aDef->setValue( oNode, aDef->fStringDef );
            }
            
            else if ( fnMatrix.
setObject( aDef->fAttr ) )
 
            {
                if ( !bSetValue )
                {}
                else if ( aDef->fNumericDef )
                {
                    for ( int k = 0; k < 16; ++k )
                        p[ k ] = aDef->fNumericDef[ k ];
                    aDef->setValue( oNode, m );
                }
                else
            }
        }
        catch ( cgfxShaderCommon::InternalError* e )   
        {
            size_t ee = (size_t)e;
            sMsg += (int)ee;
            sMsg += ") cgfxShader node \"";
            sMsg += "\": unable to initialize attribute \"";
            sMsg += aDef->fName;
            sMsg += "\"";
        }
    }                                  
}                                      
void cgfxAttrDef::purgeMObjectCache(const cgfxRCPtr<cgfxAttrDefList>& list)
{                                       
    cgfxAttrDefList::iterator it( list );
    for ( ; it; ++it )
    {
        cgfxAttrDef* aDef = (*it);
    }
}                                      
void cgfxAttrDef::validateMObjectCache(
    const cgfxRCPtr<cgfxAttrDefList>&   list)
{                                       
    cgfxAttrDefList::iterator it( list );
    for ( ; it; ++it )
    {
        cgfxAttrDef* aDef = (*it);
        aDef->fAttr = fnNode.
attribute( aDef->fName, &status );
        
        const char* suffix = aDef->getExtraAttrSuffix();
        if ( suffix )
            aDef->fAttr2 = fnNode.
attribute( aDef->fName + suffix, &status );
    }
}                                      
const char*
cgfxAttrDef::getExtraAttrSuffix() const
{
    if ( fSize == 4 )
        return compoundAttrSuffixes( fType )[ 3 ];
    return NULL;
}                                      
const char* cgfxAttrDef::typeName( cgfxAttrType type )
{
#define CASE(name) case kAttrType##name: return #name
    switch (type)
    {
    default:    
        CASE(Unknown);
        CASE(Bool);
        CASE(Int);
        CASE(Float);
        CASE(String);
        CASE(Vector2);
        CASE(Vector3);
        CASE(Vector4);
        CASE(ObjectDir);
        CASE(WorldDir);
        CASE(ViewDir);
        CASE(ProjectionDir);
        CASE(ScreenDir);
        CASE(ObjectPos);
        CASE(WorldPos);
        CASE(ViewPos);
        CASE(ProjectionPos);
        CASE(ScreenPos);
        CASE(Color3);
        CASE(Color4);
        CASE(Matrix);
        CASE(WorldMatrix);
        CASE(ViewMatrix);
        CASE(ProjectionMatrix);
        CASE(WorldViewMatrix);
        CASE(WorldViewProjectionMatrix);
        CASE(Color1DTexture);
        CASE(Color2DTexture);
        CASE(Color3DTexture);
        CASE(Color2DRectTexture);
        CASE(NormalTexture);
        CASE(BumpTexture);
        CASE(CubeTexture);
        CASE(EnvTexture);
        CASE(NormalizationTexture);
#ifdef _WIN32
        CASE(Time);
#endif
        CASE(HardwareFogEnabled);
        CASE(HardwareFogMode);
        CASE(HardwareFogStart);
        CASE(HardwareFogEnd);
        CASE(HardwareFogDensity);
        CASE(HardwareFogColor);
        CASE(Other);
    }
}
const char**
cgfxAttrDef::compoundAttrSuffixes( cgfxAttrType eAttrType )
{
    static const char* simple[] = { NULL, NULL, NULL, NULL,    NULL };
    static const char* vector[] = { "X",  "Y",  "Z",  "W",     NULL };
    static const char* color[]  = { "R",  "G",  "B",  "Alpha", NULL };
    const char** p;
    switch ( eAttrType )
    {
    case kAttrTypeVector2:
    case kAttrTypeVector3:
    case kAttrTypeVector4:
    case kAttrTypeObjectDir:
    case kAttrTypeWorldDir:
    case kAttrTypeViewDir:
    case kAttrTypeProjectionDir:
    case kAttrTypeScreenDir:
    case kAttrTypeObjectPos:
    case kAttrTypeWorldPos:
    case kAttrTypeViewPos:
    case kAttrTypeProjectionPos:
    case kAttrTypeScreenPos:
        p = vector;
        break;
    case kAttrTypeColor3:
    case kAttrTypeColor4:
        p = color;
        break;
    default:
        p = simple;
        break;
    }
    return p;
}                                      
void
cgfxAttrDef::getValue( 
MObject& oNode, 
bool& value )
 const{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(value);
    M_CHECK( status );
}
void
cgfxAttrDef::getValue( 
MObject& oNode, 
int& value )
 const{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(value);
    M_CHECK( status );
}
void
cgfxAttrDef::getValue( 
MObject& oNode, 
float& value )
 const{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(value);
    if( fUnits != MDistance::kInvalid)
    {
    }
    M_CHECK( status );
}
void
{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(value);
    M_CHECK( status );
}
void
cgfxAttrDef::getValue( 
MObject& oNode, 
float& v1, 
float& v2 )
 const{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(oData);
    M_CHECK( status );
    M_CHECK( status );
    status = fnData.getData(v1, v2);
    M_CHECK( status );
    if( fUnits != MDistance::kInvalid)
    {
    }
}
void
cgfxAttrDef::getValue( 
MObject& oNode,
                                            float& v1, float& v2, float& v3 ) const
{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(oData);
    M_CHECK( status );
    M_CHECK( status );
    status = fnData.getData(v1, v2, v3);
    M_CHECK( status );
    if( fUnits != MDistance::kInvalid)
    {
    }
}
void
cgfxAttrDef::getValue( 
MObject& oNode,
                                            float& v1, float& v2, float& v3, float& v4 ) const
{
    MPlug plug(oNode, fAttr);
 
    MPlug plug2(oNode, fAttr2);
 
    status = plug.getValue(oData);
    M_CHECK( status );
    M_CHECK( status );
    status = fnData.getData(v1, v2, v3);
    M_CHECK( status );
    
    
    status = plug2.getValue(v4);
    M_CHECK( status );
    if( fUnits != MDistance::kInvalid)
    {
    }
}
void
{
    MPlug plug(oNode, fAttr);
 
    status = plug.getValue(oData);
    M_CHECK( status );
    M_CHECK( status );
    value = fnData.
matrix(&status);
    M_CHECK( status );
}
void
{
    MPlug plug(oNode, fAttr);
 
    if (fType >= kAttrTypeFirstTexture &&
        fType <= kAttrTypeLastTexture)
    {
        plug.connectedTo(plugArray, true, false, &status);
        M_CHECK( status );
        {
            M_CHECK( status );
        }
        MPlug srcPlug = plugArray[0];
 
        
        M_CHECK( status );
    }
    M_CHECK( status );
}
void
{
    MPlug plug(oNode, fAttr);
 
    plug.connectedTo(plugArray, true, false, &status);
    M_CHECK( status && plugArray.
length() <= 1);
        src = plugArray[0];
}
void
cgfxAttrDef::setValue( 
MObject& oNode, 
bool value )
{
    MPlug plug(oNode, fAttr);
 
    status = plug.setValue(value);
    M_CHECK( status );
}
void
cgfxAttrDef::setValue( 
MObject& oNode, 
int value )
{
    MPlug plug(oNode, fAttr);
 
    status = plug.setValue(value);
    M_CHECK( status );
}
void
cgfxAttrDef::setValue( 
MObject& oNode, 
float value )
{
    MPlug plug(oNode, fAttr);
 
    
    status = plug.setValue(value);
    M_CHECK( status );
}
void
{
    MPlug plug(oNode, fAttr);
 
    status = plug.setValue((
MString &)value);
    M_CHECK( status );
}
void
cgfxAttrDef::setValue( 
MObject& oNode, 
float v1, 
float v2 )
{
    MPlug plug(oNode, fAttr);
 
    M_CHECK( status );
    status = plug.setValue(oData);
    M_CHECK( status );
}
void
cgfxAttrDef::setValue( 
MObject& oNode, 
float v1, 
float v2, 
float v3 )
{
    MPlug plug(oNode, fAttr);
 
    M_CHECK( status );
    status = plug.setValue(oData);
    M_CHECK( status );
}
void
cgfxAttrDef::setValue( 
MObject& oNode, 
float v1, 
float v2, 
float v3, 
float v4 )
{
    MPlug plug(oNode, fAttr);
 
    MPlug plug2(oNode, fAttr2);
 
    M_CHECK( status );
    
    status = plug.setValue(oData);
    M_CHECK( status );
    status = plug2.setValue(v4);
    M_CHECK( status );
}
void
{
    M_CHECK( status );
    MPlug plug( oNode, fAttr );
 
    status = plug.setValue( oData );
    M_CHECK( status );
}
{
    {
        
        
        if( iter.thisNode() != node)
        {
            if( iter.thisNode() != user)
            {
                
                
                
                
                if( src.
length() == 1 && src[ 0].partialName() != 
"msg")
 
                {
                    
                    
                    
                    if( dgFn.name() != "swatchShadingGroup")
                    {
                        
                        
                        
                        return true;
                    }
                }
            }
            
            
            
            iter.prune();
        }
    }
    return false;
}
void
{
    MPlug plug(oNode, fAttr);
 
    
    
    if( attrFn.isUsedAsColor() )
    {
        
        
        
        if( plug.isConnected())
        {
            plug.connectedTo( src, true, false, &status);
            M_CHECK( status );
            {
                MObject textureNode = src[ 0].node();
 
                
                
                
                if( !isUsedElsewhere( textureNode, oNode))
                {
                    
                    
                    
                    
                    MPlug uvPlug = textureFn.findPlug( 
"uv", &status);
 
                    {
                        uvPlug.
connectedTo( placementNode, 
true, 
false, &status);
                        M_CHECK( status );
                        
                        
                        
                        if( placementNode.
length() > 0 &&
 
                            !isUsedElsewhere( placementNode[ 0].node(), textureNode))
                        {
                            M_CHECK( dgMod->
deleteNode( placementNode[ 0].node()) );
                        }
                    }
                    
                    
                }
                else
                {
                    
                    
                }
            }
        }
        
        
        {
            
            
            
            
            
            
            MString relativePath = cgfxFindFile( value, 
true );
 
            
            
            
            if( relativePath.
length() == 0) relativePath = value;
 
            
            
            
            
            
            MObject textureNode, placementNode;
 
            
            
            M_CHECK( status );
            M_CHECK( status );
            
            
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"coverage"), fileTextureFn.findPlug( 
"coverage")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"translateFrame"), fileTextureFn.findPlug( 
"translateFrame")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"rotateFrame"), fileTextureFn.findPlug( 
"rotateFrame")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"mirrorU"), fileTextureFn.findPlug( 
"mirrorU")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"mirrorV"), fileTextureFn.findPlug( 
"mirrorV")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"stagger"), fileTextureFn.findPlug( 
"stagger")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"wrapU"), fileTextureFn.findPlug( 
"wrapU")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"wrapV"), fileTextureFn.findPlug( 
"wrapV")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"repeatUV"), fileTextureFn.findPlug( 
"repeatUV")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"offset"), fileTextureFn.findPlug( 
"offset")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"rotateUV"), fileTextureFn.findPlug( 
"rotateUV")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"noiseUV"), fileTextureFn.findPlug( 
"noiseUV")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"vertexUvOne"), fileTextureFn.findPlug( 
"vertexUvOne")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"vertexUvTwo"), fileTextureFn.findPlug( 
"vertexUvTwo")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"vertexUvThree"), fileTextureFn.findPlug( 
"vertexUvThree")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"vertexCameraOne"), fileTextureFn.findPlug( 
"vertexCameraOne")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"outUV"), fileTextureFn.findPlug( 
"uv")) );
            M_CHECK( dgMod->
connect( placementFn.findPlug( 
"outUvFilterSize"), fileTextureFn.findPlug( 
"uvFilterSize")) );
            
            
            M_CHECK( dgMod->
connect( fileTextureFn.findPlug( 
"outColor"), plug) );
            status = fileTextureFn.findPlug( "fileTextureName").setValue( relativePath);
            M_CHECK( status );
        }
        M_CHECK( dgMod->
doIt() );
    }
    else
    {
        
        
        {
            status = plug.setValue((
MString &)value);
            M_CHECK( status );
        }
    }
}
void cgfxAttrDef::setUnitsToInternal( CGparameter& cgParameter ) 
{
    
    
    if (fIsConvertedToInternal) return;
    CGannotation cgAnnotation = cgGetFirstParameterAnnotation(cgParameter);
    while (cgAnnotation)
    {
        const char* annotationName      = cgGetAnnotationName(cgAnnotation);
        const char* annotationValue     = cgGetStringAnnotationValue(cgAnnotation);
        if( stricmp( annotationName, "units" ) == 0)
        {
            unit += annotationValue;
            
            cgSetStringAnnotation(cgAnnotation, unit.asChar());
            
            fIsConvertedToInternal = true;
            return;
        }
        cgAnnotation = cgGetNextAnnotation(cgAnnotation);
    }
}
cgfxAttrDefList::iterator
cgfxAttrDefList::findInsensitive( 
const MString& name )
{
    const char* pName = name.
asChar();
 
    unsigned    lName = name.
length();
 
    iterator    it( *this );
    for ( ; it; ++it )
        if ( lName == (*it)->fName.length() &&
            0 == stricmp( pName, (*it)->fName.asChar() ) )
            break;
    return it;
};                                     
void cgfxAttrDefList::release()
{
    --refcount;
    if (refcount <= 0)
    {
        M_CHECK( refcount == 0 );
        delete this;
    }
};
void cgfxAttrDefList::releaseTextures()
{
    iterator it(*this);
    while (it)
    {
        (*it)->release();
        ++it;
    }
}
void cgfxAttrDefList::dump(const char* name)
{
    fprintf(stderr, "Dumping cgfxAttrDefList %s : \n", name);
  
    for (cgfxAttrDefList::iterator it = begin(); it; ++it) {
        cgfxAttrDef* aDef = (*it);
        fprintf(
            stderr,
            "   name=%s, type=%s, size=%d, attr=%s, hint=%d, attr2=%s, def=%s, desc=%s, semantic=%s, CGParameter=0x%p\n",
            aDef->fName.asChar(),
            cgfxAttrDef::typeName(aDef->fType),
            aDef->fSize,
            aDef->fAttr.apiTypeStr(),
            aDef->fHint,
            aDef->fAttr2.apiTypeStr(),
            aDef->fStringDef.asChar(),
            aDef->fDescription.asChar(),
            aDef->fSemantic.asChar(),
            aDef->fParameterHandle
        );
    }
}