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-star.h"
26
27 #define cd_icon_effect_load_star_texture(...) CD_APPLET_LOAD_LOCAL_TEXTURE ("star.png")
28
29
init(Icon * pIcon,CairoDock * pDock,double dt,CDIconEffectData * pData)30 static gboolean init (Icon *pIcon, CairoDock *pDock, double dt, CDIconEffectData *pData)
31 {
32 if (pData->pStarSystem != NULL)
33 return TRUE;
34
35 if (myData.iStarTexture == 0)
36 myData.iStarTexture = cd_icon_effect_load_star_texture ();
37
38 double fMaxScale = 1. + myIconsParam.fAmplitude * pDock->fMagnitudeMax;
39 CairoParticleSystem *pParticleSystem = cairo_dock_create_particle_system (myConfig.iNbStarParticles, myData.iStarTexture, pIcon->fWidth * pIcon->fScale, pIcon->fHeight * fMaxScale);
40 g_return_val_if_fail (pParticleSystem != NULL, FALSE);
41 pParticleSystem->dt = dt;
42 pParticleSystem->bAddLuminance = TRUE;
43
44 static double a = .4;
45 double r = myConfig.iStarParticleSize;
46 double fBlend;
47 CairoParticle *p;
48 int i;
49 for (i = 0; i < myConfig.iNbStarParticles; i ++)
50 {
51 p = &pParticleSystem->pParticles[i];
52
53 p->x = 2 * g_random_double () - 1;
54 p->y = g_random_double ();
55 p->z = 2 * g_random_double () - 1;
56 p->fWidth = r*(p->z + 1)/2 * g_random_double ();
57 p->fHeight = p->fWidth;
58
59 p->vx = 0.;
60 p->vy = 0.;
61
62 p->iInitialLife = myConfig.iStarDuration / dt;
63 p->iLife = p->iInitialLife * (g_random_double () + a) / (1 + a);
64
65 if (myConfig.bMysticalStars)
66 {
67 p->color[0] = g_random_double ();
68 p->color[1] = g_random_double ();
69 p->color[2] = g_random_double ();
70 }
71 else
72 {
73 fBlend = g_random_double ();
74 p->color[0] = fBlend * myConfig.pStarColor1[0] + (1 - fBlend) * myConfig.pStarColor2[0];
75 p->color[1] = fBlend * myConfig.pStarColor1[1] + (1 - fBlend) * myConfig.pStarColor2[1];
76 p->color[2] = fBlend * myConfig.pStarColor1[2] + (1 - fBlend) * myConfig.pStarColor2[2];
77 }
78 p->color[3] = 0.; // on va gerer nous-mêmes la transparence.
79
80 p->fOscillation = 0.;
81 p->fOmega = 0.;
82
83 p->fSizeFactor = 1.;
84 p->fResizeSpeed = - 1. / myConfig.iStarDuration * dt; // zoom 0 a la fin.
85 }
86
87 pData->pStarSystem = pParticleSystem;
88 return TRUE;
89 }
90
_update_star_system(CairoParticleSystem * pParticleSystem,CairoDockRewindParticleFunc pRewindParticle)91 static gboolean _update_star_system (CairoParticleSystem *pParticleSystem, CairoDockRewindParticleFunc pRewindParticle)
92 {
93 static double a = .4;
94 gboolean bAllParticlesEnded = TRUE;
95 double x;
96 CairoParticle *p;
97 int i;
98 for (i = 0; i < pParticleSystem->iNbParticles; i ++)
99 {
100 p = &(pParticleSystem->pParticles[i]);
101
102 if (p->iLife > a * p->iInitialLife)
103 p->color[3] = 0.;
104 else
105 {
106 x = 1. * p->iLife / p->iInitialLife;
107 p->color[3] = 1 - fabs (x - a/2) / (a/2);
108 }
109
110 p->fSizeFactor += p->fResizeSpeed;
111 if (p->iLife > 0)
112 {
113 p->iLife --;
114 if (pRewindParticle && p->iLife == 0)
115 {
116 pRewindParticle (p, pParticleSystem->dt);
117 }
118 if (bAllParticlesEnded && p->iLife != 0)
119 bAllParticlesEnded = FALSE;
120 }
121 }
122 return ! bAllParticlesEnded;
123 }
124
_rewind_star_particle(CairoParticle * p,double dt)125 static void _rewind_star_particle (CairoParticle *p, double dt)
126 {
127 double a = .2;
128 p->x = 2 * g_random_double () - 1;
129 p->y = g_random_double ();
130 p->fSizeFactor = 1.;
131 p->iInitialLife = myConfig.iStarDuration / dt;
132 p->iLife = p->iInitialLife * (g_random_double () + a) / (1 + a);
133 }
134
update(Icon * pIcon,CairoDock * pDock,gboolean bRepeat,CDIconEffectData * pData)135 static gboolean update (Icon *pIcon, CairoDock *pDock, gboolean bRepeat, CDIconEffectData *pData)
136 {
137 if (pData->pStarSystem == NULL)
138 return FALSE;
139
140 gboolean bContinue = _update_star_system (pData->pStarSystem,
141 (bRepeat ? _rewind_star_particle : NULL));
142 pData->pStarSystem->fWidth = pIcon->fWidth * pIcon->fScale;
143
144 double fMaxScale = 1. + myIconsParam.fAmplitude * pDock->fMagnitudeMax;
145 pData->fAreaWidth = pData->pStarSystem->fWidth + myConfig.iStarParticleSize * pDock->container.fRatio; // demi-largeur des particules a droite et a gauche.
146 pData->fAreaHeight = pIcon->fHeight * fMaxScale + myConfig.iStarParticleSize * pDock->container.fRatio;
147 pData->fBottomGap = myConfig.iStarParticleSize * pDock->container.fRatio / 2;
148
149 return bContinue;
150 }
151
152
render(CDIconEffectData * pData)153 static void render (CDIconEffectData *pData)
154 {
155 if (pData->pStarSystem == NULL)
156 return ;
157
158 cairo_dock_render_particles (pData->pStarSystem);
159 }
160
161
free_effect(CDIconEffectData * pData)162 static void free_effect (CDIconEffectData *pData)
163 {
164 if (pData->pStarSystem != NULL)
165 {
166 cairo_dock_free_particle_system (pData->pStarSystem);
167 pData->pStarSystem = NULL;
168 }
169 }
170
171
cd_icon_effect_register_stars(CDIconEffect * pEffect)172 void cd_icon_effect_register_stars (CDIconEffect *pEffect)
173 {
174 pEffect->init = init;
175 pEffect->update = update;
176 pEffect->render = render;
177 pEffect->free = free_effect;
178 }
179