
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_Direct3D_Effects_System.h
// Author : Andy Tate
// Date   : 11-May-2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __ASURA_DIRECT3D_EFFECTS_SYSTEM_H__
#define __ASURA_DIRECT3D_EFFECTS_SYSTEM_H__

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura_Hash.h"
#include "Core/Asura_HashTree.h"
#include "Rendering/Asura_Direct3D_Effect.h"


////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////


#if defined(ASURA_LOAD_EFFECT_FILES) && ASURA_LOAD_EFFECT_FILES == 1
class Asura_Direct3D_Effects_System_Effect
{
	friend class Asura_Direct3D_Effects_System;

	static Asura_Direct3D_Effects_System_Effect *s_pxFirst;
	Asura_Direct3D_Effects_System_Effect *m_pxNext;


	const char* m_szName;
	const void* m_pCompiledShader;
	u_int  m_uCompiledShaderSize;
public:
	Asura_Direct3D_Effects_System_Effect(const char* szName, const void* pCompiledShader, u_int  uCompiledShaderSize);
};

#define ASURA_DECLARE_DIRECT3D_EFFECT(Shader_Name) static Asura_Direct3D_Effects_System_Effect s_xShader_##Shader_Name (#Shader_Name, g_au##Shader_Name, sizeof(g_au##Shader_Name))
#else
#define ASURA_DECLARE_DIRECT3D_EFFECT(Shader_Name) 
#endif

////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////

class Asura_Direct3D_Effects_System
{
	// Private typedefs...

	typedef Asura_TemplateHashTree<Asura_Direct3D_Effect*>		EffectTree;
	typedef Asura_TemplateHashTree_Node<Asura_Direct3D_Effect*>	EffectTreeNode;

public:
	// Public functions...

	// Initialisation functions...
	static	void							Initialise					(void);
	static	void							Reset						(void);
	static	void							Shutdown					(void);

	// Load functions...
	// JAT 22/02/07 only want to load effects in tools builds on current-gen (but on all builds for next-gen)
#if defined( ASURA_TARGET_SM3 ) || defined( ASURA_TOOLS )
	static	Asura_Direct3D_Effect*			LoadEffectFromFile	(const char* szEffectName, const char* szFilename );
#endif // #if defined( ASURA_TARGET_SM3 ) || defined( ASURA_TOOLS )

#if ASURA_LOAD_EFFECT_FILES == 1 && !defined( ASURA_NO_LOAD_EFFECTS_FILES_FROM_FILES)
	static	void							Tools_ReloadAllEffects		(void);
#endif

#if defined(ASURA_TOOLS)
	// I'd rather this returned a const pointer, but I need to use Traverse() which isn't a const-friendly function
	// As this is only available in tools, hopefully this won't be a real problem.
	static EffectTree*						GetEffectTree() { return &s_xEffectTree; }
#endif // #if defined(ASURA_TOOLS)

	static	Asura_Direct3D_Effect*			LoadEffectFromMemory		(const Asura_Hash_ID uEffectID, void const* pvData, const u_int uDataSize );

	// Shared effect parameter functions...
	static	void							SetSharedParameters			(void);

	// Effect usage functions...
	static	Asura_Direct3D_Effect*			BeginEffect					(const char* szEffectName, const u_int uTechniqueIndex = 0);
	static	Asura_Direct3D_Effect*			BeginEffect					(Asura_Direct3D_Effect& xEffect, const u_int uTechniqueIndex = 0);
	static	void							EndEffect					(const Asura_Direct3D_Effect& xEffect);

	static	void							FlushEffects				(void);

	// Accessor functions...
	static	Asura_Direct3D_Effect*			GetEffect					(const Asura_Hash_ID uEffectID);
	static	Asura_Direct3D_Effect*			GetEffect					(const char* szEffectName)
	{
		Asura_Hash_ID uEffectID = Asura_GetHashID (szEffectName);
		return (GetEffect(uEffectID));
	}
	static Asura_Direct3D_Effect* GetCurrentEffect( void ) { return s_pxCurrentEffect; }

	static void SetSharedEffect(Asura_Direct3D_Effect* pxEffect);
	static Asura_Direct3D_Effect* GetSharedEffect() { return s_pxSharedEffect; }

#if ASURA_LOAD_EFFECT_FILES == 1 && !defined( ASURA_NO_LOAD_EFFECTS_FILES_FROM_FILES)
	static void SetShadersPath( const char* const szShadersPath );
#endif

protected:
	// Protected variables...


	// Protected functions...


private:

	// Private variables...

	// Shared effects...
	static	Asura_Direct3D_Effect*	s_pxSharedEffect;

	// Currently begun effect...
	static	Asura_Direct3D_Effect*	s_pxCurrentEffect;
	static	u_int					s_uCurrentTechnique;

	// Tree to store the effects in...
	static	EffectTree				s_xEffectTree;

	static bool						s_bLoadShadersFromDisc;

	// Shared parameters
	// Keep this POD, please - no virtual functions or other weirdnesses that create hidden data (or you'll have to change Reset()).
	struct SharedParameters 
	{
		SharedParameters() { Reset(); }
		void Reset();
		void Get(Direct3D_Effect* pxEffect);

		// Miscellaneous parameters
		D3DXHANDLE m_xViewProjectionMatrix;
		D3DXHANDLE m_xCurrentTime;			
		D3DXHANDLE m_xCameraPosition;		
#ifdef ASURA_TOOLS
		D3DXHANDLE m_xDisableLighting;	
		D3DXHANDLE m_xShowPerPixelNormals;
#endif // #ifdef ASURA_TOOLS
		D3DXHANDLE m_xUseGammaCorrection;
	};
	static SharedParameters s_xSharedParameterHandles;

	// Private functions...
	
	static bool PreResetCallback( void* pData);

	Asura_Direct3D_Effects_System  (void);
	Asura_Direct3D_Effects_System  (const Asura_Direct3D_Effects_System& xOther);
	~Asura_Direct3D_Effects_System ();

	Asura_Direct3D_Effects_System&	operator=					(const Asura_Direct3D_Effects_System& xOther);

};   // End of class 'Asura_Direct3D_Effects_System'.


#endif   // ifndef __ASURA_DIRECT3D_EFFECTS_SYSTEM_H__


/// End of file. ///
