#ifndef RPMATFX_H
#define RPMATFX_H

/**
 * \defgroup rpmatfx RpMatFX
 * \ingroup rpplugin
 *
 * Material Effects Plugin for RenderWare Graphics.
 */

/*===========================================================================*
 *--- Include files ---------------------------------------------------------*
 *===========================================================================*/
#include "rwcore.h"
#include "rpworld.h"

/* RWPUBLIC */

/*===========================================================================*
 *--- Global Types ----------------------------------------------------------*
 *===========================================================================*/

/**
 * \ingroup rpmatfx
 * RpMatFXMaterialFlags, this type represents the different types of 
 * material effects that can be used on a material. The effects are
 * initialized with \ref RpMatFXMaterialSetEffects:
 */
enum RpMatFXMaterialFlags
{
    rpMATFXEFFECTNULL       = 0,
    rpMATFXEFFECTBUMPMAP    = 1, /**<Bump mapping                 */
    rpMATFXEFFECTENVMAP     = 2, /**<Environment mapping          */
    rpMATFXEFFECTBUMPENVMAP = 3, /**<Bump and environment mapping */
    rpMATFXEFFECTDUAL       = 4, /**<Dual pass                    */
    rpMATFXXBOXMT           = 5, /**<Xbox specific multitexturing */

    rpMATFXEFFECTMAX,
    rpMATFXNUMEFFECTS       = rpMATFXEFFECTMAX - 1,

    rpMATFXFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RpMatFXMaterialFlags  RpMatFXMaterialFlags;

typedef struct _RpMultiTexture RpMultiTexture;
typedef struct _RpMTEffect RpMTEffect;

typedef struct RwMatFXInfo RwMatFXInfo;
struct RwMatFXInfo
{
        RwModuleInfo Module;
        RwFreeList * MaterialData;
};

extern RwMatFXInfo MatFXInfo;

/*===========================================================================*
 *--- Plugin API Functions --------------------------------------------------*
 *===========================================================================*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

/*--- Plugin functions ------------------------------------------------------*/
extern RwBool
RpMatFXPluginAttach( void );

/*--- Setup functions -------------------------------------------------------*/
extern RpAtomic *
RpMatFXAtomicEnableEffects( RpAtomic *atomic );

extern RpWorldSector *
RpMatFXWorldSectorEnableEffects( RpWorldSector *worldSector );

extern RpMaterial *
RpMatFXMaterialSetEffects( RpMaterial *material,
                           RpMatFXMaterialFlags flags );


/*--- Setup Effects ---------------------------------------------------------*/
extern RpMaterial *
RpMatFXMaterialSetupBumpMap( RpMaterial *material,
                             RwTexture *texture,
                             RwFrame *frame,
                             RwReal coef );

extern RpMaterial *
RpMatFXMaterialSetupEnvMap( RpMaterial *material,
                            RwTexture *texture,
                            RwFrame *frame,
                            RwBool useFrameBufferAlpha,
                            RwReal coef );

extern RpMaterial *
RpMatFXMaterialSetupDualTexture( RpMaterial *material,
                                 RwTexture *texture,
                                 RwBlendFunction srcBlendMode,
                                 RwBlendFunction dstBlendMode );

/*--- Tinker with effects ---------------------------------------------------*/
extern RpMatFXMaterialFlags
RpMatFXMaterialGetEffects( const RpMaterial *material );

/*--- Bump Map --------------------------------------------------------------*/
extern RpMaterial *
RpMatFXMaterialSetBumpMapTexture( RpMaterial *material,
                                  RwTexture *texture );

extern RpMaterial *
RpMatFXMaterialSetBumpMapFrame( RpMaterial *material,
                                RwFrame *frame );

extern RpMaterial *
RpMatFXMaterialSetBumpMapCoefficient( RpMaterial *material,
                                      RwReal coef );
extern RwTexture *
RpMatFXMaterialGetBumpMapTexture( const RpMaterial *material );

extern RwTexture *
RpMatFXMaterialGetBumpMapBumpedTexture( const RpMaterial *material );

extern RwFrame *
RpMatFXMaterialGetBumpMapFrame( const RpMaterial *material );

extern RwReal
RpMatFXMaterialGetBumpMapCoefficient( const RpMaterial *material );

/*--- Env Map ---------------------------------------------------------------*/
extern RpMaterial *
RpMatFXMaterialSetEnvMapTexture( RpMaterial *material,
                                 RwTexture *texture );

extern RpMaterial *
RpMatFXMaterialSetEnvMapFrame( RpMaterial *material,
                               RwFrame *frame );

extern RpMaterial *
RpMatFXMaterialSetEnvMapFrameBufferAlpha( RpMaterial *material,
                                          RwBool useFrameBufferAlpha );

extern RpMaterial *
RpMatFXMaterialSetEnvMapCoefficient( RpMaterial *material,
                                     RwReal coef );

extern RwTexture *
RpMatFXMaterialGetEnvMapTexture( const RpMaterial *material );

extern RwFrame *
RpMatFXMaterialGetEnvMapFrame( const RpMaterial *material );

extern RwBool
RpMatFXMaterialGetEnvMapFrameBufferAlpha( const RpMaterial *material );

extern RwReal
RpMatFXMaterialGetEnvMapCoefficient( const RpMaterial *material );

/*--- Dual Pass -------------------------------------------------------------*/
extern RpMaterial *
RpMatFXMaterialSetDualTexture( RpMaterial *material,
                               RwTexture *texture );

extern RpMaterial *
RpMatFXMaterialSetDualBlendModes( RpMaterial *material,
                                  RwBlendFunction srcBlendMode,
                                  RwBlendFunction dstBlendMode );

extern RwTexture *
RpMatFXMaterialGetDualTexture( const RpMaterial *material );

extern const RpMaterial *
RpMatFXMaterialGetDualBlendModes( const RpMaterial *material,
                                  RwBlendFunction *srcBlendMode,
                                  RwBlendFunction *dstBlendMode );


/*--- MultiTextureEffect Functions ------------------------------------------*/
extern RpMTEffect *
RpMTEffectCreateDummy(RwChar *name);

extern void
RpMTEffectDestroy(RpMTEffect *effect);

extern RwChar *
RpMTEffectGetName(RpMTEffect *effect);

extern RpMTEffect *
RpMTEffectAddRef(RpMTEffect *effect);


/*--- MultiTexture Functions ------------------------------------------------*/
extern RwUInt32
RpMultiTextureGetNumTextures(RpMultiTexture *multiTexture);

extern RpMultiTexture *
RpMultiTextureSetTexture(RpMultiTexture *multiTexture, 
                         RwUInt32        index, 
                         RwTexture      *texture);

extern RwTexture *
RpMultiTextureGetTexture(RpMultiTexture *multiTexture, 
                         RwUInt32        index);

extern RpMultiTexture *
RpMultiTextureSetCoords(RpMultiTexture *multiTexture, 
                        RwUInt32        index, 
                        RwUInt32        texCoordIndex);

extern RwUInt32
RpMultiTextureGetCoords(RpMultiTexture *multiTexture, 
                        RwUInt32        index);

extern RpMultiTexture *
RpMultiTextureSetEffect(RpMultiTexture *multiTexture,
                        RpMTEffect    *effect);

extern RpMTEffect *
RpMultiTextureGetEffect(RpMultiTexture *multiTexture);


/*--- Material MultiTexture Functions ---------------------------------------*/
extern RpMaterial *
RpMaterialCreateMultiTexture(RpMaterial *material,
                             RwPlatformID platformID,
                             RwUInt32 numTextures);

extern RpMaterial *
RpMaterialDestroyMultiTexture(RpMaterial *material,
                              RwPlatformID platformID);

extern RpMultiTexture *
RpMaterialGetMultiTexture(RpMaterial *material,
                          RwPlatformID platformID);

extern RwBool
RpMaterialQueryMultiTexturePlatform(RpMaterial *material,
                                    RwPlatformID platformID);

/* RWPUBLICEND */

extern RwTexture *
_rpMatFXTextureMaskCreate( const RwTexture *baseTexture, 
                           const RwTexture *effectTexture );

extern RwUInt32
_rpMatFXStreamWriteTexture(RwStream * stream,
                           const RwTexture * texture);

extern RwUInt32
_rpMatFXStreamReadTexture(RwStream * stream,
                          RwTexture ** texture);
    
RwUInt32
_rpMatFXStreamSizeTexture(const RwTexture * texture);



/* Backwards compatibility macros */

#define MatFXStreamWriteTexture(stream, texture) \
        _rpMatFXStreamWriteTexture(stream, texture)

#define MatFXStreamReadTexture(stream, texture) \
        _rpMatFXStreamReadTexture(stream, texture)
    
#define MatFXStreamSizeTexture(texture) \
        _rpMatFXStreamSizeTexture(texture)

#ifdef __cplusplus
}
#endif /* __cplusplus */

#if defined(GCN_DRVMODEL_H) || defined(NULLGCN_DRVMODEL_H)
#include "rpmfxgcn.h"
#endif

#if defined(XBOX_DRVMODEL_H) \
    || defined(NULLXBOX_DRVMODEL_H) || defined(NULL_DRVMODEL_H)
#include "rpmfxxbx.h"
#endif

#endif /* RPMATFX_H */
