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