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