
//////////////////////////////////////////////////////////////////////////////////////////
//
//  FILE : Tools_StaticDecal_System.h
//
//  Created by Dave Reed - 07/08/07
//
//  Copyright (C) 2007 Rebellion (Derby), All Rights Reserved.
//
//  Static Decal management/creation for tools
//
//////////////////////////////////////////////////////////////////////////////////////////


#ifndef __TOOLS_STATICDECAL_SYSTEM_H__
#define __TOOLS_STATICDECAL_SYSTEM_H__

#include "Objects/Tools_Object.h"
#include "Decals/Tools_Mode_Decals.h"
#include "SpecialFX/Asura_Decal_Manager.h"


enum
{
	TOOLS_STATICDECAL_USAGE_USERCREATED,
	TOOLS_STATICDECAL_USAGE_BOTANICALSHADOW,
};


class Tools_StaticDecal
{
public:

	Tools_StaticDecal()
	{
		m_iModuleIndex  = -2;
		m_xPosition	    = Asura_Vector_3(0,0,0);
		m_xOrient	    = Asura_Maths::IdentityMatrix3x3;
		m_fScale	    = 1.0f;
		m_fAlpha	    = 1.0f;
		m_iDecalIndex   = 0;
		m_uDecalSetHash = 0;
		m_uUsage	    = TOOLS_STATICDECAL_USAGE_USERCREATED;
	}

	Asura_Vector_3		m_xPosition;
	Asura_Matrix_3x3	m_xOrient;
	uint32				m_uDecalSetHash;
	int					m_iDecalIndex;
	int					m_iModuleIndex;			// -2 means not initialised, -1 means not in a module
	float				m_fScale;
	float				m_fAlpha;
	uint32				m_uUsage;

	class Tools_StaticDecal_Buffer *m_pxBuffer;	// Buffer that this decal belongs to
};



// Important - This is now the same as a D3D_DecalVertex in the platform render code.
// This lets us use the existing shaders to render the decals when in tools mode
class Tools_StaticDecal_Vertex
{
public:

	Asura_Vector_3  xPos;
	float			fU,fV;	
	float			fCreationTime;		// (Creation Time for non-static decals)
	float			fAlpha;
	Asura_Vector_3  xNormal;
	Asura_Vector_3  xTangent;
	Asura_Vector_3  xBinormal;
	// Note this only works with because the above is 16byte aligned
	Asura_AVector4  xSHRed;
	Asura_AVector4  xSHGreen;
	Asura_AVector4  xSHBlue;
};



// Tools_StaticDecal_Buffer
class Tools_StaticDecal_Buffer
{
public:

	Tools_StaticDecal_Buffer()
	{	
		m_iModuleIndex		= -2;
		m_uDecalMaterial	= 0;
		m_iNumDecals		= 0;
		m_ppxDecals			= 0;
		m_iNumPolys			= 0;
		m_bDirty			= false;

		m_piIndices			= NULL;
		m_iNumIndices		= 0;
		m_pxVerts			= NULL;
		m_iNumVerts			= 0;

		m_xAABB.Reset();
	}

	~Tools_StaticDecal_Buffer()
	{	
		if (m_ppxDecals)
		{			
			for(int i=0; i<m_iNumDecals; i++)
			{
				delete m_ppxDecals[i];
			}

			delete [] m_ppxDecals;
			m_ppxDecals = NULL;
		}

		if (m_pxVerts)
		{
			delete [] m_pxVerts;
			m_pxVerts   = NULL;
			m_iNumVerts = 0;
		}

		if (m_piIndices)
		{
			delete [] m_piIndices;
			m_piIndices   = NULL;
			m_iNumIndices = 0;
		}
	}

	int							m_iModuleIndex;
	uint32						m_uDecalMaterial;
	int							m_iNumDecals;
	int							m_iNumPolys;
	Tools_StaticDecal**			m_ppxDecals;
	bool						m_bDirty;

	// Vertex/Index buffers
	int*						m_piIndices;
	int							m_iNumIndices;
	Tools_StaticDecal_Vertex*	m_pxVerts;
	int							m_iNumVerts;	

	Asura_Bounding_Box			m_xAABB;
};


class Tools_StaticDecal_System
{

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

	static void						  UpdateDecal(Tools_StaticDecal_Object *pxToolsDecal);
	static void						  RemoveDecal(Tools_StaticDecal_Object *pxToolsDecal);
	static void						  SetSelectedDecal(Tools_StaticDecal_Object *pxToolsDecal);

	static void						  CreateToolsObjects(void);
	static void						  UpdateBuffers(bool bForceAll=false, uint32 uForceSpecificMaterial = 0, bool bOnExport=false);

	static int						  GetNumDecalBuffers(void);
	static int						  GetNumDecals(void);
	static int						  GetNumDecalPolys(void);

	static Tools_StaticDecal_Buffer*  GetDecalBufferByIndex(int i) {return s_ppxDecalBuffers[i];}

	// This is called from Asura_Decal_System as decals are added
	static void						  AddStrip(const Asura_Decal_Vertex* pxStrip,
												u_int uNumVertices,
												const Asura_RGBA& xDiffuseRGBA,
												const Asura_Decal_Template* pxDecalTemplate,
												bool CalculateStatiSH);


	static void						  RenderWireframe(void);

	static void						  AllocateDecalBuffers(int iNumDecalBuffers);

	static void						  OptimizeBuffer(int iBuffer);
private:
	static void						  UpdateVertices(Tools_StaticDecal_Buffer *pxBuffer);

	static Tools_StaticDecal		 *AddDecal(int iModule, uint32 uDecalSetHash);
	static Tools_StaticDecal_Buffer	 *GetDecalBuffer(int iModule, uint32 uDecalSetHash);
	static Tools_StaticDecal_Buffer	 *GetDecalBuffer(Tools_StaticDecal *pxDecal);
	static void						  RemoveDecalBuffer(Tools_StaticDecal_Buffer *pxBuffer);

	static void						  ClearWorkspaceVerts();


	static int						  s_iNumDecalBuffers;
	static Tools_StaticDecal_Buffer **s_ppxDecalBuffers;

	static int						  s_iWorkspaceNumVerts;
	static int						  s_iWorkspaceNumIndices;
	static int						  s_iWorkspaceMaxVerts;
	static int						  s_iWorkspaceMaxIndices;
	static int*						  s_piWorkspaceIndices;
	static Tools_StaticDecal_Vertex*  s_pxWorkspaceVerts;
	static uint32					  s_uCurrentAlpha;

	static Tools_StaticDecal*		  s_pxSelectedDecal;
	static Tools_StaticDecal_Buffer*  s_pxSelectedDecalBuffer;
	static int						  s_iSelectedDecalFirstIndex;
	static int						  s_iSelectedDecalNumPolys;


};



#endif //__TOOLS_STATICDECAL_SYSTEM_H__