//////////////////////////////////////////////////////////////////////////////
//
// Asura_Xbox360_MaterialResponse_System.h
//
// Copyright (c) 2007 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

#if defined ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#if !defined __ASURA_XBOX360_MATERIALRESPONSE_SYSTEM_H__
#define __ASURA_XBOX360_MATERIALRESPONSE_SYSTEM_H__

/******************************************************************************/
/* Included Files                                                             */
/******************************************************************************/

// Asura Xbox 360
#include "Rendering/Asura_Xbox360_Effect_System.h"
#include "Rendering/Asura_Xbox360_Graphics.h"

/******************************************************************************/
/* Constants                                                                  */
/******************************************************************************/

#ifndef ASURA_XBOX360_MATERIALS_TEXTURE_HEIGHT 
#define ASURA_XBOX360_MATERIALS_TEXTURE_HEIGHT (512)
#endif // #ifndef ASURA_XBOX360_MATERIALS_TEXTURE_HEIGHT 

/******************************************************************************/
/* Classes                                                                    */
/******************************************************************************/

class Asura_Animation;
class Asura_Chunk_Stream;
class Asura_MaterialResponse;
class Asura_Xbox360_XPR;

template< class T > class Asura_TemplateHashTree;

////////////////////////////////////////////////////////////////////////////////
//
// Asura_Xbox360_MaterialResponse_Handles
//
// Class to store parameter handles for a effect which uses the material
// response system
//
////////////////////////////////////////////////////////////////////////////////

class Asura_Xbox360_MaterialResponse_Handles
{
public:

	Asura_Xbox360_MaterialResponse_Handles();
	void InitialiseFromEffect( const Asura_Xbox360_Effect& xEffect );

	Asura_Xbox360_Effect_System::Handle m_xMaterialProperties;
	Asura_Xbox360_Effect_System::Handle m_xMaterialsTexture;

	Asura_Xbox360_Effect_System::Handle m_xUseAlbedo;
	Asura_Xbox360_Effect_System::Handle m_xUseNormalMap;
	Asura_Xbox360_Effect_System::Handle m_xUseSpecularMap;
	Asura_Xbox360_Effect_System::Handle m_xUseTransparencyMap;
	Asura_Xbox360_Effect_System::Handle m_xUseSelfIlluminationMap;
	Asura_Xbox360_Effect_System::Handle m_xUseEnvironmentMap;
	Asura_Xbox360_Effect_System::Handle m_xUseReflectivityMask;
	Asura_Xbox360_Effect_System::Handle m_xUseParallaxMap;

	Asura_Xbox360_Effect_System::Handle m_xDualAlbedo;
	Asura_Xbox360_Effect_System::Handle m_xDualNormalMap;
	Asura_Xbox360_Effect_System::Handle m_xDualSpecularMap;
	Asura_Xbox360_Effect_System::Handle m_xDualTransparencyMap;
	Asura_Xbox360_Effect_System::Handle m_xDualSelfIlluminationMap;
	Asura_Xbox360_Effect_System::Handle m_xDualParallaxMap;

	Asura_Xbox360_Effect_System::Handle m_xAlbedo;
	Asura_Xbox360_Effect_System::Handle m_xNormalMap;
	Asura_Xbox360_Effect_System::Handle m_xSpecularMap;
	Asura_Xbox360_Effect_System::Handle m_xTransparencyMap;
	Asura_Xbox360_Effect_System::Handle m_xSelfIlluminationMap;
	Asura_Xbox360_Effect_System::Handle m_xEnvironmentMap;
	Asura_Xbox360_Effect_System::Handle m_xReflectivityMask;
	Asura_Xbox360_Effect_System::Handle m_xParallaxMap;

	Asura_Xbox360_Effect_System::Handle m_xAlbedo2;
	Asura_Xbox360_Effect_System::Handle m_xNormalMap2;
	Asura_Xbox360_Effect_System::Handle m_xSpecularMap2;
	Asura_Xbox360_Effect_System::Handle m_xTransparencyMap2;
	Asura_Xbox360_Effect_System::Handle m_xSelfIlluminationMap2;
	Asura_Xbox360_Effect_System::Handle m_xParallaxMap2;

	Asura_Xbox360_Effect_System::Handle m_xUV_Offsets;
	Asura_Xbox360_Effect_System::Handle m_xSelfIlluminationParameters;
	Asura_Xbox360_Effect_System::Handle m_xAlbedoModifier;
	Asura_Xbox360_Effect_System::Handle m_xBlendIntoAlbedo;

	Asura_Xbox360_Effect_System::Handle m_xRedSH;
	Asura_Xbox360_Effect_System::Handle m_xGreenSH;
	Asura_Xbox360_Effect_System::Handle m_xBlueSH;
	Asura_Xbox360_Effect_System::Handle m_xSHLightDirection;
	Asura_Xbox360_Effect_System::Handle m_xSHLightColour;

	Asura_Xbox360_Effect_System::Handle m_xFogEnabled;
	Asura_Xbox360_Effect_System::Handle m_xFogTexture;
	Asura_Xbox360_Effect_System::Handle m_xFogColour;
	Asura_Xbox360_Effect_System::Handle m_xFogParams;
};

////////////////////////////////////////////////////////////////////////////////
//
// Asura_Xbox360_MRPShader
//
// Holds a material response pixel shader and a reference to the XPR from which
// it was loaded
//
////////////////////////////////////////////////////////////////////////////////

class Asura_Xbox360_MRPShader
{
public:

	Asura_Xbox360_MRPShader( Direct3D_PixelShader* const pxShader, Asura_Xbox360_XPR& xXPR );
	~Asura_Xbox360_MRPShader();

	Direct3D_PixelShader* GetShader() { return m_pxShader; }
	Asura_Xbox360_XPR& GetXPR() { return m_xXPR; }

protected:

	Direct3D_PixelShader* m_pxShader;
	Asura_Xbox360_XPR& m_xXPR;

private:

	// Prevent copy construction and assignment
	Asura_Xbox360_MRPShader( const Asura_Xbox360_MRPShader& xOther );
	Asura_Xbox360_MRPShader& operator=( const Asura_Xbox360_MRPShader& xOther );
};

////////////////////////////////////////////////////////////////////////////////
//
// Asura_Xbox360_MaterialResponse_System
//
// System to manage material response on 360
//
////////////////////////////////////////////////////////////////////////////////

class Asura_Xbox360_MaterialResponse_System
{
public:

	static void Initialise();
	static void Reset();
	static void Shutdown();

	static void CreateConstantBuffer( const Asura_Hash_ID uNameHash,
									  const Asura_MaterialResponse& xMaterial );

	static Direct3D_Texture* GetDataTexture() { return s_pxMaterialsTexture; }
	static void UpdateDataTexture( Asura_Chunk_Stream& xStream, const int iVersion );

	static void SetBlendStates( const Asura_MaterialResponse* const pxMaterial );

	static void SetEffectParameters( const Asura_MaterialResponse* const pxMaterial1,
		const Asura_MaterialResponse* const pxMaterial2, const Asura_Animation* const pxAnim,
		const Asura_Xbox360_MaterialResponse_Handles& xHandles, Asura_Xbox360_Effect& xEffect );

	static void SetSHParameters( const Asura_MaterialResponse* const pxMaterial,
								 const Asura_Xbox360_MaterialResponse_Handles& xHandles,
								 Asura_Xbox360_Effect& xEffect );

	static void SetFogParameters(bool bIsForwardPass, 
								 const Asura_MaterialResponse* const pxMaterial, 
								 const Asura_Xbox360_MaterialResponse_Handles& xHandles, 
								 Asura_Xbox360_Effect& xEffect );

	static void AddPixelShader( const char* const szName, void* const pData,
								Asura_Xbox360_XPR& xXPR );

	static Direct3D_PixelShader* GetPixelShader( const Asura_Hash_ID uHash );
	static Direct3D_ConstantBuffer* GetConstantBuffer( const Asura_Hash_ID uMaterialName );

	static void SetMaterialConstants( const Asura_MaterialResponse* const pxMaterial1,
		const Asura_MaterialResponse* const pxMaterial2, const Asura_Hash_ID uCBHash,
		const Asura_Animation* const pxAnim );

protected:

	static Direct3D_Texture* s_pxMaterialsTexture;
	static Asura_TemplateHashTree< Asura_Xbox360_MRPShader* > s_xPSTree;
	static Asura_TemplateHashTree< Direct3D_ConstantBuffer* > s_xCBTree;
};

#endif // !defined __ASURA_XBOX360_MATERIALRESPONSE_SYSTEM_H__
