//------------------------------------------------------------------------------------------------------------------------
//					+-----------------------------------------------------------+
//					|	Fonction qui gere le rendu dans les DIB etc.... (suite)	|
//					+-----------------------------------------------------------+
//------------------------------------------------------------------------------------------------------------------------


#include "stdAfx.h"
#include "..\resource.h"


//------------------------------------------------------------------------------------------------------------------------
//								+------------------------+
//								|Les variables Globales  |
//								+------------------------+
//------------------------------------------------------------------------------------------------------------------------


HWND DIBRender::m_hWnd	= NULL ;

BitmapSkin*	DIBRender::ListeBitmap = NULL	;
BoutonSkin*	DIBRender::ListeBouton = NULL	;
MultiAff*	DIBRender::ListeMultiAff = NULL	;	// liste de tout les boutons de la skin a checker

U32*	DIBRender::SkinGen = NULL		;	// Bitmap de la skin Generale en 32 bit
U32*	DIBRender::BackGen = NULL		;	// mémoire tampon
U8*		DIBRender::MaskGen = NULL		;	// Bitmap de Mask en 32 bit
U8*		DIBRender::ActionGen = NULL		;	// Bitmap de ou ya les zones d'action
U32*	DIBRender::ScreenGen = NULL		;	// Bitmap de Screen en 32 bit
int		DIBRender::xGen,DIBRender::yGen	;	// dimension des bitmap pour la skin generale
int		DIBRender::TailleScreen = 0		;
int		DIBRender::TailleXScreen	= 0	;
int		DIBRender::TailleYScreen	= 0	;


//------------------------------------------------------------------------------------------------------------------------
//								+-------------------------+
//								| Les Fonctions qui tuent |
//								+-------------------------+
//------------------------------------------------------------------------------------------------------------------------



//------------------------------------------------------------------------------------------------------------------------
//									Fonction pour DIBRender !
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::Initialise(HWND hwnd)
{
	CDC dc;

	m_hWnd = hwnd;

	//---------------------- Load le GTZ de l'interface

	U3D3DataManager = new DataManager	;

	HRSRC   tmpRSrc =  FindResource(  NULL, MAKEINTRESOURCE(IDR_FRONT), "GTZ" )	;
	HGLOBAL tmpMod = LoadResource( NULL, tmpRSrc )								;
	U8*		ptrRes = (U8*)LockResource( tmpMod )								;
	U32		sizeRes = SizeofResource( NULL, tmpRSrc )							;

	CMemFile file( ptrRes, sizeRes )	;
	CArchive ar(&file, CArchive::load )	;
	U3D3DataManager->LoadGTZ( ar )		;
	ar.Close()							;


	
	//---------------------- Load la GROSSE skin
	LoadBitmapJpg( "Datas\\Front\\skin.jpg", xGen, yGen, SkinGen )		;
	LoadBitmapRaw( "Datas\\Front\\mask.raw", xGen, yGen, MaskGen )		;
	LoadBitmapRaw( "Datas\\Front\\Action.raw", xGen, yGen, ActionGen )	;
	BackGen = new unsigned int[xGen*yGen]								;

	//--------------------- fond d'ecran( image du desktop en fait
	ScreenGen = NULL	;
	TailleScreen = 0	;
	TailleXScreen	= 0	;
	TailleYScreen	= 0	;


	//-------------------- Ini liste d'elements
	ListeBitmap = NULL		;
	ListeBouton = NULL		;
	ListeMultiAff = NULL	;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::Release()
{
	delete U3D3DataManager	;
	
	delete [] SkinGen	;
	delete [] MaskGen	;
	delete [] BackGen	;
	delete [] ScreenGen	;
	delete [] ActionGen	;

	//----------------------- Detruit toutes les images
	BitmapSkin *BMPtmp	;
	while( ListeBitmap )
	{
		BMPtmp = ListeBitmap				;
		ListeBitmap =  ListeBitmap->suiv	;
		delete BMPtmp						;
	}

	//--------------------- Detruit tout les boutons
	BoutonSkin *BTtmp	;
	while( ListeBouton )
	{
		BTtmp = ListeBouton				;
		ListeBouton = ListeBouton->suiv	;
		delete BTtmp					;
	}

	//-------------------- Detruit tout les boutons checkers
	MultiAff*	MAFFtmp	;
	while( ListeMultiAff )
	{
		MAFFtmp = ListeMultiAff				;
		ListeMultiAff = ListeMultiAff->suiv	;
		delete MAFFtmp						;
	}

}
//------------------------------------------------------------------------------------------------------------------------
// ajoute une bitmap dans la skin
void DIBRender::AddBitmap( int ID, LPCSTR nomOpen, BOOL msk )
{
	BitmapSkin	*tmp	;

	tmp = new BitmapSkin( ID, nomOpen, msk )	;
	tmp->suiv = ListeBitmap						;
	ListeBitmap = tmp							;
}
//------------------------------------------------------------------------------------------------------------------------
// retourn bitmap avec cette ID
BitmapSkin *DIBRender::GetBitmap( int ID )
{
	BitmapSkin *tmp ;

	tmp = ListeBitmap	;
	while( tmp )
	{
		if( tmp->Cmp( ID ) )
			return tmp	;
		tmp = tmp->suiv	;
	}

	return NULL	;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AddBouton( int ID, int xp, int yp, int colormask, BitmapSkin *b )
{
	BoutonSkin *tmp ;

	tmp = new BoutonSkin( ID, xp, yp, colormask, b )	;
	tmp->suiv = ListeBouton								;
	ListeBouton = tmp									;
}
//------------------------------------------------------------------------------------------------------------------------
BoutonSkin *DIBRender::GetBouton( int ID )
{
	BoutonSkin *tmp = ListeBouton	;

	while( tmp )
	{
		if( tmp->GetID() == ID )
			return tmp	;
		tmp = tmp->suiv	;
	}

	return NULL	;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AddMultiAff( int ID, int xp, int yp )
{
	MultiAff *tmp = ListeMultiAff	;

	tmp = new MultiAff( ID, xp, yp )	;
	tmp->suiv = ListeMultiAff			;
	ListeMultiAff = tmp					;
}
//------------------------------------------------------------------------------------------------------------------------
MultiAff *DIBRender::GetMultiAff( int ID )
{
	MultiAff *tmp = ListeMultiAff	;

	while( tmp )
	{
		if( tmp->GetID() == ID )
			return tmp	;
		tmp = tmp->suiv	;
	}

	return NULL	;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::LoadBitmapJpg( LPCSTR nom, int &x, int &y, U32 *&dest )
{
	TextureManager::SetRepertoire( "" )	;

	U32 a,b ;
	dest = TextureManager::NewJpg( nom, a, b )	;
	x = a	;
	y = b	;

	for( a=0; a<(U32)x*y; a++ )
	{
		U8* ptr = (U8*)&dest[a]	;
		U8 coulr = *ptr			;
		U8 coulb = *(ptr+2)		;
		*ptr = coulb				;
		*(ptr+2) = coulr			;
	}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
void DIBRender::LoadBitmapRaw( LPCSTR nom, int x, int y, U8 *&dest )
{
	TextureManager::SetRepertoire( "" )	;

	dest = TextureManager::NewRaw( nom, x, y )	;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
void DIBRender::GetDim(int &width, int &height)
{
	width = xGen	;
	height = yGen	;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AffiSkinGen( CDC *Cdest, HWND hwnd, int xpos, int ypos )
{
	int Temps = (int)clock()	;


	//------------------------------ affiche fond !!!!!
	AffSkinBmp()					;

	//------------------------------ Affiche tout les boutons
	BoutonSkin	*BTtmp = ListeBouton	;
	while( BTtmp )
	{
		BTtmp->Affiche()	;
		BTtmp = BTtmp->suiv	;
	}

	//----------------------------- Affiche les Multi Aff
	MultiAff *BTCtmp = ListeMultiAff	;
	while( BTCtmp )
	{
		BTCtmp->Affiche()			;
		BTCtmp = 	BTCtmp->suiv	;
	}

	FillBackWindow( xpos, ypos )	;	// fait alpha avec fond d'ecran

	BITMAPINFO pbitmap;
	pbitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	pbitmap.bmiHeader.biWidth = xGen;
	pbitmap.bmiHeader.biHeight = -yGen;
	pbitmap.bmiHeader.biPlanes = 1;
	pbitmap.bmiHeader.biBitCount = 32;
	pbitmap.bmiHeader.biCompression = BI_RGB;
	pbitmap.bmiHeader.biSizeImage = 0;
	pbitmap.bmiHeader.biXPelsPerMeter = 0;
	pbitmap.bmiHeader.biYPelsPerMeter = 0;
	pbitmap.bmiHeader.biClrUsed = 0;
	pbitmap.bmiHeader.biClrImportant = 0;
	SetDIBitsToDevice (
							Cdest->m_hDC,	// handle of device context
							0,				// x-coordinate of upper-left corner of dest. rect.
							0,				// y-coordinate of upper-left corner of dest. rect.
							xGen,			// source rectangle width
							yGen,			// source rectangle height
							0,				// x-coordinate of lower-left corner of source rect.
							0,				// y-coordinate of lower-left corner of source rect.
							0,				// first scan line in array
							yGen,			// number of scan lines
							BackGen,		// address of array with DIB bits
							&pbitmap,		// address of structure with bitmap info.
							DIB_RGB_COLORS	// RGB or palette indices
						);

}
//------------------------------------------------------------------------------------------------------------------------
int DIBRender::OuEstTu( int x, int y)
{
	if( x > xGen ) return DEHORS_SKIN	;
	if( y > yGen ) return DEHORS_SKIN	;

	int pos = ActionGen[ y*xGen + x ]		;

	//--------------------- Test pour voar si c'est en dehors
	if( pos== TRANSP_COLOR_SKIN )	return DEHORS_SKIN	;

	//--------------------- Test sur tout les boutons normaux
	BoutonSkin	*BTtmp = ListeBouton	;
	while( BTtmp )
	{
		if( BTtmp->IsInside( pos )	)
			return BTtmp->GetID()	;
		BTtmp = BTtmp->suiv	;
	}

	return DANS_SKIN	;
}

//------------------------------------------------------------------------------------------------------------------------
// renvoie couleur dans la mask a position x, y
int	DIBRender::GetColorMask( int x, int y )	
{
	return ActionGen[ y*xGen + x ]	;
}
//------------------------------------------------------------------------------------------------------------------------
HRGN DIBRender::MakeRegion()
{
	HRGN rgnc, rgnl;
	int x, y, l = 0;
	BOOL ff = TRUE, inf = FALSE;

	unsigned int dep=0;
	for(y = 0; y <yGen; y++) 
	{
		for(x = 0; x <xGen; x++,dep++) 
		{
			if( ActionGen[dep] ==TRANSP_COLOR_SKIN ) 
			{
				if( inf )
				{
					inf = FALSE;
					rgnl = CreateRectRgn(l, y, x, y+1);
					if( ff ) 
					{
						rgnc = rgnl;
						ff = FALSE;
					} 
					else
					{
						CombineRgn(rgnc, rgnc, rgnl, RGN_OR);
					}
				}
			} 
			else
			{
				if( !inf ) 
				{
					inf = TRUE;
					l = x;
				}
			}
		}
	}

	return rgnc;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AffSkinBmp()
{
/*	unsigned int*	ptrdst = BackGen;
	unsigned int*	ptrsrc = SkinGen;
	unsigned char*	ptrmsk = (unsigned char*)MaskGen;
	for(int a=0; a<yGen; a++)
		for(int b=0; b<xGen; b++, ptrdst++, ptrsrc++, ptrmsk++)
		{
			unsigned char alpha1 = *ptrmsk		;
			if( alpha1 )
			{
				unsigned char alpha2 = 255-alpha1	;

				unsigned int r = ( alpha1*(((*ptrsrc)&0x00ff0000)>>16) + alpha2*(((*ptrdst)&0x00ff0000)>>16) ) >> 8	;
				unsigned int v = ( alpha1*(((*ptrsrc)&0x0000ff00)>>8) + alpha2*(((*ptrdst)&0x0000ff00)>>8)) >> 8		;
				unsigned int b = ( alpha1*((*ptrsrc)&0x000000ff) + alpha2*((*ptrdst)&0x000000ff) ) >> 8				;

				*ptrdst = (r<<16) | (v<<8) | b	;
			}
		}*/

	memcpy( BackGen, SkinGen, xGen*yGen*4 )	;
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AffInSkin( unsigned int *src, int x, int y, int width, int height )
{
	int dep=0;
	int depS=y*xGen;
	for(int a=0; a<height; a++,depS+=xGen)
		for(int b=0; b<width; b++,dep++)
			BackGen[ depS+b+x ] = src[dep];
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AffInSkinMsk( unsigned int *src, int x, int y, int width, int height )
{
	int dep=0;
	int depS=y*xGen;
	for(int a=0; a<height; a++,depS+=xGen)
		for(int b=0; b<width; b++,dep++)
			if( src[dep] != TRANSP_COLOR_SKIN )
				BackGen[ depS+b+x ] = src[dep];
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::AffInSkinAdd( unsigned int *src, int x, int y, int width, int height )
{
/*	int dep=0;
	int depS=y*xGen;
	for(int a=0; a<height; a++,depS+=xGen)
		for(int b=0; b<width; b++,dep++)
			AddPix( &BackGen[ depS+b+x ], src[dep] );*/
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::ClearAllState()
{
	//------------------------- Clear tout les boutons normaux
	BoutonSkin *BTtmp = ListeBouton	;
	while( BTtmp )
	{
		BTtmp->SetHighLight( FALSE )	;
		BTtmp = BTtmp->suiv			;
	}

	MultiAff* tmpmulti = ListeMultiAff	;
	while( tmpmulti )
	{
		tmpmulti->SetActuaBitmap( -1 )	;
		tmpmulti = tmpmulti->suiv		;
	}
}

//------------------------------------------------------------------------------------------------------------------------
void DIBRender::TestScreenOrAllocate( int x, int y )
{
	if( TailleScreen != x*y )
	{
		if( ScreenGen )
			delete [] ScreenGen	;

		ScreenGen = new unsigned int[x*y]	;
		TailleScreen = x*y					;
		TailleXScreen	= x					;
		TailleYScreen	= y					;
	}
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::GetBackGround()
{
	BITMAPINFO *pbitmapinfo=NULL;
	/////////////////////////////////////////
	HDC dcsrc;
	HDC dcdest;
	HBITMAP bitmap;
	/////////////////////////////////////////
	RECT rect;
//	int dx_src, dy_src;

	/////////////////////////////////////////
	HWND hwnd = GetDesktopWindow()		;
	GetWindowRect ( hwnd, &rect )		;
	int dx_src = rect.right-rect.left	;
	int dy_src = rect.bottom-rect.top	;

	dcsrc = GetDC ( hwnd );

	bitmap = CreateCompatibleBitmap ( dcsrc, dx_src, dy_src )	;
	dcdest = CreateCompatibleDC ( dcsrc )					;
	/////////////////////////////////////////

	if((pbitmapinfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER)))!=NULL)
	{
		pbitmapinfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER); // in m_bitcount;
		pbitmapinfo->bmiHeader.biWidth         = dx_src;
		pbitmapinfo->bmiHeader.biHeight        = -dy_src;
		pbitmapinfo->bmiHeader.biPlanes        = 1;
		pbitmapinfo->bmiHeader.biBitCount      = 32;
		pbitmapinfo->bmiHeader.biCompression   = BI_RGB;
		pbitmapinfo->bmiHeader.biSizeImage     = 0;
		pbitmapinfo->bmiHeader.biXPelsPerMeter = 0;
		pbitmapinfo->bmiHeader.biYPelsPerMeter = 0;
		pbitmapinfo->bmiHeader.biClrUsed       = 0;
		pbitmapinfo->bmiHeader.biClrImportant  = 0;

		SelectObject(dcdest, bitmap);
		// Dessine le DC dans le DIB
		/*
		BitBlt( 
				dcdest,	// handle to destination device context
				0,		// int x
				0,		// int y
				dx,	// int nWidth
				dy,	// int nHeight
				dcsrc,	// handle to source device context
				0,		// int xSrc
				0,		// int ySrc
				SRCCOPY
			);
		*/

		TestScreenOrAllocate( dx_src, dy_src )	;

		StretchBlt(
					dcdest,	// handle of destination device context 
					0,		// x-coordinate of upper-left corner of dest. rect. 
					0,		// y-coordinate of upper-left corner of dest. rect. 
					dx_src,	//dx,	// width of destination rectangle 
					dy_src,	//dy,	// height of destination rectangle 
					dcsrc,	// handle of source device context 
					0,		// x-coordinate of upper-left corner of source rectangle 
					0,		// y-coordinate of upper-left corner of source rectangle 
					dx_src,	// width of source rectangle 
					dy_src,	// height of source rectangle 
					SRCCOPY	// raster operation code 
				); 
 
		
		GetDIBits(
					dcdest,			// handle of device context 
					bitmap,			// handle of bitmap 
					0,				// first scan line to set in destination bitmap  
					dy_src,			// number of scan lines to copy 
					ScreenGen,		// address of array for bitmap bits 
					pbitmapinfo,		// address of structure with bitmap data 
					DIB_RGB_COLORS	// RGB or palette index 
				);

		free(pbitmapinfo);
	}

	DeleteDC ( dcdest );
	DeleteObject ( bitmap );
	ReleaseDC ( hwnd, dcsrc );
}
//------------------------------------------------------------------------------------------------------------------------
void DIBRender::FillBackWindow( int xpos, int ypos )
{
	int xstart = xpos		;
	int ystart = ypos		;
	int xend = xpos + xGen	;
	int yend = ypos + yGen	;
	int depx = 0			;
	int depy = 0			;


	//----------- fait le clipping
	if( xstart <0 )				
	{
		depx = -xstart	;
		xstart = 0		;
	}
	if( xstart >= TailleXScreen )	return	;

	if( ystart <0 )	
	{
		depy = -ystart	;
		ystart = 0		;
	}
	if( ystart >= TailleYScreen )	return	;

	if( xend <= 0 )			return						;
	if( xend > TailleXScreen ) xend = TailleXScreen	;

	if( yend <= 0 )			return						;
	if( yend > TailleYScreen ) yend = TailleYScreen	;

	unsigned int* ptrSrc = &ScreenGen[ ystart*TailleXScreen + xstart ]	;
	unsigned int* ptrDest = &BackGen[ depx + depy*xGen]					;
	U8*			  ptrMask = &MaskGen[ depx + depy*xGen]					;

	//----------- remplit BackGen comme il fo
	int delta = xend - xstart	;
	for( int a=0; a<yend-ystart; a++ )
	{
///		memcpy( ptrDest, ptrSrc, delta*4 )	;
		unsigned int*	ptrdst = ptrDest	;
		unsigned int*	ptrsrc = ptrSrc		;
		U8*	ptrmsk = ptrMask				;
		for(int i=0; i<delta; i++, ptrdst++, ptrsrc++, ptrmsk++)
		{
			unsigned char alpha1 = *ptrmsk		;
			if( alpha1 )
			{
				unsigned char alpha2 = 255-alpha1	;

				unsigned int r = ( alpha2*(((*ptrsrc)&0x00ff0000)>>16) + alpha1*(((*ptrdst)&0x00ff0000)>>16) ) >> 8	;
				unsigned int v = ( alpha2*(((*ptrsrc)&0x0000ff00)>>8) + alpha1*(((*ptrdst)&0x0000ff00)>>8)) >> 8	;
				unsigned int b = ( alpha2*((*ptrsrc)&0x000000ff) + alpha1*((*ptrdst)&0x000000ff) ) >> 8				;

				*ptrdst = (r<<16) | (v<<8) | b	;
			}
			else
			{
				*ptrdst = *ptrsrc	;
			}
		}
		ptrSrc += TailleXScreen	;
		ptrDest += xGen			;
		ptrMask	+= xGen			;
	}
}
//------------------------------------------------------------------------------------------------------------------------
