~jroose/cairo-dock-plug-ins/Messaging-Menu-alaric-devel

« back to all changes in this revision

Viewing changes to Cairo-Penguin/src/applet-animation.c

  • Committer: jroose at gmail
  • Date: 2010-11-18 14:43:40 UTC
  • Revision ID: jroose@gmail.com-20101118144340-qvrs0rmanr5lr1mj
Messaging-Menu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-notifications.h"
 
26
#include "applet-theme.h"
 
27
#include "applet-animation.h"
 
28
 
 
29
 
 
30
void penguin_move_in_dock (CairoDockModuleInstance *myApplet)
 
31
{
 
32
        static GdkRectangle area;
 
33
        if (! cairo_dock_animation_will_be_visible (myDock))
 
34
                return ;
 
35
        
 
36
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
37
        g_return_if_fail (pAnimation != NULL);
 
38
        int iPreviousPositionX = myData.iCurrentPositionX, iPreviousPositionY = myData.iCurrentPositionY;
 
39
        
 
40
        Icon *pFirstDrawnIcon = NULL;
 
41
        if (myDock->pFirstDrawnElement != NULL)
 
42
                pFirstDrawnIcon = myDock->pFirstDrawnElement->data;
 
43
        if (pFirstDrawnIcon == NULL && myDock->icons != NULL)
 
44
                pFirstDrawnIcon = myDock->icons->data;
 
45
        int iXMin = (pFirstDrawnIcon != NULL ? pFirstDrawnIcon->fXAtRest : 0);
 
46
        iXMin = 0;
 
47
        int iXMax = iXMin + myDock->fFlatDockWidth;
 
48
        int iHeight = myDock->container.iHeight;
 
49
        
 
50
        penguin_calculate_new_position (myApplet, pAnimation, iXMin, iXMax, iHeight);
 
51
        
 
52
        penguin_advance_to_next_frame (myApplet, pAnimation);
 
53
        
 
54
        if (myDock->container.bIsHorizontal)
 
55
        {
 
56
                area.x = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MIN (iPreviousPositionX, myData.iCurrentPositionX));
 
57
                area.y = myDock->container.iHeight - MAX (iPreviousPositionY, myData.iCurrentPositionY) - pAnimation->iFrameHeight;
 
58
                area.width = abs (iPreviousPositionX - myData.iCurrentPositionX) + pAnimation->iFrameWidth + 1;  // +1 car sinon on a des trainees parfois, pas compris pourquoi :-/
 
59
                area.height = abs (iPreviousPositionY - myData.iCurrentPositionY) + pAnimation->iFrameHeight;
 
60
        }
 
61
        else
 
62
        {
 
63
                if (myDock->container.bDirectionUp)
 
64
                {
 
65
                        if (!g_bUseOpenGL)
 
66
                        {
 
67
                                area.y = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MAX (iPreviousPositionX, myData.iCurrentPositionX));
 
68
                                area.y = myDock->container.iWidth - area.y;
 
69
                        }
 
70
                        else
 
71
                        {
 
72
                                area.y = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MAX (iPreviousPositionX, myData.iCurrentPositionX)) + pAnimation->iFrameWidth;
 
73
                                area.y = myDock->container.iWidth - area.y;
 
74
                        }
 
75
                        area.x = myDock->container.iHeight - MAX (iPreviousPositionY, myData.iCurrentPositionY) - pAnimation->iFrameHeight;
 
76
                }
 
77
                else
 
78
                {
 
79
                        area.y = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MIN (iPreviousPositionX, myData.iCurrentPositionX));
 
80
                        area.x = MAX (iPreviousPositionY, myData.iCurrentPositionY);
 
81
                }
 
82
                area.height = abs (iPreviousPositionX - myData.iCurrentPositionX) + pAnimation->iFrameWidth + 1;  // meme remarque sur le +1.
 
83
                area.width = abs (iPreviousPositionY - myData.iCurrentPositionY) + pAnimation->iFrameHeight;
 
84
        }
 
85
        cairo_dock_redraw_container_area (myContainer, &area);
 
86
}
 
87
 
 
88
static void _penguin_draw_texture (CairoDockModuleInstance *myApplet, PenguinAnimation *pAnimation, double fOffsetX, double fOffsetY, double fScale)
 
89
{
 
90
        g_return_if_fail (pAnimation->iTexture != 0);
 
91
        int iIconWidth, iIconHeight;
 
92
        cairo_dock_get_icon_extent (myIcon, myContainer, &iIconWidth, &iIconHeight);
 
93
        
 
94
        _cairo_dock_enable_texture ();
 
95
        _cairo_dock_set_blend_alpha ();
 
96
        _cairo_dock_set_alpha (1.);
 
97
        
 
98
        glBindTexture (GL_TEXTURE_2D, pAnimation->iTexture);
 
99
        _cairo_dock_apply_current_texture_portion_at_size_with_offset ((double) myData.iCurrentFrame/pAnimation->iNbFrames, 
 
100
                .5*myData.iCurrentDirection,
 
101
                1./pAnimation->iNbFrames,
 
102
                1./pAnimation->iNbDirections,
 
103
                pAnimation->iFrameWidth*fScale,
 
104
                pAnimation->iFrameHeight*fScale,
 
105
                floor (fOffsetX + myData.iCurrentPositionX + .5*pAnimation->iFrameWidth) + .5,
 
106
                floor (fOffsetY + myData.iCurrentPositionY + .5*pAnimation->iFrameHeight*fScale) + .5);
 
107
        _cairo_dock_disable_texture ();
 
108
}
 
109
void penguin_draw_on_dock_opengl (CairoDockModuleInstance *myApplet, CairoContainer *pContainer)
 
110
{
 
111
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
112
        if (pAnimation == NULL)
 
113
                return ;
 
114
        
 
115
        glPushMatrix ();
 
116
        ///glLoadIdentity ();
 
117
        
 
118
        if (! myDock->container.bIsHorizontal)
 
119
        {
 
120
                glTranslatef (myDock->container.iHeight/2, myDock->container.iWidth/2, 0.);
 
121
                glRotatef (myDock->container.bDirectionUp ? 90. : -90., 0., 0., 1.);
 
122
                glTranslatef (- myDock->container.iWidth/2, - myDock->container.iHeight/2, 0.);
 
123
        }
 
124
        _penguin_draw_texture (myApplet, pAnimation, (myDock->container.iWidth - myDock->fFlatDockWidth) * .5, 0., 1.);
 
125
        
 
126
        glPopMatrix ();
 
127
}
 
128
 
 
129
void penguin_draw_on_dock (CairoDockModuleInstance *myApplet, CairoContainer *pContainer, cairo_t *pCairoContext)
 
130
{
 
131
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
132
        if (pAnimation == NULL)
 
133
                return ;
 
134
        
 
135
        g_return_if_fail (pAnimation->pSurfaces != NULL);
 
136
        cairo_surface_t *pSurface = pAnimation->pSurfaces[myData.iCurrentDirection][myData.iCurrentFrame];
 
137
        
 
138
        cairo_save (pCairoContext);
 
139
        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
 
140
        
 
141
        if (myDock->container.bIsHorizontal)
 
142
        {
 
143
                cairo_translate (pCairoContext, floor ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + myData.iCurrentPositionX), myDock->container.iHeight - myData.iCurrentPositionY - pAnimation->iFrameHeight);
 
144
                cairo_set_source_surface (pCairoContext, pSurface, 0.0, 0.0);
 
145
                cairo_paint (pCairoContext);
 
146
        }
 
147
        else
 
148
        {
 
149
                if (myDock->container.bDirectionUp)
 
150
                        cairo_translate (pCairoContext,
 
151
                                myDock->container.iHeight - myData.iCurrentPositionY - pAnimation->iFrameHeight,
 
152
                                floor (myDock->container.iWidth - (.5*(myDock->container.iWidth - myDock->fFlatDockWidth) + myData.iCurrentPositionX)));
 
153
                else
 
154
                        cairo_translate (pCairoContext,
 
155
                                myData.iCurrentPositionY,
 
156
                                floor (.5*(myDock->container.iWidth - myDock->fFlatDockWidth) + myData.iCurrentPositionX));
 
157
                cairo_dock_draw_surface (pCairoContext, pSurface, pAnimation->iFrameWidth, pAnimation->iFrameHeight, myDock->container.bDirectionUp, myDock->container.bIsHorizontal, 1.);
 
158
        }
 
159
        
 
160
        cairo_restore (pCairoContext);
 
161
}
 
162
gboolean penguin_render_on_container (CairoDockModuleInstance *myApplet, CairoContainer *pContainer, cairo_t *pCairoContext)
 
163
{
 
164
        if (pContainer != myContainer)
 
165
                return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
166
        if (! cairo_dock_animation_will_be_visible (myDock))
 
167
                return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
168
        
 
169
        if (pCairoContext != NULL)
 
170
                penguin_draw_on_dock (myApplet, pContainer, pCairoContext);
 
171
        else
 
172
                penguin_draw_on_dock_opengl (myApplet, pContainer);
 
173
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
174
}
 
175
 
 
176
 
 
177
 
 
178
void penguin_move_in_icon (CairoDockModuleInstance *myApplet)
 
179
{
 
180
        if (! cairo_dock_animation_will_be_visible (myDock))
 
181
                return ;
 
182
        
 
183
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
184
        g_return_if_fail (pAnimation != NULL);
 
185
        
 
186
        double fScale = (pAnimation->iNbFrames > 1 || pAnimation->iSpeed != 0 || pAnimation->iAcceleration != 0 ? myIcon->fScale : 1.);  // s'il est a l'arret on le met a la taille de l'icone au repos.
 
187
        int iWidth = myIcon->fWidth / myDock->container.fRatio * fScale;
 
188
        int iHeight = myIcon->fHeight / myDock->container.fRatio * fScale;
 
189
        int iXMin = - iWidth / 2;
 
190
        int iXMax = - iXMin;
 
191
        
 
192
        penguin_calculate_new_position (myApplet, pAnimation, iXMin, iXMax, iHeight);
 
193
        
 
194
        penguin_advance_to_next_frame (myApplet, pAnimation);
 
195
        
 
196
        if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
 
197
        {
 
198
                CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN ();
 
199
                
 
200
                int iIconWidth, iIconHeight;
 
201
                cairo_dock_get_icon_extent (myIcon, myContainer, &iIconWidth, &iIconHeight);
 
202
                
 
203
                g_return_if_fail (pAnimation->iTexture != 0);
 
204
                double f = (1 + g_fAmplitude) / fScale;
 
205
                double x, y;  // centre du pingouin, en coordonnées absolues.
 
206
                x = myData.iCurrentPositionX - iXMin - iIconWidth/2 + pAnimation->iFrameWidth/2*f;
 
207
                y = myData.iCurrentPositionY + pAnimation->iFrameHeight/2*f;
 
208
                
 
209
                _cairo_dock_enable_texture ();
 
210
                _cairo_dock_set_blend_alpha ();
 
211
                _cairo_dock_set_alpha (1.);
 
212
                
 
213
                glBindTexture (GL_TEXTURE_2D, pAnimation->iTexture);
 
214
                _cairo_dock_apply_current_texture_portion_at_size_with_offset (1.*myData.iCurrentFrame/pAnimation->iNbFrames, 
 
215
                        .5*myData.iCurrentDirection, 1./pAnimation->iNbFrames, 1./pAnimation->iNbDirections,
 
216
                        pAnimation->iFrameWidth*f, pAnimation->iFrameHeight*f,
 
217
                        x, - iIconHeight/2 + y);
 
218
                _cairo_dock_disable_texture ();
 
219
                
 
220
                CD_APPLET_FINISH_DRAWING_MY_ICON;
 
221
        }
 
222
        else
 
223
        {
 
224
                g_return_if_fail (pAnimation->pSurfaces != NULL);
 
225
                cairo_surface_t *pSurface = pAnimation->pSurfaces[myData.iCurrentDirection][myData.iCurrentFrame];
 
226
                g_return_if_fail (pSurface != NULL);
 
227
                
 
228
                //\________________ On efface l'ancienne image.
 
229
                cairo_set_source_rgba (myDrawContext, 0.0, 0.0, 0.0, 0.0);
 
230
                cairo_set_operator (myDrawContext, CAIRO_OPERATOR_SOURCE);
 
231
                cairo_paint (myDrawContext);
 
232
                cairo_set_operator (myDrawContext, CAIRO_OPERATOR_OVER);
 
233
                
 
234
                //\________________ On applique la nouvelle image.
 
235
                if (pSurface != NULL)
 
236
                {
 
237
                        cairo_save (myDrawContext);
 
238
                        cairo_scale (myDrawContext, (1 + g_fAmplitude) / fScale, (1 + g_fAmplitude) / fScale);
 
239
                        cairo_set_source_surface (
 
240
                                myDrawContext,
 
241
                                pSurface,
 
242
                                iXMax + myData.iCurrentPositionX,
 
243
                                iHeight - myData.iCurrentPositionY - pAnimation->iFrameHeight);
 
244
                        cairo_paint (myDrawContext);
 
245
                        cairo_restore (myDrawContext);
 
246
                }
 
247
                
 
248
                //\________________ les reflets.
 
249
                CD_APPLET_UPDATE_REFLECT_ON_MY_ICON;
 
250
        }
 
251
        
 
252
        CD_APPLET_REDRAW_MY_ICON;
 
253
}
 
254
 
 
255
 
 
256
 
 
257
void penguin_calculate_new_position (CairoDockModuleInstance *myApplet, PenguinAnimation *pAnimation, int iXMin, int iXMax, int iHeight)
 
258
{
 
259
        //\________________ On calule la nouvelle vitesse.
 
260
        if (pAnimation->iAcceleration != 0 && myData.iCurrentSpeed != pAnimation->iTerminalVelocity)
 
261
        {
 
262
                myData.iCurrentSpeed += pAnimation->iAcceleration;
 
263
                if ( (pAnimation->iAcceleration > 0 && myData.iCurrentSpeed > pAnimation->iTerminalVelocity) || (pAnimation->iAcceleration < 0 && myData.iCurrentSpeed < pAnimation->iTerminalVelocity))
 
264
                        myData.iCurrentSpeed = pAnimation->iTerminalVelocity;
 
265
        }
 
266
        
 
267
        //\________________ On calule la nouvelle position.
 
268
        int sens;
 
269
        if (pAnimation->iDirection == PENGUIN_HORIZONTAL)
 
270
        {
 
271
                sens = (myData.iCurrentDirection == 0 ? -1 : 1);
 
272
                myData.iCurrentPositionX += sens * myData.iCurrentSpeed;
 
273
        }
 
274
        else
 
275
        {
 
276
                sens = (pAnimation->iDirection == PENGUIN_UP ? 1 : -1);
 
277
                myData.iCurrentPositionY += sens * myData.iCurrentSpeed;
 
278
        }
 
279
        
 
280
        //\________________ On tient compte des contraintes.
 
281
        if (myData.iCurrentPositionX < iXMin || myData.iCurrentPositionX + pAnimation->iFrameWidth > iXMax)
 
282
        {
 
283
                if (myData.iCurrentPositionX < iXMin)
 
284
                        myData.iCurrentPositionX = iXMin;
 
285
                else
 
286
                        myData.iCurrentPositionX = iXMax - pAnimation->iFrameWidth;
 
287
                if (pAnimation->iDirection == PENGUIN_HORIZONTAL && myConfig.bFree)  // dans l'icone on continue l'animation.
 
288
                {
 
289
                        if (pAnimation->iNbDirections == 2) // on peut repartir dans l'autre sens ou remonter.
 
290
                        {
 
291
                                int iRandom = g_random_int_range (0, 3);
 
292
                                if (iRandom != 0)  // 2 chance sur 3.
 
293
                                {
 
294
                                        myData.iCurrentDirection = 1 - myData.iCurrentDirection;
 
295
                                        //cd_debug ("myData.iCurrentDirection <- %d", myData.iCurrentDirection);
 
296
                                }
 
297
                                else
 
298
                                {
 
299
                                        int iNewAnimation = penguin_choose_go_up_animation (myApplet);
 
300
                                        penguin_set_new_animation (myApplet, iNewAnimation);
 
301
                                }
 
302
                        }
 
303
                        else  // on remonte.
 
304
                        {
 
305
                                int iNewAnimation = penguin_choose_go_up_animation (myApplet);
 
306
                                penguin_set_new_animation (myApplet, iNewAnimation);
 
307
                        }
 
308
                }
 
309
        }
 
310
        
 
311
        if (myData.iCurrentPositionY < (myConfig.bFree ? myBackground.iDockLineWidth + myConfig.iGroundOffset : 0))
 
312
        {
 
313
                myData.iCurrentPositionY = (myConfig.bFree ? myBackground.iDockLineWidth + myConfig.iGroundOffset : 0);
 
314
        }
 
315
        else if (myData.iCurrentPositionY + pAnimation->iFrameHeight > iHeight)
 
316
        {
 
317
                myData.iCurrentPositionY = iHeight - pAnimation->iFrameHeight;
 
318
        }
 
319
}
 
320
 
 
321
 
 
322
 
 
323
void penguin_advance_to_next_frame (CairoDockModuleInstance *myApplet, PenguinAnimation *pAnimation)
 
324
{
 
325
        myData.iCurrentFrame ++;
 
326
        if (myData.iCurrentFrame >= pAnimation->iNbFrames)
 
327
        {
 
328
                myData.iCurrentFrame = 0;
 
329
                myData.iCount ++;
 
330
                
 
331
                if (pAnimation->bEnding)  // c'est une animation de fin, elle ne se joue qu'une seule fois.
 
332
                {
 
333
                        myData.iSleepingTime = 0;
 
334
                        if (! myConfig.bFree)
 
335
                        {
 
336
                                cairo_dock_erase_cairo_context (myDrawContext);  // CD_APPLET_SET_SURFACE_ON_MY_ICON (NULL)
 
337
                                
 
338
                                if (myIcon->pReflectionBuffer != NULL)
 
339
                                {
 
340
                                        cairo_surface_destroy (myIcon->pReflectionBuffer);
 
341
                                        myIcon->pReflectionBuffer = NULL;
 
342
                                }
 
343
                                        if (CAIRO_DOCK_CONTAINER_IS_OPENGL (myContainer))
 
344
                                        cairo_dock_update_icon_texture (myIcon);
 
345
                        }
 
346
                        else  // on reste sur la derniere image de l'animation de fin.
 
347
                        {
 
348
                                myData.iCurrentFrame = pAnimation->iNbFrames - 1;
 
349
                        }
 
350
                        
 
351
                        penguin_start_animating_with_delay (myApplet);
 
352
                }
 
353
                else if (myData.iCount * myData.fFrameDelay * pAnimation->iNbFrames > myConfig.iDelayBetweenChanges)  // il est temps de changer d'animation.
 
354
                {
 
355
                        int iNewAnimation = penguin_choose_next_animation (myApplet, pAnimation);
 
356
                        penguin_set_new_animation (myApplet, iNewAnimation);
 
357
                }
 
358
        }
 
359
}
 
360
 
 
361
 
 
362
 
 
363
int penguin_choose_movement_animation (CairoDockModuleInstance *myApplet)
 
364
{
 
365
        //cd_debug ("");
 
366
        if (myData.iNbMovmentAnimations == 0)
 
367
                return 0;
 
368
        else
 
369
        {
 
370
                int iRandom = g_random_int_range (0, myData.iNbMovmentAnimations);  // [a;b[
 
371
                //g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbMovmentAnimations, myData.pMovmentAnimations[iRandom]);
 
372
                return myData.pMovmentAnimations[iRandom];
 
373
        }
 
374
}
 
375
 
 
376
int penguin_choose_go_up_animation (CairoDockModuleInstance *myApplet)
 
377
{
 
378
        //cd_debug ("");
 
379
        if (myData.iNbGoUpAnimations == 0)
 
380
                return penguin_choose_movement_animation (myApplet);
 
381
        else
 
382
        {
 
383
                int iRandom = g_random_int_range (0, myData.iNbGoUpAnimations);  // [a;b[
 
384
                //g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbGoUpAnimations, myData.pGoUpAnimations[iRandom]);
 
385
                return myData.pGoUpAnimations[iRandom];
 
386
        }
 
387
}
 
388
 
 
389
int penguin_choose_beginning_animation (CairoDockModuleInstance *myApplet)
 
390
{
 
391
        //cd_debug ("");
 
392
        if (myData.iNbBeginningAnimations == 0)
 
393
                return penguin_choose_movement_animation (myApplet);
 
394
        else
 
395
        {
 
396
                int iRandom = g_random_int_range (0, myData.iNbBeginningAnimations);  // [a;b[
 
397
                //g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbBeginningAnimations, myData.pBeginningAnimations[iRandom]);
 
398
                return myData.pBeginningAnimations[iRandom];
 
399
        }
 
400
}
 
401
 
 
402
int penguin_choose_ending_animation (CairoDockModuleInstance *myApplet)
 
403
{
 
404
        //cd_debug ("");
 
405
        if (myData.iNbEndingAnimations == 0)
 
406
                return penguin_choose_go_up_animation (myApplet);
 
407
        else
 
408
        {
 
409
                int iRandom = g_random_int_range (0, myData.iNbEndingAnimations);  // [a;b[
 
410
                //g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbEndingAnimations, myData.pEndingAnimations[iRandom]);
 
411
                return myData.pEndingAnimations[iRandom];
 
412
        }
 
413
}
 
414
 
 
415
int penguin_choose_resting_animation (CairoDockModuleInstance *myApplet)
 
416
{
 
417
        //cd_debug ("");
 
418
        if (myData.iNbRestAnimations == 0)
 
419
                return penguin_choose_go_up_animation (myApplet);
 
420
        else
 
421
        {
 
422
                int iRandom = g_random_int_range (0, myData.iNbRestAnimations);  // [a;b[
 
423
                //g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbRestAnimations, myData.pRestAnimations[iRandom]);
 
424
                return myData.pRestAnimations[iRandom];
 
425
        }
 
426
}
 
427
 
 
428
int penguin_choose_next_animation (CairoDockModuleInstance *myApplet, PenguinAnimation *pAnimation)
 
429
{
 
430
        //cd_debug ("");
 
431
        int iNewAnimation;
 
432
        if (pAnimation == NULL || pAnimation->bEnding)  // le pingouin est en fin d'animation, on le relance.
 
433
        {
 
434
                iNewAnimation = penguin_choose_beginning_animation (myApplet);
 
435
        }
 
436
        else if (pAnimation->iDirection == PENGUIN_HORIZONTAL)  // le pingouin se deplace.
 
437
        {
 
438
                if (myConfig.bFree)
 
439
                        iNewAnimation = penguin_choose_movement_animation (myApplet);
 
440
                else  // dans l'icone on ne repart pas en haut sur les bords.
 
441
                {
 
442
                        int iRandom = g_random_int_range (0, 3);
 
443
                        if (iRandom == 0)
 
444
                                iNewAnimation = penguin_choose_go_up_animation (myApplet);
 
445
                        else
 
446
                                iNewAnimation = penguin_choose_movement_animation (myApplet);
 
447
                }
 
448
        }
 
449
        else  // le pingouin monte ou descend.
 
450
        {
 
451
                if (pAnimation->iDirection == PENGUIN_UP)  // il monte, on le refait descendre.
 
452
                        iNewAnimation = penguin_choose_beginning_animation (myApplet);
 
453
                else  // il descend, on le fait se deplacer.
 
454
                        iNewAnimation = penguin_choose_movement_animation (myApplet);
 
455
        }
 
456
        return iNewAnimation;
 
457
}
 
458
 
 
459
 
 
460
void penguin_set_new_animation (CairoDockModuleInstance *myApplet, int iNewAnimation)
 
461
{
 
462
        //cd_message ("%s (%d)", __func__, iNewAnimation);
 
463
        PenguinAnimation *pPreviousAnimation = penguin_get_current_animation ();
 
464
        int iPreviousWidth = (pPreviousAnimation != NULL ? pPreviousAnimation->iFrameWidth : 0);
 
465
        int iPreviousHeight = (pPreviousAnimation != NULL ? pPreviousAnimation->iFrameHeight : 0);
 
466
        int iPreviousDirection = (pPreviousAnimation != NULL ? pPreviousAnimation->iDirection : 0);
 
467
        
 
468
        myData.iCurrentAnimation = iNewAnimation;
 
469
        myData.iCurrentFrame = 0;
 
470
        myData.iCount = 0;
 
471
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
472
        if (pAnimation == NULL)
 
473
                return ;
 
474
        myData.iCurrentSpeed = pAnimation->iSpeed;
 
475
        
 
476
        if (pAnimation->pSurfaces == NULL && pAnimation->iTexture == 0)
 
477
        {
 
478
                penguin_load_animation_buffer (pAnimation, myDrawContext, myConfig.fAlpha, CAIRO_DOCK_CONTAINER_IS_OPENGL (myContainer));
 
479
        }
 
480
        
 
481
        if (pAnimation->iDirection == PENGUIN_HORIZONTAL)
 
482
        {
 
483
                if (pAnimation->iNbDirections == 2)
 
484
                        myData.iCurrentDirection = g_random_int_range (0, 2);  // [a;b[
 
485
                else
 
486
                        myData.iCurrentDirection = 0;
 
487
                myData.iCurrentPositionY = (myConfig.bFree ? myBackground.iDockLineWidth + myConfig.iGroundOffset : 0);
 
488
        }
 
489
        else  // la direction reste la meme.
 
490
        {
 
491
                myData.iCurrentDirection = MIN (myData.iCurrentDirection, pAnimation->iNbDirections - 1);
 
492
                if (myData.iCurrentDirection == 1)  // on plaque a droite.
 
493
                        myData.iCurrentPositionX += iPreviousWidth - pAnimation->iFrameWidth;
 
494
                if (pAnimation->iDirection == PENGUIN_DOWN)
 
495
                {
 
496
                        if (myConfig.bFree)
 
497
                                myData.iCurrentPositionY = myContainer->iHeight;
 
498
                        else
 
499
                                myData.iCurrentPositionY = myIcon->fHeight / myDock->container.fRatio * myIcon->fScale;
 
500
                }
 
501
        }
 
502
}
 
503
 
 
504
 
 
505
gboolean penguin_update_container (CairoDockModuleInstance *myApplet, CairoContainer *pContainer, gboolean *bContinueAnimation)
 
506
{
 
507
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
508
        if (pAnimation == NULL || (pAnimation->bEnding && myData.iCount > 0))
 
509
                return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
510
        
 
511
        penguin_move_in_dock (myApplet);
 
512
        *bContinueAnimation = TRUE;
 
513
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
514
}
 
515
 
 
516
gboolean penguin_update_icon (CairoDockModuleInstance *myApplet, Icon *pIcon, CairoContainer *pContainer, gboolean *bContinueAnimation)
 
517
{
 
518
        PenguinAnimation *pAnimation = penguin_get_current_animation ();
 
519
        if (pAnimation == NULL || (pAnimation->bEnding && myData.iCount > 0))
 
520
                return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
521
        
 
522
        penguin_move_in_icon (myApplet);
 
523
        *bContinueAnimation = TRUE;
 
524
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
525
}
 
526
 
 
527
 
 
528
void penguin_start_animating (CairoDockModuleInstance *myApplet)
 
529
{
 
530
        int iNewAnimation = penguin_choose_beginning_animation (myApplet);
 
531
        penguin_set_new_animation (myApplet, iNewAnimation);
 
532
        
 
533
        penguin_remove_notfications();
 
534
        if (myConfig.bFree)
 
535
        {
 
536
                cairo_dock_register_notification_on_object (myContainer, CAIRO_DOCK_UPDATE_DOCK_SLOW, (CairoDockNotificationFunc) penguin_update_container, CAIRO_DOCK_RUN_AFTER, myApplet);
 
537
                cairo_dock_register_notification_on_object (myContainer, CAIRO_DOCK_RENDER_DOCK, (CairoDockNotificationFunc) penguin_render_on_container, CAIRO_DOCK_RUN_AFTER, myApplet);
 
538
        }
 
539
        else
 
540
        {
 
541
                cairo_dock_register_notification_on_object (myIcon, CAIRO_DOCK_UPDATE_ICON_SLOW, (CairoDockNotificationFunc) penguin_update_icon, CAIRO_DOCK_RUN_AFTER, myApplet);
 
542
        }
 
543
}
 
544
 
 
545
static gboolean _penguin_restart_delayed (CairoDockModuleInstance *myApplet)
 
546
{
 
547
        myData.iSidRestartDelayed = 0;
 
548
        penguin_start_animating (myApplet);
 
549
        
 
550
        if (! myData.bHasBeenStarted)
 
551
        {
 
552
                myData.bHasBeenStarted = TRUE;
 
553
                cd_message ("le pingouin demarre pour la 1ere fois");
 
554
                
 
555
                if (myConfig.bFree)  // attention : c'est un hack moyen; il faudrait pouvoir indiquer a cairo-dock de ne pas inserer notre icone...
 
556
                {
 
557
                        cairo_dock_detach_icon_from_dock (myIcon, myDock, myIcons.iSeparateIcons);
 
558
                        cairo_dock_update_dock_size (myDock);
 
559
                }
 
560
                else
 
561
                {
 
562
                        cairo_dock_insert_icon_in_dock (myIcon, myDock, CAIRO_DOCK_UPDATE_DOCK_SIZE, ! CAIRO_DOCK_ANIMATE_ICON);
 
563
                }
 
564
                cairo_dock_launch_animation (myContainer);
 
565
        }
 
566
        
 
567
        return FALSE;
 
568
}
 
569
void penguin_start_animating_with_delay (CairoDockModuleInstance *myApplet)
 
570
{
 
571
        if (myData.iSidRestartDelayed != 0)
 
572
                return ;
 
573
        if (cairo_dock_is_loading ())
 
574
        {
 
575
                myData.iSidRestartDelayed = g_timeout_add_seconds (2, (GSourceFunc) _penguin_restart_delayed, (gpointer) myApplet);  // priorite au chargement du dock, on demarrera plus tard.
 
576
        }
 
577
        else
 
578
        {
 
579
                myData.iSidRestartDelayed = g_timeout_add_seconds (1, (GSourceFunc) _penguin_restart_delayed, (gpointer) myApplet);  // on est oblige de faire ca, pour detacher l'icone apres que le dock l'ait inseree.
 
580
                //myData.iSidRestartDelayed = g_idle_add ((GSourceFunc) _penguin_restart_delayed, (gpointer) myApplet);  // on est oblige de faire ca, pour detacher l'icone apres que le dock l'ait inseree.
 
581
        }
 
582
}