#include "../../Direct3D/Shader/RuShader_D3D_Editor_GraphVis.h"

#pragma managed(push, off)

// ************************************************************************************************************************************************************

CRuShader_Editor_GraphVis::CRuShader_Editor_GraphVis(CRuEngineD3D *engine)
:	CRuShader_Static_Base(engine)
{
	// Setup vertex elements
	CRuVertexElement vertexElements[] =
	{
		{ 0,	0,	ruELEMENTTYPE_FLOAT3,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_POSITION,	0 },
		{ 0,	12,	ruELEMENTTYPE_D3DCOLOR,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_COLOR,		0 },
		RUVERTEXDECL_END()
	};

	// Construct vertex declaration
	ruSAFE_RELEASE(m_vertexDecl);
	m_vertexDecl = m_engine->CreateVertexDeclaration(vertexElements);

	char *vsSource = "\
																													\n\
	vs_1_1															; Vertex shader version 1.1						\n\
																													\n\
	dcl_position0		v0											; Declare position								\n\
	dcl_color			v2											; Declare diffuse								\n\
																													\n\
	mov					r0,			c20.yyyy						; Move 1 into r0								\n\
	mov					r1,			c20.yyyy						; Move 1 into r1								\n\
																													\n\
	; Calculate index to instance data																				\n\
	mul					r2.x,		v2.w,		c31.x				; Scale diffuse alpha by 256 to get an integer	\n\
	mad					r2.x,		r2.x,		c31.y,		c31.z	; Calculate address index for row 0 in r2.x		\n\
	add					r2.y,		r2.x,		c20.y				; Calculate address index for row 1 in r2.y		\n\
	add					r2.z,		r2.y,		c20.y				; Calculate address index for row 2 in r2.z		\n\
																													\n\
	; Calculate position																							\n\
	mov					a0.x,		r2.x							; Copy row 0 index to index register			\n\
	mul					r0.xyz,		v0,			c[a0.x]				; Scale											\n\
																													\n\
	mov					a0.x,		r2.y							; Copy row 1 index to index register			\n\
	add					r0.xyz,		r0,			c[a0.x]				; Translate										\n\
																													\n\
	; Transform position into homogeneous space																		\n\
	m4x3				r1.xyz,		r0,			c3					; Transform vertex to view space				\n\
	m4x4				oPos,		r1,			c6					; Transform vertex to homogeneous space			\n\
																													\n\
	; Fog factor																									\n\
	mov					oFog,		c20.y							; Output fog factor (constant 1.0)				\n\
																													\n\
	; Diffuse color																									\n\
	mov					oD0,		v2.x							; Output global diffuse as diffuse color		\n\
	";

	char *psSource = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Arithmetic ops																								\n\
	mov					r0,			v0								; Copy diffuse color to output					\n\
	";

	// Assemble vertex shader
	m_vertexShader = RuD3DAssembleVertexShader(vsSource);

	// Assemble pixel shader
	m_pixelShader = RuD3DAssemblePixelShader(psSource);
}

CRuShader_Editor_GraphVis::~CRuShader_Editor_GraphVis()
{
}

void CRuShader_Editor_GraphVis::BeginPass(INT32 passNumber)
{
	// Call base BeginPass to perform any additional setup
	CRuShader_Static_Base::BeginPass(passNumber);

	if(passNumber == 0)
	{
		m_vertexDecl->Select();
		m_engine->SetVertexShader(m_vertexShader);
		m_engine->SetPixelShader(m_pixelShader);
		m_engine->SetVertexShaderConstants(0, m_shaderConstants, 256);
		m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);
	}
}

void CRuShader_Editor_GraphVis::SetParameters(const CRuParameterCache *paramCache)
{
	// Chain set parameters call to parent
	CRuShader_Static_Base::SetParameters(paramCache);

	DWORD param;

	if(paramCache->GetParameter(ruPARAMTYPE_GEOINSTANCE_S_COUNT, param))
	{
		m_numInstances = (UINT32) param;
	}

	if(paramCache->GetParameter(ruPARAMTYPE_GEOINSTANCE_S_DATA, param))
	{
		float *instanceData = reinterpret_cast<float *>(param);

		// Number of constants = instance dataset + 24 constants for the per-draw data
		INT32 numConstants = 4 + m_numInstances * 8;
		INT32 constantOffset = 31 * 4;

		memcpy(&m_shaderConstants[constantOffset], instanceData, sizeof(float) * numConstants);
	}
}

// ************************************************************************************************************************************************************

#pragma managed(pop)
