#ifndef _cgfxShaderNode_h_
#define _cgfxShaderNode_h_
#include "cgfxShaderCommon.h"
#include <maya/MFnNumericAttribute.h>
#include <maya/MNodeMessage.h>
#include <maya/MObjectArray.h>
#include <maya/MCallbackIdArray.h>
#include <maya/MPxHwShaderNode.h>
#include <maya/MPxNode.h>
#include <maya/MStateManager.h>
#include <maya/MStringArray.h>
#include <maya/MTypeId.h>
#include <maya/MPxShaderOverride.h>
#include "cgfxRCPtr.h"
#include "cgfxEffectDef.h"
#include "cgfxAttrDef.h"
#include <set>
#include <map>
class cgfxProfile;
class cgfxPassStateSetter;
#define  CGFXSHADERNODE_GL_TEXTURE_MAX  32       // GL_TEXTURE31-GL_TEXTURE0+1
#define  CGFXSHADERNODE_GL_COLOR_MAX 1
{
    friend class cgfxAttrDef; 
    friend class cgfxShaderOverride;
public:
    cgfxShaderNode();
                    ~cgfxShaderNode() override;
    
    
    
    
    static  void*       creator();
    
    
    static  void        initializeNodeAttrs();
    
    
    
    
    
    
    
    
    
    void            bindAttrValues();
    void            bindViewAttrValues(
const MDagPath& shapePath);
 
#if MAYA_API_VERSION >= 700
    #define _SWATCH_RENDERING_SUPPORTED_ 1
#endif
#if defined(_SWATCH_RENDERING_SUPPORTED_)
    
#endif
    
    
    
    
        int prim,
        unsigned int writable,
        int indexCount,
        const unsigned int * indexArray,
        int vertexCount,
        const int * vertexIDs,
        const float * vertexArray,
        int normalCount,
        const float ** normalArrays,
        int colorCount,
        const float ** colorArrays,
        int texCoordCount,
        const float ** texCoordArrays) override;
    
    
    
    
#if MAYA_API_VERSION >= 700
#else
#endif
    
    
                                floatRegion region,
                                int& imageWidth,
                                int& imageHeight) override;
                                floatRegion region,
                                int& imageWidth,
                                int& imageHeight) override;
    
    
    const cgfxRCPtr<cgfxAttrDefList>& attrDefList() const { return fAttrDefList; };
    void setAttrDefList(const cgfxRCPtr<cgfxAttrDefList>& list);
    
    
    
    MString shaderFxFile()
 const { 
return fShaderFxFile; };
 
    bool shaderFxFileChanged() const { return fShaderFxFileChanged; }
    void setShaderFxFileChanged(bool val) { fShaderFxFileChanged = val; if (val) ++fGeomReqDataVersionId; }
    
    MString         getTechnique()
 const { 
return fTechnique; };
 
    const MStringArray& getTechniqueList()
 const { 
return fTechniqueList; }
 
    
    MString         getProfile()
 const { 
return fProfileName; };
 
    
    
    
    
    void                setVertexAttributes( cgfxRCPtr<cgfxVertexAttribute> attributeList);
    
    void                setVertexAttributeSource( 
const MStringArray& sources);
 
    
    void                analyseVertexAttributes();
    
    
    
    
    inline bool getTexturesByName() const { return fTexturesByName; };
    
    
    const cgfxRCPtr<const cgfxEffect>& effect() { return fEffect; };
    void setEffect(const cgfxRCPtr<const cgfxEffect>& effect);
    
protected:
    
    bool            createEffect();
    
    void            setShaderFxFile( 
const MString& fxFile )
 
    {
        if (fxFile != fShaderFxFile)
        {
            
            fShaderFxFile = fxFile;
            fShaderFxFileChanged = true;
            fLastShaderFxFileAtVASSet = "";
            ++fGeomReqDataVersionId;
        }
    };
    void            setTechnique( 
const MString& techn );
 
    void            setProfile( 
const MString& profileName );
 
    void            setProfile( const cgfxProfile* profile );
    void            setTexturesByName( bool texturesByName, bool updateAttributes = false);
    void            updateTechniqueList();
    
    void            reportInternalError( const char* function, size_t errcode);
public:
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    static  MObject sVertexAttributeList;
 
    
    static  MObject sVertexAttributeSource;
 
    
    
    
    
    static  CGcontext   sCgContext;
    
    static void         cgErrorCallBack();
    
    static void         cgErrorHandler(CGcontext cgContext, CGerror cgError, void* userData);
protected:
    
    cgfxRCPtr<const cgfxEffect> fEffect;
    
    
    cgfxRCPtr<cgfxVertexAttribute>  fVertexAttributes;
    
    
    cgfxRCPtr<cgfxAttrDefList> fAttrDefList;
    
    bool                    fShaderFxFileChanged;
    const cgfxTechnique*    fCurrentTechnique;
    bool                    fTexturesByName;
    
    
    
    int             fNormalsPerVertex;
    
    
    
    
    
    
    
    
    
    cgfxStructureCache fBoundDataCache;
    
    cgfxPassStateSetter* fPassStateSetters;
    
    GLboolean       fDepthEnableState;
    GLint           fDepthFunc;
    GLint           fBlendSourceFactor;
    GLint           fBlendDestFactor;
    
    bool            fConstructed;      
    short           fErrorCount;
    short           fErrorLimit;
    
    
    
    
    int             fGeomReqDataVersionId;
public:
    typedef std::set<cgfxShaderNode*> NodeList;
    static void getNodesUsingEffect(const cgfxRCPtr<const cgfxEffect>& effect, NodeList &nodes);
private:
    
    typedef std::map<const cgfxEffect*, NodeList> Effect2NodesMap;
    static Effect2NodesMap sEffect2NodesMap;
    static void addAssociation(cgfxShaderNode* node, const cgfxRCPtr<const cgfxEffect>& effect);
    static void removeAssociation(cgfxShaderNode* node, const cgfxRCPtr<const cgfxEffect>& effect);
    
};
{
public:
    ~cgfxShaderOverride() override;
    
    
    
    
    {
        return !fShaderNode ||
            fShaderNode->fGeomReqDataVersionId != fGeomReqDataVersionId;
    }
public:
    static const MString drawDbClassification;
 
    static const MString drawRegistrantId;
 
protected:
    cgfxShaderOverride(
const MObject& obj);
 
    
    bool bindAttrValues() const;
    
    cgfxShaderNode *fShaderNode;
    int fGeomReqDataVersionId;
    mutable bool fNeedPassSetterInit;
    static cgfxShaderNode* sActiveShaderNode;
    static cgfxShaderNode* sLastDrawShaderNode;
};
#endif