// ImageQuad.cpp: implementation of the CImageQuad class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ImageQuad.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CImageQuad::CImageQuad( PDIRECT3DDEVICE8 pDevice, DWORD x0, DWORD y0, DWORD x1, DWORD y1 )
{
	if( x0 == IQ_USEDEFAULT || y0 == IQ_USEDEFAULT || x1 == IQ_USEDEFAULT || y1 == IQ_USEDEFAULT )
	{
		D3DVIEWPORT8	d3dvport;

		if( FAILED( pDevice->GetViewport( &d3dvport ) ) )		
			throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create quad buffer" );		

		if( x0 == IQ_USEDEFAULT )
			x0 = d3dvport.X;

		if( y0 == IQ_USEDEFAULT )
			y0 = d3dvport.Y;

		if( x1 == IQ_USEDEFAULT )
			x1 = d3dvport.Width + d3dvport.X;

		if( y1 == IQ_USEDEFAULT )
			y1 = d3dvport.Height + d3dvport.Y;
	}

	if( FAILED( pDevice->CreateVertexBuffer( 6*sizeof(TLVERTEX), 0, FVF_TLVERTEX, D3DPOOL_DEFAULT, &m_pvbQuad ) ) )
		throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create quad buffer" );	

	PTLVERTEX			pVertices;

	m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 );

	*(pVertices++) = TLVERTEX( (FLOAT)x0, (FLOAT)y0, 0.0f, 0.5f, 0xffffff, 0.0f, 0.0f );
	*(pVertices++) = TLVERTEX( (FLOAT)x1, (FLOAT)y0, 0.0f, 0.5f, 0xffffff, 1.0f, 0.0f );
	*(pVertices++) = TLVERTEX( (FLOAT)x0, (FLOAT)y1, 0.0f, 0.5f, 0xffffff, 0.0f, 1.0f );
	
	*(pVertices++) = TLVERTEX( (FLOAT)x0, (FLOAT)y1, 0.0f, 0.5f, 0xffffff, 0.0f, 1.0f );
	*(pVertices++) = TLVERTEX( (FLOAT)x1, (FLOAT)y0, 0.0f, 0.5f, 0xffffff, 1.0f, 0.0f );	
	*(pVertices++) = TLVERTEX( (FLOAT)x1, (FLOAT)y1, 0.0f, 0.5f, 0xffffff, 1.0f, 1.0f );

	m_pvbQuad->Unlock();
}

CImageQuad::~CImageQuad()
{
	m_pvbQuad->Release();
}

BOOL CImageQuad::Resize( FLOAT x0, FLOAT y0, FLOAT x1, FLOAT y1 )
{
	PTLVERTEX			pVertices;

	if( FAILED( m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 ) ) )
		return FALSE;

	pVertices[0].m_vPos.x = x0; pVertices[0].m_vPos.y = y0;
	pVertices[1].m_vPos.x = x1; pVertices[1].m_vPos.y = y0;
	pVertices[2].m_vPos.x = x0; pVertices[2].m_vPos.y = y1;
	
	pVertices[3].m_vPos.x = x0; pVertices[3].m_vPos.y = y1;
	pVertices[4].m_vPos.x = x1; pVertices[4].m_vPos.y = y0;
	pVertices[5].m_vPos.x = x1; pVertices[5].m_vPos.y = y1;

	m_pvbQuad->Unlock();

	return TRUE;
}

BOOL CImageQuad::Resize( LPRECT pRect )
{
	PTLVERTEX			pVertices;	

	if( FAILED( m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 ) ) )
		return FALSE;

	pVertices[0].m_vPos.x = (FLOAT)pRect->left; pVertices[0].m_vPos.y = (FLOAT)pRect->top;
	pVertices[1].m_vPos.x = (FLOAT)pRect->right; pVertices[1].m_vPos.y = (FLOAT)pRect->top;
	pVertices[2].m_vPos.x = (FLOAT)pRect->left; pVertices[2].m_vPos.y = (FLOAT)pRect->bottom;
	
	pVertices[2].m_vPos.x = (FLOAT)pRect->left; pVertices[2].m_vPos.y = (FLOAT)pRect->bottom;
	pVertices[1].m_vPos.x = (FLOAT)pRect->right; pVertices[1].m_vPos.y = (FLOAT)pRect->top;
	pVertices[5].m_vPos.x = (FLOAT)pRect->right; pVertices[5].m_vPos.y = (FLOAT)pRect->bottom;

	m_pvbQuad->Unlock();

	return TRUE;
}

BOOL CImageQuad::SetAlpha( DWORD dwAlpha )
{
	dwAlpha = ( dwAlpha&0xff ) << 24;
	
	PTLVERTEX			pVertices;	

	if( FAILED( m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 ) ) )
		return FALSE;

	pVertices[0].m_dwColor = ( pVertices[0].m_dwColor&0xffffff ) | dwAlpha;
	pVertices[1].m_dwColor = ( pVertices[1].m_dwColor&0xffffff ) | dwAlpha;
	pVertices[2].m_dwColor = ( pVertices[2].m_dwColor&0xffffff ) | dwAlpha;
	pVertices[3].m_dwColor = ( pVertices[3].m_dwColor&0xffffff ) | dwAlpha;
	pVertices[4].m_dwColor = ( pVertices[4].m_dwColor&0xffffff ) | dwAlpha;
	pVertices[5].m_dwColor = ( pVertices[5].m_dwColor&0xffffff ) | dwAlpha;

	m_pvbQuad->Unlock();

	return TRUE;
}

BOOL CImageQuad::SetColor( DWORD dwColor )
{
	dwColor &= 0xffffff;

	PTLVERTEX			pVertices;	

	if( FAILED( m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 ) ) )
		return FALSE;

	pVertices[0].m_dwColor = ( pVertices[0].m_dwColor&0xff000000 ) | dwColor;
	pVertices[1].m_dwColor = ( pVertices[1].m_dwColor&0xff000000 ) | dwColor;
	pVertices[2].m_dwColor = ( pVertices[2].m_dwColor&0xff000000 ) | dwColor;
	pVertices[3].m_dwColor = ( pVertices[3].m_dwColor&0xff000000 ) | dwColor;
	pVertices[4].m_dwColor = ( pVertices[4].m_dwColor&0xff000000 ) | dwColor;
	pVertices[5].m_dwColor = ( pVertices[5].m_dwColor&0xff000000 ) | dwColor;

	m_pvbQuad->Unlock();

	return TRUE;
}

BOOL CImageQuad::SetARGB( DWORD dwARGB )
{
	PTLVERTEX			pVertices;	

	if( FAILED( m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 ) ) )
		return FALSE;

	pVertices[0].m_dwColor = dwARGB;
	pVertices[1].m_dwColor = dwARGB;
	pVertices[2].m_dwColor = dwARGB;
	pVertices[3].m_dwColor = dwARGB;
	pVertices[4].m_dwColor = dwARGB;
	pVertices[5].m_dwColor = dwARGB; 

	m_pvbQuad->Unlock();

	return TRUE;
}

BOOL CImageQuad::SetZ( FLOAT fZ )
{
	PTLVERTEX			pVertices;	
	FLOAT				rhw = 1.0f/fZ;

	if( FAILED(  m_pvbQuad->Lock( 0, 0, (LPBYTE*)&pVertices, 0 ) ) )
		return FALSE;

	pVertices[0].m_vPos.z = fZ; pVertices[0].m_fRhw = rhw;
	pVertices[1].m_vPos.z = fZ; pVertices[1].m_fRhw = rhw;
	pVertices[2].m_vPos.z = fZ; pVertices[2].m_fRhw = rhw;
	pVertices[3].m_vPos.z = fZ; pVertices[3].m_fRhw = rhw;
	pVertices[4].m_vPos.z = fZ; pVertices[4].m_fRhw = rhw;
	pVertices[5].m_vPos.z = fZ;	pVertices[5].m_fRhw = rhw; 

	m_pvbQuad->Unlock();

	return TRUE;
}

BOOL CImageQuad::Lock( LPBYTE* ppVertices )
{
	return SUCCEEDED( m_pvbQuad->Lock( 0, 0, ppVertices, 0 ) );
}

BOOL CImageQuad::Unlock()
{
	return SUCCEEDED( m_pvbQuad->Unlock() );
}

BOOL CImageQuad::Render( PDIRECT3DDEVICE8 pDevice )
{
	DWORD					dwCullMode;
	DWORD					dwZMode;

	pDevice->GetRenderState( D3DRS_CULLMODE, &dwCullMode );
	pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
	pDevice->GetRenderState( D3DRS_ZENABLE, &dwZMode );
	pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );

	if( FAILED( pDevice->SetStreamSource( 0, m_pvbQuad, sizeof(TLVERTEX) ) ) )
		return FALSE;

	if( FAILED( pDevice->SetVertexShader( FVF_TLVERTEX ) ) )
		return FALSE;

	if( FAILED( pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ) ) )
		return FALSE;

	pDevice->SetRenderState( D3DRS_CULLMODE, dwCullMode );
	pDevice->SetRenderState( D3DRS_ZENABLE, dwZMode );

	return TRUE;
}
