#ifndef __PARTICLE_SYSTEM_H__
#define __PARTICLE_SYSTEM_H__

#ifdef __HOME__
#include "d:\job\include\ParticleSystem.cpp"
#else
#include "include\ParticleSystem.cpp"
#endif

float					cEmitter::GetLifeTime( void ){
	return( fOP3 + fOP4 * frand() - fOP4 / 2 );
}

void					cEmitter::Create( DWORD EMMT , cVector3 op1 ){
	EMITTER_TYPE = EMMT;
	OP1 = op1;
}

cVector3					cEmitter::GetVelosity( void ){
	cVector3		RET( OP2 );
	RET.x += fOP2 * frand() - fOP2/2;
	RET.y += fOP2 * frand() - fOP2/2;
	RET.z += fOP2 * frand() - fOP2/2;

	return( RET );
}

cD3DParticleVertex			cEmitter::GetVertex( int i , cD3DParticleVertex &PV ){
	if( EMITTER_TYPE & EMM_SPRAY ){
		switch( i ){
			case( 0 ):
				PV.x = OP1.x-fOP1 / 2;
				PV.y = OP1.y-fOP1 / 2;
				PV.z = 0;

				return( PV );
			break;
			case( 1 ):
				PV.x = OP1.x-fOP1 / 2;
				PV.y = OP1.y+fOP1 / 2;
				PV.z = 0;

				return( PV );
			break;
			case( 2 ):
				PV.x = OP1.x+fOP1 / 2;
				PV.y = OP1.y+fOP1 / 2;
				PV.z = 0;

				return( PV );
			break;
			case( 3 ):
				PV.x = OP1.x-fOP1 / 2;
				PV.y = OP1.y-fOP1 / 2;
				PV.z = 0;

				return( PV );
			break;
			case( 4 ):
				PV.x = OP1.x+fOP1 / 2;
				PV.y = OP1.y+fOP1 / 2;
				PV.z = 0;

				return( PV );
			break;
			case( 5 ):
				PV.x = OP1.x+fOP1 / 2;
				PV.y = OP1.y-fOP1 / 2;
				PV.z = 0;

				return( PV );
			break;
		}
	}
}

void					cParticleSystem::CreateVisualPart( char *tex_name ){
	TextureCursor = TextureManager.GetTextureCursor( tex_name );
}

void					cParticleSystem::RunSystem( float dt ){
	if( VertexBuffer ){
		for( int i( 0 ) ; i < VertexBuffer->Vertexes.Cursor ; i++ ){
			if( _EFFECTS & EFF_GRAVITY ){
				VertexBuffer->Vertexes[ i ] += dt * ( *VelosityArray )[ i / 6 ] + cVector3( 0 , 0.5 * dt * dt * CNST_GRAVITY , 0 );
			}
			else{
				VertexBuffer->Vertexes[ i ] += dt * ( * VelosityArray )[ i / 6 ];
			}
		}
		for( int i( 0 ) ; i < VertexBuffer->Vertexes.Cursor / 6 ; i++ ){
			if( _EFFECTS & EFF_GRAVITY ){
				( *VelosityArray )[ i ] += cVector3( 0 , dt * CNST_GRAVITY , 0 );
			}
			if( _EFFECTS & EFF_AGING ){
				if( LifeTime ){
					( * LifeTime )[ i ] -= dt;
					if( ( * LifeTime )[ i ] <= 0 ){
						Emitter.GetVertex( 0 , ( * VertexBuffer )[ 6 * i + 0 ] );
						Emitter.GetVertex( 1 , ( * VertexBuffer )[ 6 * i + 1 ] );
						Emitter.GetVertex( 2 , ( * VertexBuffer )[ 6 * i + 2 ] );
						Emitter.GetVertex( 3 , ( * VertexBuffer )[ 6 * i + 3 ] );
						Emitter.GetVertex( 4 , ( * VertexBuffer )[ 6 * i + 4 ] );
						Emitter.GetVertex( 5 , ( * VertexBuffer )[ 6 * i + 5 ] );

						( * VelosityArray )[ i ] = Emitter.GetVelosity();

						( * LifeTime )[ i ] = Emitter.GetLifeTime();
					}
				}
				else{
					MessageBox( 0 , "Система частиц создана с \"нестареющими\" партиклами." , "Ошибка" , 0 );
					exit( 0 );
				}
			}
		}
	}
	else{
		MessageBox( 0 , "Система частиц не была инициализирована!" , "Ошибка" , 0 );
		exit( 0 );
	}
}

void					cParticleSystem::Release( void ){
	if( VelosityArray ){
		VelosityArray->Release();
		delete [] VelosityArray;
	}
	if( VertexBuffer ){
		VertexBuffer->Release();
		delete [] VertexBuffer;
	}
	if( LifeTime ){
		LifeTime->Release();
		delete [] LifeTime;
	}
}

void					cParticleSystem::Render( LPDIRECT3DDEVICE8 D3DDevice ){
	TextureManager[ TextureCursor ].SetTexture( D3DDevice , 0 );

	D3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE , true );
	D3DDevice->SetRenderState( D3DRS_SRCBLEND , D3DBLEND_SRCALPHA );
	D3DDevice->SetRenderState( D3DRS_DESTBLEND , D3DBLEND_INVSRCALPHA );
	D3DDevice->SetRenderState( D3DRS_ZENABLE , false );

	VertexBuffer->Render( D3DDevice , FVF_D3DPARTICLE_VERTEX );

	D3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE , false );
	D3DDevice->SetRenderState( D3DRS_ZENABLE , true );
	D3DDevice->SetRenderState( D3DRS_STENCILENABLE , false );

	TextureManager[ TextureCursor ].ResetTexture( D3DDevice , 0 );
}

void					cParticleSystem::CreateMathPart( float m , float d ){
	if( _EFFECTS && EFF_AGING ){
		if( VertexBuffer ){
			LifeTime = new cArray< float >;
			LifeTime->SetLength( VertexBuffer->Vertexes.Cursor / 6 );
			LifeTime->Cursor = VertexBuffer->Vertexes.Cursor / 6;
			for( int i( 0 ) ; i < VertexBuffer->Vertexes.Cursor / 6 ; i++ ){
				( * LifeTime )[ i ] = m + d * frand() - d / 2;
			}
			Emitter.fOP3 = m;
			Emitter.fOP4 = d;
		}
		else{
			MessageBox( 0 , "Система частиц не была первично инициализирована." , "Ошибка" , 0 );
			exit( 0 );
		}
	}
	else{
		MessageBox( 0 , "Система частиц объявлена как постоянная во времени." , "Ошибка" , 0 );
		exit( 0 );
	}
}

void					cParticleSystem::Create( cVector3 p , cVector3 v , float d , int c , float size , int _effects ){
	_EFFECTS = _effects;

	VelosityArray = new cArray< cVector3 >;
	VelosityArray->SetLength( c );

	VertexBuffer = new cD3DVertexBuffer< cD3DParticleVertex >;
	VertexBuffer->Vertexes.SetLength( c * 6 );
	VertexBuffer->Vertexes.Cursor = 0;

	for( int i( 0 ) ; i < c ; i++ ){
		//устанавливаем скорость
		cVector3			deviation( d * frand() - ( ( float )d / 2 ) , d * frand() - d / 2 , d * frand() - d / 2 );
		( *VelosityArray )[ i ] = v + deviation;

		//устанавливаем геометрию
		VertexBuffer->AddVertex( cD3DParticleVertex( - size / 2 , - size / 2 , 0 , 0 , 1 ) );
		( * VertexBuffer )[ VertexBuffer->Vertexes.Cursor - 1 ] += p;
		VertexBuffer->AddVertex( cD3DParticleVertex( - size / 2 ,   size / 2 , 0 , 0 , 0 ) );
		( * VertexBuffer )[ VertexBuffer->Vertexes.Cursor - 1 ] += p;
		VertexBuffer->AddVertex( cD3DParticleVertex(   size / 2 ,   size / 2 , 0 , 1 , 0 ) );
		( * VertexBuffer )[ VertexBuffer->Vertexes.Cursor - 1 ] += p;

		VertexBuffer->AddVertex( cD3DParticleVertex( - size / 2 , - size / 2 , 0 , 0 , 1 ) );
		( * VertexBuffer )[ VertexBuffer->Vertexes.Cursor - 1 ] += p;
		VertexBuffer->AddVertex( cD3DParticleVertex(   size / 2 ,   size / 2 , 0 , 1 , 0 ) );
		( * VertexBuffer )[ VertexBuffer->Vertexes.Cursor - 1 ] += p;
		VertexBuffer->AddVertex( cD3DParticleVertex(   size / 2 , - size / 2 , 0 , 1 , 1 ) );
		( * VertexBuffer )[ VertexBuffer->Vertexes.Cursor - 1 ] += p;
	}

	Emitter.OP1 = p;
	Emitter.fOP1 = size;

	Emitter.OP2 = v;
	Emitter.fOP2 = d;
}

#endif