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-notifications.h"
25 #include "star-tex.h"
26
27 static double fRadius = .33;
28 static double a = .2;
29
30
cd_show_mouse_render(gpointer pUserData,GldiContainer * pContainer,cairo_t * pCairoContext)31 gboolean cd_show_mouse_render (gpointer pUserData, GldiContainer *pContainer, cairo_t *pCairoContext)
32 {
33 CDShowMouseData *pData = CD_APPLET_GET_MY_CONTAINER_DATA (pContainer);
34 if (pData == NULL)
35 return GLDI_NOTIFICATION_LET_PASS;
36
37 glPushMatrix();
38
39 if (CAIRO_DOCK_IS_DESKLET (pContainer))
40 {
41 CairoDesklet *pDesklet = CAIRO_DESKLET (pContainer);
42 glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, -pDesklet->container.iHeight*(sqrt(3)/2));
43 }
44 if (pContainer->bIsHorizontal)
45 glTranslatef (pContainer->iMouseX, pContainer->iHeight - pContainer->iMouseY, 0.);
46 else
47 glTranslatef (pContainer->iMouseY, pContainer->iWidth - pContainer->iMouseX, 0.);
48 cairo_dock_render_particles (pData->pSystem);
49
50 glPopMatrix();
51
52 return GLDI_NOTIFICATION_LET_PASS;
53 }
54
55
56 #define _compute_area(area, pContainer, pData) do {\
57 if (pContainer->bIsHorizontal) {\
58 area.x = pContainer->iMouseX - pData->pSystem->fWidth/2;\
59 area.y = MAX (0, pContainer->iMouseY - pData->pSystem->fHeight);\
60 area.width = pData->pSystem->fWidth;\
61 area.height = pData->pSystem->fHeight*2; }\
62 else {\
63 area.y = pContainer->iMouseX - pData->pSystem->fWidth/2;\
64 area.x = MAX (0, pContainer->iMouseY - pData->pSystem->fHeight);\
65 area.height = pData->pSystem->fWidth;\
66 area.width = pData->pSystem->fHeight*2; } } while (0)
cd_show_mouse_update_container(gpointer pUserData,GldiContainer * pContainer,gboolean * bContinueAnimation)67 gboolean cd_show_mouse_update_container (gpointer pUserData, GldiContainer *pContainer, gboolean *bContinueAnimation)
68 {
69 CDShowMouseData *pData = CD_APPLET_GET_MY_CONTAINER_DATA (pContainer);
70 if (pData == NULL)
71 return GLDI_NOTIFICATION_LET_PASS;
72
73 GdkRectangle area;
74 if (! pContainer->bInside)
75 {
76 pData->fAlpha -= .05;
77 if (pData->fAlpha <= 0)
78 {
79 _compute_area (area, pContainer, pData);
80 cairo_dock_redraw_container_area (pContainer, &area);
81
82 cairo_dock_free_particle_system (pData->pSystem);
83 g_free (pData);
84 CD_APPLET_SET_MY_CONTAINER_DATA (pContainer, NULL);
85
86 return GLDI_NOTIFICATION_LET_PASS;
87 }
88 }
89 else if (pData->fAlpha != 1)
90 pData->fAlpha = MIN (1., pData->fAlpha + .05);
91
92 double dt = cairo_dock_get_animation_delta_t (pContainer) * 1e-3;
93 pData->fRotationAngle += 2*G_PI * myConfig.fRotationSpeed * dt;
94
95 cd_show_mouse_update_sources (pData);
96 pData->pSystem->fWidth = 2 * MIN (96, pContainer->iHeight);
97 pData->pSystem->fHeight = MIN (96, pContainer->iHeight);
98 cd_show_mouse_update_particle_system (pData->pSystem, pData);
99
100 _compute_area (area, pContainer, pData);
101 cairo_dock_redraw_container_area (pContainer, &area);
102
103 *bContinueAnimation = TRUE;
104 return GLDI_NOTIFICATION_LET_PASS;
105 }
106
107
cd_show_mouse_enter_container(gpointer pUserData,GldiContainer * pContainer,gboolean * bStartAnimation)108 gboolean cd_show_mouse_enter_container (gpointer pUserData, GldiContainer *pContainer, gboolean *bStartAnimation)
109 {
110 if (! CAIRO_DOCK_CONTAINER_IS_OPENGL (pContainer))
111 return GLDI_NOTIFICATION_LET_PASS;
112
113 CDShowMouseData *pData = CD_APPLET_GET_MY_CONTAINER_DATA (pContainer);
114 if (pData == NULL)
115 {
116 pData = g_new0 (CDShowMouseData, 1);
117 pData->fAlpha = 1.;
118
119 double dt = cairo_dock_get_animation_delta_t (pContainer);
120 pData->pSourceCoords = cd_show_mouse_init_sources ();
121 pData->pSystem = cd_show_mouse_init_system (pContainer, dt, pData->pSourceCoords);
122
123 CD_APPLET_SET_MY_CONTAINER_DATA (pContainer, pData);
124 }
125
126
127 *bStartAnimation = TRUE;
128 return GLDI_NOTIFICATION_LET_PASS;
129 }
130
131
132
cd_show_mouse_init_sources(void)133 gdouble *cd_show_mouse_init_sources (void)
134 {
135 double *pSourceCoords = g_new (double, myConfig.iNbSources * 2);
136 double fTheta;
137 int i;
138 for (i = 0; i < myConfig.iNbSources; i ++)
139 {
140 fTheta = 2*G_PI * i / myConfig.iNbSources;
141 pSourceCoords[2*i] = fRadius * cos (fTheta);
142 pSourceCoords[2*i+1] = fRadius * sin (fTheta);
143 }
144 return pSourceCoords;
145 }
146
cd_show_mouse_init_system(GldiContainer * pContainer,double dt,double * pSourceCoords)147 CairoParticleSystem *cd_show_mouse_init_system (GldiContainer *pContainer, double dt, double *pSourceCoords)
148 {
149 if (myData.iTexture == 0)
150 myData.iTexture = cairo_dock_create_texture_from_raw_data (starTex, 32, 32); /// 32 = sqrt (4096/4)
151 double fHeight = pContainer->iHeight; // iMaxDockHeight ?
152 CairoParticleSystem *pParticleSystem = cairo_dock_create_particle_system (myConfig.iNbParticles * myConfig.iNbSources, myData.iTexture, 2*fHeight, fHeight);
153 pParticleSystem->dt = dt;
154
155 int iNumSource;
156 double fBlend;
157 double r = myConfig.iParticleSize / (1 + a);
158 double sigma = myConfig.fScattering;
159 CairoParticle *p;
160 int i;
161 for (i = 0; i < pParticleSystem->iNbParticles; i ++)
162 {
163 p = &(pParticleSystem->pParticles[i]);
164
165 iNumSource = i / myConfig.iNbParticles;
166
167 p->x = pSourceCoords[2*iNumSource];
168 p->y = pSourceCoords[2*iNumSource+1];
169 p->z = 0;
170 p->fWidth = r * (a + g_random_double ());
171 p->fHeight = p->fWidth;
172
173 p->vx = sigma * (2 * g_random_double () - 1) * dt / myConfig.iParticleLifeTime;
174 p->vy = sigma * (2 * g_random_double () - 1) * dt / myConfig.iParticleLifeTime;
175 p->iInitialLife = ceil (myConfig.iParticleLifeTime / dt);
176 p->iLife = g_random_int_range (1, p->iInitialLife+1);
177
178 if (myConfig.bMysticalFire)
179 {
180 p->color[0] = g_random_double ();
181 p->color[1] = g_random_double ();
182 p->color[2] = g_random_double ();
183 }
184 else
185 {
186 fBlend = g_random_double ();
187 p->color[0] = fBlend * myConfig.pColor1[0] + (1 - fBlend) * myConfig.pColor2[0];
188 p->color[1] = fBlend * myConfig.pColor1[1] + (1 - fBlend) * myConfig.pColor2[1];
189 p->color[2] = fBlend * myConfig.pColor1[2] + (1 - fBlend) * myConfig.pColor2[2];
190 }
191 p->color[3] = 1.;
192
193 p->fSizeFactor = 1.;
194 p->fResizeSpeed = .5 / myConfig.iParticleLifeTime * dt; // zoom 1.5 a la fin.
195 }
196
197 return pParticleSystem;
198
199 }
200
cd_show_mouse_update_sources(CDShowMouseData * pData)201 void cd_show_mouse_update_sources (CDShowMouseData *pData)
202 {
203 double *pSourceCoords = pData->pSourceCoords;
204 double fTheta;
205 int i;
206 for (i = 0; i < myConfig.iNbSources; i ++)
207 {
208 fTheta = 2*G_PI * i / myConfig.iNbSources + pData->fRotationAngle;
209 pSourceCoords[2*i] = fRadius * cos (fTheta);
210 pSourceCoords[2*i+1] = fRadius * sin (fTheta);
211 }
212 }
213
214
cd_show_mouse_update_particle_system(CairoParticleSystem * pParticleSystem,CDShowMouseData * pData)215 void cd_show_mouse_update_particle_system (CairoParticleSystem *pParticleSystem, CDShowMouseData *pData)
216 {
217 double *pSourceCoords = pData->pSourceCoords;
218 CairoParticle *p;
219 double dt = pParticleSystem->dt;
220 int i;
221 double sigma = myConfig.fScattering;
222 for (i = 0; i < pParticleSystem->iNbParticles; i ++)
223 {
224 p = &(pParticleSystem->pParticles[i]);
225
226 p->x += p->vx;
227 p->y += p->vy;
228 p->color[3] = pData->fAlpha * p->iLife / p->iInitialLife;
229 p->fSizeFactor += p->fResizeSpeed;
230 if (p->iLife > 0)
231 {
232 p->iLife --;
233 if (p->iLife == 0)
234 {
235 int iNumSource = i / myConfig.iNbParticles;
236 p->x = pSourceCoords[2*iNumSource];
237 p->y = pSourceCoords[2*iNumSource+1];
238
239 p->vx = sigma * (2 * g_random_double () - 1) * dt / myConfig.iParticleLifeTime;
240 p->vy = sigma * (2 * g_random_double () - 1) * dt / myConfig.iParticleLifeTime;
241
242 p->color[3] = pData->fAlpha;
243 p->fSizeFactor = 1.;
244
245 p->iLife = g_random_int_range (1, p->iInitialLife+1);
246 }
247 }
248 }
249 }
250
cd_show_mouse_free_data(gpointer pUserData,GldiContainer * pContainer)251 gboolean cd_show_mouse_free_data (gpointer pUserData, GldiContainer *pContainer)
252 {
253 cd_message ("");
254 CDShowMouseData *pData = CD_APPLET_GET_MY_CONTAINER_DATA (pContainer);
255 if (pData == NULL)
256 return GLDI_NOTIFICATION_LET_PASS;
257
258 cairo_dock_free_particle_system (pData->pSystem);
259 g_free (pData);
260 CD_APPLET_SET_MY_CONTAINER_DATA (pContainer, NULL);
261 return GLDI_NOTIFICATION_LET_PASS;
262 }
263