1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail    : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 
24 #include "applet-struct.h"
25 #include "applet-rain.h"
26 
27 
28 #define cd_icon_effect_load_rain_texture(...) CD_APPLET_LOAD_LOCAL_TEXTURE ("rain.png")
29 
30 #define cd_icon_effect_update_rain_system cairo_dock_update_default_particle_system
31 
32 
init(Icon * pIcon,CairoDock * pDock,double dt,CDIconEffectData * pData)33 static gboolean init (Icon *pIcon, CairoDock *pDock, double dt, CDIconEffectData *pData)
34 {
35 	if (pData->pRainSystem != NULL)
36 		return TRUE;
37 
38 	if (myData.iRainTexture == 0)
39 		myData.iRainTexture = cd_icon_effect_load_rain_texture ();
40 
41 	double fMaxScale = 1. + myIconsParam.fAmplitude * pDock->fMagnitudeMax;
42 	CairoParticleSystem *pParticleSystem = cairo_dock_create_particle_system (myConfig.iNbRainParticles, myData.iRainTexture, pIcon->fWidth * pIcon->fScale, pIcon->fHeight * fMaxScale);
43 	g_return_val_if_fail (pParticleSystem != NULL, FALSE);
44 	pParticleSystem->dt = dt;
45 	if (myConfig.bRotateEffects && ! pDock->container.bDirectionUp && pDock->container.bIsHorizontal)
46 		pParticleSystem->bDirectionUp = FALSE;
47 
48 	double a = myConfig.fRainParticleSpeed;
49 	static double epsilon = 0.1;
50 	double r = myConfig.iRainParticleSize;
51 	double fBlend;
52 	double vmax = 1. / myConfig.iRainDuration;
53 	CairoParticle *p;
54 	int i;
55 	for (i = 0; i < myConfig.iNbRainParticles; i ++)
56 	{
57 		p = &(pParticleSystem->pParticles[i]);
58 
59 		p->x = 2 * g_random_double () - 1;
60 		p->y = 1.;
61 		p->z = 2 * g_random_double () - 1;
62 		p->fWidth = r*(p->z + 2)/3 * g_random_double ();
63 		p->fHeight = p->fWidth;
64 
65 		p->vx = 0.;
66 		p->vy = -a * vmax * ((p->z + 1)/2 * g_random_double () + epsilon) * dt;
67 		p->iInitialLife = MIN (-1./ p->vy, ceil (myConfig.iRainDuration / dt));
68 		p->iLife = p->iInitialLife;
69 
70 		{
71 			fBlend = g_random_double ();
72 			p->color[0] = fBlend * myConfig.pRainColor1[0] + (1 - fBlend) * myConfig.pRainColor2[0];
73 			p->color[1] = fBlend * myConfig.pRainColor1[1] + (1 - fBlend) * myConfig.pRainColor2[1];
74 			p->color[2] = fBlend * myConfig.pRainColor1[2] + (1 - fBlend) * myConfig.pRainColor2[2];
75 		}
76 		p->color[3] = 0.;
77 
78 		p->fOscillation = 0.;
79 		p->fOmega = 0.;  // tr/s
80 
81 		p->fSizeFactor = 1.;
82 		p->fResizeSpeed = 0.;  // zoom 1 a la fin.
83 	}
84 
85 	pData->pRainSystem = pParticleSystem;
86 	return TRUE;
87 }
88 
89 
_rewind_rain_particle(CairoParticle * p,double dt)90 void _rewind_rain_particle (CairoParticle *p, double dt)
91 {
92 	static double epsilon = 0.1;
93 	double a = myConfig.fRainParticleSpeed/2;
94 	double r = myConfig.iRainParticleSize;
95 	double vmax = 1. / myConfig.iRainDuration;
96 	p->x = 2 * g_random_double () - 1;
97 	p->y = 1.;
98 	p->z = 2 * g_random_double () - 1;
99 
100 	p->fWidth = r*(p->z + 2)/3 * g_random_double ();
101 	p->fHeight = p->fWidth;
102 
103 	p->vy = -a * vmax * ((p->z + 1)/2 * g_random_double () + epsilon) * dt;
104 
105 	p->iInitialLife = MIN (-1./ p->vy, ceil (myConfig.iRainDuration / dt));
106 	p->iLife = p->iInitialLife;
107 
108 	p->fSizeFactor = 1.;
109 }
110 
111 
update(Icon * pIcon,CairoDock * pDock,gboolean bRepeat,CDIconEffectData * pData)112 static gboolean update (Icon *pIcon, CairoDock *pDock, gboolean bRepeat, CDIconEffectData *pData)
113 {
114 	if (pData->pRainSystem == NULL)
115 		return FALSE;
116 
117 	gboolean bContinue = cairo_dock_update_default_particle_system (pData->pRainSystem,
118 		(bRepeat ? _rewind_rain_particle : NULL));
119 	pData->pRainSystem->fWidth = pIcon->fWidth * pIcon->fScale;
120 
121 	double fMaxScale = 1. + myIconsParam.fAmplitude * pDock->fMagnitudeMax;
122 	pData->fAreaWidth = pData->pRainSystem->fWidth + myConfig.iRainParticleSize * pDock->container.fRatio;  // demi-largeur des particules a droite et a gauche.
123 	pData->fAreaHeight = pIcon->fHeight * fMaxScale + myConfig.iRainParticleSize/2 * pDock->container.fRatio;
124 	pData->fBottomGap = 0.;
125 
126 	return bContinue;
127 }
128 
129 
render(CDIconEffectData * pData)130 static void render (CDIconEffectData *pData)
131 {
132 	if (pData->pRainSystem == NULL)
133 		return ;
134 
135 	cairo_dock_render_particles (pData->pRainSystem);
136 }
137 
138 
free_effect(CDIconEffectData * pData)139 static void free_effect (CDIconEffectData *pData)
140 {
141 	if (pData->pRainSystem != NULL)
142 	{
143 		cairo_dock_free_particle_system (pData->pRainSystem);
144 		pData->pRainSystem = NULL;
145 	}
146 }
147 
148 
cd_icon_effect_register_rain(CDIconEffect * pEffect)149 void cd_icon_effect_register_rain (CDIconEffect *pEffect)
150 {
151 	pEffect->init = init;
152 	pEffect->update = update;
153 	pEffect->render = render;
154 	pEffect->free = free_effect;
155 }
156