CairoParticleSystem *cd_icon_effect_init_stars (Icon *pIcon, CairoDock *pDock, double dt)
{
	if (myData.iStarTexture == 0)
		myData.iStarTexture = cd_icon_effect_load_star_texture ();
	double fMaxScale = (pDock->bAtBottom ? 1. : cairo_dock_get_max_scale (CAIRO_CONTAINER (pDock)));
	CairoParticleSystem *pStarParticleSystem = cairo_dock_create_particle_system (myConfig.iNbStarParticles, myData.iStarTexture, pIcon->fWidth * pIcon->fScale, pIcon->fHeight * fMaxScale);
	g_return_val_if_fail (pStarParticleSystem != NULL, NULL);
	pStarParticleSystem->dt = dt;
	pStarParticleSystem->bAddLuminance = TRUE;
	
	static double a = .4;
	static double epsilon = 0.1;
	double r = myConfig.iStarParticleSize;
	double fBlend;
	CairoParticle *p;
	int i;
	for (i = 0; i < myConfig.iNbStarParticles; i ++)
	{
		p = &pStarParticleSystem->pParticles[i];
		
		p->x = 2 * g_random_double () - 1;
		p->y = g_random_double ();
		p->z = 2 * g_random_double () - 1;
		p->fWidth = r*(p->z + 1)/2 * g_random_double ();
		p->fHeight = p->fWidth;
		
		p->vx = 0.;
		p->vy = 0.;
		
		p->iInitialLife = myConfig.iStarDuration / dt;
		p->iLife = p->iInitialLife * (g_random_double () + a) / (1 + a);
		
		if (myConfig.bMysticalStars)
		{
			p->color[0] = g_random_double ();
			p->color[1] = g_random_double ();
			p->color[2] = g_random_double ();
		}
		else
		{
			fBlend = g_random_double ();
			p->color[0] = fBlend * myConfig.pStarColor1[0] + (1 - fBlend) * myConfig.pStarColor2[0];
			p->color[1] = fBlend * myConfig.pStarColor1[1] + (1 - fBlend) * myConfig.pStarColor2[1];
			p->color[2] = fBlend * myConfig.pStarColor1[2] + (1 - fBlend) * myConfig.pStarColor2[2];
		}
		p->color[3] = 0.;  // on va gerer nous-mêmes la transparence.
		
		p->fOscillation = 0.;
		p->fOmega = 0.;
		
		p->fSizeFactor = 1.;
		p->fResizeSpeed = - 1. / myConfig.iStarDuration * dt;  // zoom 0 a la fin.
	}
	
	return pStarParticleSystem;
}
static gboolean init (Icon *pIcon, CairoDock *pDock, double dt, CDIconEffectData *pData)
{
	if (pData->pRainSystem != NULL)
		return TRUE;
	
	if (myData.iRainTexture == 0)
		myData.iRainTexture = cd_icon_effect_load_rain_texture ();
	
	double fMaxScale = 1. + myIconsParam.fAmplitude * pDock->fMagnitudeMax;
	CairoParticleSystem *pParticleSystem = cairo_dock_create_particle_system (myConfig.iNbRainParticles, myData.iRainTexture, pIcon->fWidth * pIcon->fScale, pIcon->fHeight * fMaxScale);
	g_return_val_if_fail (pParticleSystem != NULL, FALSE);
	pParticleSystem->dt = dt;
	if (myConfig.bRotateEffects && ! pDock->container.bDirectionUp && pDock->container.bIsHorizontal)
		pParticleSystem->bDirectionUp = FALSE;
	
	double a = myConfig.fRainParticleSpeed;
	static double epsilon = 0.1;
	double r = myConfig.iRainParticleSize;
	double fBlend;
	double vmax = 1. / myConfig.iRainDuration;
	CairoParticle *p;
	int i;
	for (i = 0; i < myConfig.iNbRainParticles; i ++)
	{
		p = &(pParticleSystem->pParticles[i]);
		
		p->x = 2 * g_random_double () - 1;
		p->y = 1.;
		p->z = 2 * g_random_double () - 1;
		p->fWidth = r*(p->z + 2)/3 * g_random_double ();
		p->fHeight = p->fWidth;
		
		p->vx = 0.;
		p->vy = -a * vmax * ((p->z + 1)/2 * g_random_double () + epsilon) * dt;
		p->iInitialLife = MIN (-1./ p->vy, ceil (myConfig.iRainDuration / dt));
		p->iLife = p->iInitialLife;
		
		{
			fBlend = g_random_double ();
			p->color[0] = fBlend * myConfig.pRainColor1[0] + (1 - fBlend) * myConfig.pRainColor2[0];
			p->color[1] = fBlend * myConfig.pRainColor1[1] + (1 - fBlend) * myConfig.pRainColor2[1];
			p->color[2] = fBlend * myConfig.pRainColor1[2] + (1 - fBlend) * myConfig.pRainColor2[2];
		}
		p->color[3] = 0.;
		
		p->fOscillation = 0.;
		p->fOmega = 0.;  // tr/s
		
		p->fSizeFactor = 1.;
		p->fResizeSpeed = 0.;  // zoom 1 a la fin.
	}
	
	pData->pRainSystem = pParticleSystem;
	return TRUE;
}
static gboolean init (Icon *pIcon, CairoDock *pDock, double dt, CDIconEffectData *pData)
{
	if (pData->pStormSystem != NULL)
		return TRUE;
	
	if (myData.iFireTexture == 0)
		myData.iFireTexture = cd_icon_effect_load_storm_texture ();
	
	double fMaxScale = 1. + myIconsParam.fAmplitude * pDock->fMagnitudeMax;
	CairoParticleSystem *pParticleSystem = cairo_dock_create_particle_system (myConfig.iNbStormParticles, myData.iFireTexture, pIcon->fWidth * pIcon->fScale, pIcon->fHeight * fMaxScale);
	g_return_val_if_fail (pParticleSystem != NULL, FALSE);
	pParticleSystem->dt = dt;
	if (myConfig.bRotateEffects && ! pDock->container.bDirectionUp && pDock->container.bIsHorizontal)
		pParticleSystem->bDirectionUp = FALSE;
	
	double r = myConfig.iStormParticleSize;
	double vmax = 1. / myConfig.iStormDuration * 2;
	double fBlend;
	CairoParticle *p;
	int i;
	for (i = 0; i < myConfig.iNbStormParticles; i ++)
	{
		p = &pParticleSystem->pParticles[i];
		
		p->x = 0.;  // on le calculera a la main.
		p->y = -1. * i /myConfig.iNbStormParticles + .01 * (2 * g_random_double () - 1);
		p->z = 1.;  // idem.
		p->fWidth = r * (1 + ar * (2 * g_random_double () - 1));
		p->fHeight = p->fWidth;
		
		p->vx = ad * (2 * g_random_double () - 1);  // utilisation detournee : dispersion.
		p->vy = vmax * (1 - ad * g_random_double ()) * dt * 2;
		
		p->iInitialLife = MIN ((1 - p->y) / p->vy, ceil (myConfig.iStormDuration/2 / dt));
		p->iLife = p->iInitialLife;
		
		fBlend = g_random_double ();
		p->color[0] = fBlend * myConfig.pStormColor1[0] + (1 - fBlend) * myConfig.pStormColor2[0];
		p->color[1] = fBlend * myConfig.pStormColor1[1] + (1 - fBlend) * myConfig.pStormColor2[1];
		p->color[2] = fBlend * myConfig.pStormColor1[2] + (1 - fBlend) * myConfig.pStormColor2[2];
		p->color[3] = (p->y < 0 ? 0. : at);
		
		p->fOscillation = 0.;
		p->fOmega = 0.;
		
		p->fSizeFactor = 1.;
		p->fResizeSpeed = 0.;  // zoom constant.
	}
	
	pData->pStormSystem = pParticleSystem;
	return TRUE;
}